usr/src/uts/common/inet/tcp/tcp.c
author kais
Sat, 12 Nov 2005 18:58:05 -0800
changeset 898 64b2a371a6bd
parent 766 c521de78a32f
child 1023 c6eef10d42b2
permissions -rw-r--r--
PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy 4931229 Kernel-level SSL proxy
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>
898
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
    97
#include <inet/kssl/ksslapi.h>
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    98
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    99
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   100
 * TCP Notes: aka FireEngine Phase I (PSARC 2002/433)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   101
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   102
 * (Read the detailed design doc in PSARC case directory)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   103
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   104
 * The entire tcp state is contained in tcp_t and conn_t structure
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   105
 * which are allocated in tandem using ipcl_conn_create() and passing
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   106
 * IPCL_CONNTCP as a flag. We use 'conn_ref' and 'conn_lock' to protect
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   107
 * the references on the tcp_t. The tcp_t structure is never compressed
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   108
 * and packets always land on the correct TCP perimeter from the time
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   109
 * eager is created till the time tcp_t dies (as such the old mentat
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   110
 * TCP global queue is not used for detached state and no IPSEC checking
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   111
 * is required). The global queue is still allocated to send out resets
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   112
 * for connection which have no listeners and IP directly calls
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   113
 * tcp_xmit_listeners_reset() which does any policy check.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   114
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   115
 * Protection and Synchronisation mechanism:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   116
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   117
 * The tcp data structure does not use any kind of lock for protecting
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   118
 * its state but instead uses 'squeues' for mutual exclusion from various
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   119
 * read and write side threads. To access a tcp member, the thread should
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   120
 * always be behind squeue (via squeue_enter, squeue_enter_nodrain, or
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   121
 * squeue_fill). Since the squeues allow a direct function call, caller
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   122
 * can pass any tcp function having prototype of edesc_t as argument
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   123
 * (different from traditional STREAMs model where packets come in only
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   124
 * designated entry points). The list of functions that can be directly
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   125
 * called via squeue are listed before the usual function prototype.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   126
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   127
 * Referencing:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   128
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   129
 * 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
   130
 * tcp structure doesn't disappear when its needed. When the application
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   131
 * creates an outgoing connection or accepts an incoming connection, we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   132
 * start out with 2 references on 'conn_ref'. One for TCP and one for IP.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   133
 * The IP reference is just a symbolic reference since ip_tcpclose()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   134
 * looks at tcp structure after tcp_close_output() returns which could
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   135
 * have dropped the last TCP reference. So as long as the connection is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   136
 * in attached state i.e. !TCP_IS_DETACHED, we have 2 references on the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   137
 * conn_t. The classifier puts its own reference when the connection is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   138
 * inserted in listen or connected hash. Anytime a thread needs to enter
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   139
 * the tcp connection perimeter, it retrieves the conn/tcp from q->ptr
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   140
 * on write side or by doing a classify on read side and then puts a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   141
 * reference on the conn before doing squeue_enter/tryenter/fill. For
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   142
 * read side, the classifier itself puts the reference under fanout lock
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   143
 * to make sure that tcp can't disappear before it gets processed. The
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   144
 * squeue will drop this reference automatically so the called function
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   145
 * doesn't have to do a DEC_REF.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   146
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   147
 * Opening a new connection:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   148
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   149
 * The outgoing connection open is pretty simple. ip_tcpopen() does the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   150
 * work in creating the conn/tcp structure and initializing it. The
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   151
 * squeue assignment is done based on the CPU the application
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   152
 * is running on. So for outbound connections, processing is always done
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   153
 * on application CPU which might be different from the incoming CPU
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   154
 * being interrupted by the NIC. An optimal way would be to figure out
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   155
 * the NIC <-> CPU binding at listen time, and assign the outgoing
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   156
 * connection to the squeue attached to the CPU that will be interrupted
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   157
 * for incoming packets (we know the NIC based on the bind IP address).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   158
 * This might seem like a problem if more data is going out but the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   159
 * fact is that in most cases the transmit is ACK driven transmit where
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   160
 * the outgoing data normally sits on TCP's xmit queue waiting to be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   161
 * transmitted.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   162
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   163
 * Accepting a connection:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   164
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   165
 * This is a more interesting case because of various races involved in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   166
 * establishing a eager in its own perimeter. Read the meta comment on
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   167
 * top of tcp_conn_request(). But briefly, the squeue is picked by
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   168
 * ip_tcp_input()/ip_fanout_tcp_v6() based on the interrupted CPU.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   169
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   170
 * Closing a connection:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   171
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   172
 * The close is fairly straight forward. tcp_close() calls tcp_close_output()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   173
 * via squeue to do the close and mark the tcp as detached if the connection
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   174
 * was in state TCPS_ESTABLISHED or greater. In the later case, TCP keep its
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   175
 * reference but tcp_close() drop IP's reference always. So if tcp was
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   176
 * not killed, it is sitting in time_wait list with 2 reference - 1 for TCP
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   177
 * and 1 because it is in classifier's connected hash. This is the condition
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   178
 * we use to determine that its OK to clean up the tcp outside of squeue
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   179
 * when time wait expires (check the ref under fanout and conn_lock and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   180
 * if it is 2, remove it from fanout hash and kill it).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   181
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   182
 * Although close just drops the necessary references and marks the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   183
 * tcp_detached state, tcp_close needs to know the tcp_detached has been
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   184
 * set (under squeue) before letting the STREAM go away (because a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   185
 * inbound packet might attempt to go up the STREAM while the close
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   186
 * has happened and tcp_detached is not set). So a special lock and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   187
 * flag is used along with a condition variable (tcp_closelock, tcp_closed,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   188
 * and tcp_closecv) to signal tcp_close that tcp_close_out() has marked
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   189
 * tcp_detached.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   190
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   191
 * Special provisions and fast paths:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   192
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   193
 * We make special provision for (AF_INET, SOCK_STREAM) sockets which
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   194
 * can't have 'ipv6_recvpktinfo' set and for these type of sockets, IP
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   195
 * will never send a M_CTL to TCP. As such, ip_tcp_input() which handles
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   196
 * all TCP packets from the wire makes a IPCL_IS_TCP4_CONNECTED_NO_POLICY
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   197
 * check to send packets directly to tcp_rput_data via squeue. Everyone
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   198
 * else comes through tcp_input() on the read side.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   199
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   200
 * We also make special provisions for sockfs by marking tcp_issocket
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   201
 * whenever we have only sockfs on top of TCP. This allows us to skip
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   202
 * putting the tcp in acceptor hash since a sockfs listener can never
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   203
 * become acceptor and also avoid allocating a tcp_t for acceptor STREAM
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   204
 * since eager has already been allocated and the accept now happens
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   205
 * on acceptor STREAM. There is a big blob of comment on top of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   206
 * tcp_conn_request explaining the new accept. When socket is POP'd,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   207
 * sockfs sends us an ioctl to mark the fact and we go back to old
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   208
 * behaviour. Once tcp_issocket is unset, its never set for the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   209
 * life of that connection.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   210
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   211
 * IPsec notes :
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   212
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   213
 * Since a packet is always executed on the correct TCP perimeter
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   214
 * all IPsec processing is defered to IP including checking new
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   215
 * connections and setting IPSEC policies for new connection. The
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   216
 * only exception is tcp_xmit_listeners_reset() which is called
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   217
 * directly from IP and needs to policy check to see if TH_RST
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   218
 * can be sent out.
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
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   222
extern major_t TCP6_MAJ;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   223
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   224
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   225
 * Values for squeue switch:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   226
 * 1: squeue_enter_nodrain
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   227
 * 2: squeue_enter
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   228
 * 3: squeue_fill
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   229
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   230
int tcp_squeue_close = 2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   231
int tcp_squeue_wput = 2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   232
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   233
squeue_func_t tcp_squeue_close_proc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   234
squeue_func_t tcp_squeue_wput_proc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   235
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   236
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   237
 * This controls how tiny a write must be before we try to copy it
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   238
 * into the the mblk on the tail of the transmit queue.  Not much
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   239
 * speedup is observed for values larger than sixteen.  Zero will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   240
 * disable the optimisation.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   241
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   242
int tcp_tx_pull_len = 16;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   243
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   244
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   245
 * TCP Statistics.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   246
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   247
 * How TCP statistics work.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   248
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   249
 * There are two types of statistics invoked by two macros.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   250
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   251
 * TCP_STAT(name) does non-atomic increment of a named stat counter. It is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   252
 * supposed to be used in non MT-hot paths of the code.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   253
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   254
 * TCP_DBGSTAT(name) does atomic increment of a named stat counter. It is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   255
 * supposed to be used for DEBUG purposes and may be used on a hot path.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   256
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   257
 * Both TCP_STAT and TCP_DBGSTAT counters are available using kstat
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   258
 * (use "kstat tcp" to get them).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   259
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   260
 * There is also additional debugging facility that marks tcp_clean_death()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   261
 * instances and saves them in tcp_t structure. It is triggered by
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   262
 * TCP_TAG_CLEAN_DEATH define. Also, there is a global array of counters for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   263
 * tcp_clean_death() calls that counts the number of times each tag was hit. It
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   264
 * is triggered by TCP_CLD_COUNTERS define.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   265
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   266
 * How to add new counters.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   267
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   268
 * 1) Add a field in the tcp_stat structure describing your counter.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   269
 * 2) Add a line in tcp_statistics with the name of the counter.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   270
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   271
 *    IMPORTANT!! - make sure that both are in sync !!
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   272
 * 3) Use either TCP_STAT or TCP_DBGSTAT with the name.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   273
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   274
 * Please avoid using private counters which are not kstat-exported.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   275
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   276
 * TCP_TAG_CLEAN_DEATH set to 1 enables tagging of tcp_clean_death() instances
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   277
 * in tcp_t structure.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   278
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   279
 * TCP_MAX_CLEAN_DEATH_TAG is the maximum number of possible clean death tags.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   280
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   281
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   282
#ifndef TCP_DEBUG_COUNTER
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   283
#ifdef DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   284
#define	TCP_DEBUG_COUNTER 1
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   285
#else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   286
#define	TCP_DEBUG_COUNTER 0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   287
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   288
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   289
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
   290
#define	TCP_CLD_COUNTERS 0
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   291
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   292
#define	TCP_TAG_CLEAN_DEATH 1
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   293
#define	TCP_MAX_CLEAN_DEATH_TAG 32
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   294
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   295
#ifdef lint
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   296
static int _lint_dummy_;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   297
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   298
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   299
#if TCP_CLD_COUNTERS
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   300
static uint_t tcp_clean_death_stat[TCP_MAX_CLEAN_DEATH_TAG];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   301
#define	TCP_CLD_STAT(x) tcp_clean_death_stat[x]++
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   302
#elif defined(lint)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   303
#define	TCP_CLD_STAT(x) ASSERT(_lint_dummy_ == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   304
#else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   305
#define	TCP_CLD_STAT(x)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   306
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   307
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   308
#if TCP_DEBUG_COUNTER
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   309
#define	TCP_DBGSTAT(x) atomic_add_64(&(tcp_statistics.x.value.ui64), 1)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   310
#elif defined(lint)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   311
#define	TCP_DBGSTAT(x) ASSERT(_lint_dummy_ == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   312
#else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   313
#define	TCP_DBGSTAT(x)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   314
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   315
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
   316
tcp_stat_t tcp_statistics = {
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   317
	{ "tcp_time_wait",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   318
	{ "tcp_time_wait_syn",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   319
	{ "tcp_time_wait_success",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   320
	{ "tcp_time_wait_fail",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   321
	{ "tcp_reinput_syn",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   322
	{ "tcp_ip_output",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   323
	{ "tcp_detach_non_time_wait",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   324
	{ "tcp_detach_time_wait",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   325
	{ "tcp_time_wait_reap",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   326
	{ "tcp_clean_death_nondetached",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   327
	{ "tcp_reinit_calls",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   328
	{ "tcp_eager_err1",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   329
	{ "tcp_eager_err2",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   330
	{ "tcp_eager_blowoff_calls",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   331
	{ "tcp_eager_blowoff_q",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   332
	{ "tcp_eager_blowoff_q0",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   333
	{ "tcp_not_hard_bound",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   334
	{ "tcp_no_listener",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   335
	{ "tcp_found_eager",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   336
	{ "tcp_wrong_queue",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   337
	{ "tcp_found_eager_binding1",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   338
	{ "tcp_found_eager_bound1",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   339
	{ "tcp_eager_has_listener1",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   340
	{ "tcp_open_alloc",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   341
	{ "tcp_open_detached_alloc",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   342
	{ "tcp_rput_time_wait",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   343
	{ "tcp_listendrop",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   344
	{ "tcp_listendropq0",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   345
	{ "tcp_wrong_rq",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   346
	{ "tcp_rsrv_calls",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   347
	{ "tcp_eagerfree2",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   348
	{ "tcp_eagerfree3",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   349
	{ "tcp_eagerfree4",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   350
	{ "tcp_eagerfree5",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   351
	{ "tcp_timewait_syn_fail",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   352
	{ "tcp_listen_badflags",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   353
	{ "tcp_timeout_calls",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   354
	{ "tcp_timeout_cached_alloc",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   355
	{ "tcp_timeout_cancel_reqs",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   356
	{ "tcp_timeout_canceled",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   357
	{ "tcp_timermp_alloced",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   358
	{ "tcp_timermp_freed",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   359
	{ "tcp_timermp_allocfail",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   360
	{ "tcp_timermp_allocdblfail",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   361
	{ "tcp_push_timer_cnt",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   362
	{ "tcp_ack_timer_cnt",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   363
	{ "tcp_ire_null1",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   364
	{ "tcp_ire_null",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   365
	{ "tcp_ip_send",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   366
	{ "tcp_ip_ire_send",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   367
	{ "tcp_wsrv_called",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   368
	{ "tcp_flwctl_on",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   369
	{ "tcp_timer_fire_early",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   370
	{ "tcp_timer_fire_miss",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   371
	{ "tcp_freelist_cleanup",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   372
	{ "tcp_rput_v6_error",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   373
	{ "tcp_out_sw_cksum",		KSTAT_DATA_UINT64 },
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
   374
	{ "tcp_out_sw_cksum_bytes",	KSTAT_DATA_UINT64 },
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   375
	{ "tcp_zcopy_on",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   376
	{ "tcp_zcopy_off",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   377
	{ "tcp_zcopy_backoff",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   378
	{ "tcp_zcopy_disable",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   379
	{ "tcp_mdt_pkt_out",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   380
	{ "tcp_mdt_pkt_out_v4",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   381
	{ "tcp_mdt_pkt_out_v6",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   382
	{ "tcp_mdt_discarded",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   383
	{ "tcp_mdt_conn_halted1",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   384
	{ "tcp_mdt_conn_halted2",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   385
	{ "tcp_mdt_conn_halted3",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   386
	{ "tcp_mdt_conn_resumed1",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   387
	{ "tcp_mdt_conn_resumed2",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   388
	{ "tcp_mdt_legacy_small",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   389
	{ "tcp_mdt_legacy_all",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   390
	{ "tcp_mdt_legacy_ret",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   391
	{ "tcp_mdt_allocfail",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   392
	{ "tcp_mdt_addpdescfail",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   393
	{ "tcp_mdt_allocd",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   394
	{ "tcp_mdt_linked",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   395
	{ "tcp_fusion_flowctl",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   396
	{ "tcp_fusion_backenabled",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   397
	{ "tcp_fusion_urg",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   398
	{ "tcp_fusion_putnext",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   399
	{ "tcp_fusion_unfusable",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   400
	{ "tcp_fusion_aborted",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   401
	{ "tcp_fusion_unqualified",	KSTAT_DATA_UINT64 },
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
   402
	{ "tcp_fusion_rrw_busy",	KSTAT_DATA_UINT64 },
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
   403
	{ "tcp_fusion_rrw_msgcnt",	KSTAT_DATA_UINT64 },
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   404
	{ "tcp_in_ack_unsent_drop",	KSTAT_DATA_UINT64 },
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
   405
	{ "tcp_sock_fallback",		KSTAT_DATA_UINT64 },
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   406
};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   407
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   408
static kstat_t *tcp_kstat;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   409
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   410
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   411
 * Call either ip_output or ip_output_v6. This replaces putnext() calls on the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   412
 * tcp write side.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   413
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   414
#define	CALL_IP_WPUT(connp, q, mp) {					\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   415
	ASSERT(((q)->q_flag & QREADR) == 0);				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   416
	TCP_DBGSTAT(tcp_ip_output);					\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   417
	connp->conn_send(connp, (mp), (q), IP_WPUT);			\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   418
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   419
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   420
/* Macros for timestamp comparisons */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   421
#define	TSTMP_GEQ(a, b)	((int32_t)((a)-(b)) >= 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   422
#define	TSTMP_LT(a, b)	((int32_t)((a)-(b)) < 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   423
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   424
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   425
 * Parameters for TCP Initial Send Sequence number (ISS) generation.  When
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   426
 * tcp_strong_iss is set to 1, which is the default, the ISS is calculated
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   427
 * by adding three components: a time component which grows by 1 every 4096
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   428
 * nanoseconds (versus every 4 microseconds suggested by RFC 793, page 27);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   429
 * a per-connection component which grows by 125000 for every new connection;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   430
 * and an "extra" component that grows by a random amount centered
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   431
 * approximately on 64000.  This causes the the ISS generator to cycle every
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   432
 * 4.89 hours if no TCP connections are made, and faster if connections are
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   433
 * made.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   434
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   435
 * When tcp_strong_iss is set to 0, ISS is calculated by adding two
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   436
 * components: a time component which grows by 250000 every second; and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   437
 * a per-connection component which grows by 125000 for every new connections.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   438
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   439
 * A third method, when tcp_strong_iss is set to 2, for generating ISS is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   440
 * prescribed by Steve Bellovin.  This involves adding time, the 125000 per
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   441
 * connection, and a one-way hash (MD5) of the connection ID <sport, dport,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   442
 * src, dst>, a "truly" random (per RFC 1750) number, and a console-entered
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   443
 * password.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   444
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   445
#define	ISS_INCR	250000
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   446
#define	ISS_NSEC_SHT	12
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   447
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   448
static uint32_t tcp_iss_incr_extra;	/* Incremented for each connection */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   449
static kmutex_t tcp_iss_key_lock;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   450
static MD5_CTX tcp_iss_key;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   451
static sin_t	sin_null;	/* Zero address for quick clears */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   452
static sin6_t	sin6_null;	/* Zero address for quick clears */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   453
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   454
/* Packet dropper for TCP IPsec policy drops. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   455
static ipdropper_t tcp_dropper;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   456
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   457
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   458
 * This implementation follows the 4.3BSD interpretation of the urgent
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   459
 * pointer and not RFC 1122. Switching to RFC 1122 behavior would cause
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   460
 * incompatible changes in protocols like telnet and rlogin.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   461
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   462
#define	TCP_OLD_URP_INTERPRETATION	1
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   463
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   464
#define	TCP_IS_DETACHED_NONEAGER(tcp)	\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   465
	(TCP_IS_DETACHED(tcp) && \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   466
	    (!(tcp)->tcp_hard_binding))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   467
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   468
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   469
 * TCP reassembly macros.  We hide starting and ending sequence numbers in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   470
 * b_next and b_prev of messages on the reassembly queue.  The messages are
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   471
 * chained using b_cont.  These macros are used in tcp_reass() so we don't
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   472
 * have to see the ugly casts and assignments.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   473
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   474
#define	TCP_REASS_SEQ(mp)		((uint32_t)(uintptr_t)((mp)->b_next))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   475
#define	TCP_REASS_SET_SEQ(mp, u)	((mp)->b_next = \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   476
					(mblk_t *)(uintptr_t)(u))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   477
#define	TCP_REASS_END(mp)		((uint32_t)(uintptr_t)((mp)->b_prev))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   478
#define	TCP_REASS_SET_END(mp, u)	((mp)->b_prev = \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   479
					(mblk_t *)(uintptr_t)(u))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   480
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   481
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   482
 * Implementation of TCP Timers.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   483
 * =============================
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   484
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   485
 * INTERFACE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   486
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   487
 * There are two basic functions dealing with tcp timers:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   488
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   489
 *	timeout_id_t	tcp_timeout(connp, func, time)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   490
 * 	clock_t		tcp_timeout_cancel(connp, timeout_id)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   491
 *	TCP_TIMER_RESTART(tcp, intvl)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   492
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   493
 * tcp_timeout() starts a timer for the 'tcp' instance arranging to call 'func'
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   494
 * after 'time' ticks passed. The function called by timeout() must adhere to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   495
 * the same restrictions as a driver soft interrupt handler - it must not sleep
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   496
 * or call other functions that might sleep. The value returned is the opaque
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   497
 * non-zero timeout identifier that can be passed to tcp_timeout_cancel() to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   498
 * cancel the request. The call to tcp_timeout() may fail in which case it
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   499
 * returns zero. This is different from the timeout(9F) function which never
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   500
 * fails.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   501
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   502
 * The call-back function 'func' always receives 'connp' as its single
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   503
 * argument. It is always executed in the squeue corresponding to the tcp
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   504
 * structure. The tcp structure is guaranteed to be present at the time the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   505
 * call-back is called.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   506
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   507
 * NOTE: The call-back function 'func' is never called if tcp is in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   508
 * 	the TCPS_CLOSED state.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   509
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   510
 * tcp_timeout_cancel() attempts to cancel a pending tcp_timeout()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   511
 * request. locks acquired by the call-back routine should not be held across
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   512
 * the call to tcp_timeout_cancel() or a deadlock may result.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   513
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   514
 * tcp_timeout_cancel() returns -1 if it can not cancel the timeout request.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   515
 * Otherwise, it returns an integer value greater than or equal to 0. In
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   516
 * particular, if the call-back function is already placed on the squeue, it can
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   517
 * not be canceled.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   518
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   519
 * NOTE: both tcp_timeout() and tcp_timeout_cancel() should always be called
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   520
 * 	within squeue context corresponding to the tcp instance. Since the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   521
 *	call-back is also called via the same squeue, there are no race
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   522
 *	conditions described in untimeout(9F) manual page since all calls are
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   523
 *	strictly serialized.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   524
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   525
 *      TCP_TIMER_RESTART() is a macro that attempts to cancel a pending timeout
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   526
 *	stored in tcp_timer_tid and starts a new one using
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   527
 *	MSEC_TO_TICK(intvl). It always uses tcp_timer() function as a call-back
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   528
 *	and stores the return value of tcp_timeout() in the tcp->tcp_timer_tid
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   529
 *	field.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   530
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   531
 * NOTE: since the timeout cancellation is not guaranteed, the cancelled
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   532
 *	call-back may still be called, so it is possible tcp_timer() will be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   533
 *	called several times. This should not be a problem since tcp_timer()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   534
 *	should always check the tcp instance state.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   535
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   536
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   537
 * IMPLEMENTATION:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   538
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   539
 * TCP timers are implemented using three-stage process. The call to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   540
 * tcp_timeout() uses timeout(9F) function to call tcp_timer_callback() function
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   541
 * when the timer expires. The tcp_timer_callback() arranges the call of the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   542
 * tcp_timer_handler() function via squeue corresponding to the tcp
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   543
 * instance. The tcp_timer_handler() calls actual requested timeout call-back
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   544
 * and passes tcp instance as an argument to it. Information is passed between
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   545
 * stages using the tcp_timer_t structure which contains the connp pointer, the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   546
 * tcp call-back to call and the timeout id returned by the timeout(9F).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   547
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   548
 * 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
   549
 * 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
   550
 * mblk points to the beginning of tcp_timer_t structure. The tcp_timeout()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   551
 * returns the pointer to this mblk.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   552
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   553
 * The pseudo mblk is allocated from a special tcp_timer_cache kmem cache. It
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   554
 * looks like a normal mblk without actual dblk attached to it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   555
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   556
 * To optimize performance each tcp instance holds a small cache of timer
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   557
 * mblocks. In the current implementation it caches up to two timer mblocks per
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   558
 * tcp instance. The cache is preserved over tcp frees and is only freed when
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   559
 * the whole tcp structure is destroyed by its kmem destructor. Since all tcp
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   560
 * timer processing happens on a corresponding squeue, the cache manipulation
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   561
 * does not require any locks. Experiments show that majority of timer mblocks
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   562
 * allocations are satisfied from the tcp cache and do not involve kmem calls.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   563
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   564
 * The tcp_timeout() places a refhold on the connp instance which guarantees
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   565
 * that it will be present at the time the call-back function fires. The
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   566
 * tcp_timer_handler() drops the reference after calling the call-back, so the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   567
 * call-back function does not need to manipulate the references explicitly.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   568
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   569
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   570
typedef struct tcp_timer_s {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   571
	conn_t	*connp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   572
	void 	(*tcpt_proc)(void *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   573
	timeout_id_t   tcpt_tid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   574
} tcp_timer_t;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   575
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   576
static kmem_cache_t *tcp_timercache;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   577
kmem_cache_t	*tcp_sack_info_cache;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   578
kmem_cache_t	*tcp_iphc_cache;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   579
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   580
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   581
 * For scalability, we must not run a timer for every TCP connection
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   582
 * in TIME_WAIT state.  To see why, consider (for time wait interval of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   583
 * 4 minutes):
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   584
 *	1000 connections/sec * 240 seconds/time wait = 240,000 active conn's
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   585
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   586
 * This list is ordered by time, so you need only delete from the head
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   587
 * until you get to entries which aren't old enough to delete yet.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   588
 * The list consists of only the detached TIME_WAIT connections.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   589
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   590
 * Note that the timer (tcp_time_wait_expire) is started when the tcp_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   591
 * becomes detached TIME_WAIT (either by changing the state and already
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   592
 * being detached or the other way around). This means that the TIME_WAIT
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   593
 * state can be extended (up to doubled) if the connection doesn't become
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   594
 * detached for a long time.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   595
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   596
 * The list manipulations (including tcp_time_wait_next/prev)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   597
 * are protected by the tcp_time_wait_lock. The content of the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   598
 * detached TIME_WAIT connections is protected by the normal perimeters.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   599
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   600
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   601
typedef struct tcp_squeue_priv_s {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   602
	kmutex_t	tcp_time_wait_lock;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   603
				/* Protects the next 3 globals */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   604
	timeout_id_t	tcp_time_wait_tid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   605
	tcp_t		*tcp_time_wait_head;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   606
	tcp_t		*tcp_time_wait_tail;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   607
	tcp_t		*tcp_free_list;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   608
} tcp_squeue_priv_t;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   609
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   610
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   611
 * TCP_TIME_WAIT_DELAY governs how often the time_wait_collector runs.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   612
 * Running it every 5 seconds seems to give the best results.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   613
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   614
#define	TCP_TIME_WAIT_DELAY drv_usectohz(5000000)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   615
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   616
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   617
#define	TCP_XMIT_LOWATER	4096
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   618
#define	TCP_XMIT_HIWATER	49152
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   619
#define	TCP_RECV_LOWATER	2048
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   620
#define	TCP_RECV_HIWATER	49152
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   621
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   622
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   623
 *  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
   624
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   625
#define	PAWS_TIMEOUT	((clock_t)(24*24*60*60*hz))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   626
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   627
#define	TIDUSZ	4096	/* transport interface data unit size */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   628
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   629
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   630
 * 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
   631
 * hashing.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   632
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   633
#define	TCP_BIND_FANOUT_SIZE	512
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   634
#define	TCP_BIND_HASH(lport) (ntohs(lport) & (TCP_BIND_FANOUT_SIZE - 1))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   635
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   636
 * 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
   637
 * hashing.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   638
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   639
#define	TCP_FANOUT_SIZE		256
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   640
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   641
#ifdef	_ILP32
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   642
#define	TCP_ACCEPTOR_HASH(accid)					\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   643
		(((uint_t)(accid) >> 8) & (TCP_FANOUT_SIZE - 1))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   644
#else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   645
#define	TCP_ACCEPTOR_HASH(accid)					\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   646
		((uint_t)(accid) & (TCP_FANOUT_SIZE - 1))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   647
#endif	/* _ILP32 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   648
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   649
#define	IP_ADDR_CACHE_SIZE	2048
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   650
#define	IP_ADDR_CACHE_HASH(faddr)					\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   651
	(ntohl(faddr) & (IP_ADDR_CACHE_SIZE -1))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   652
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   653
/* Hash for HSPs uses all 32 bits, since both networks and hosts are in table */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   654
#define	TCP_HSP_HASH_SIZE 256
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   655
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   656
#define	TCP_HSP_HASH(addr)					\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   657
	(((addr>>24) ^ (addr >>16) ^			\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   658
	    (addr>>8) ^ (addr)) % TCP_HSP_HASH_SIZE)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   659
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   660
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   661
 * TCP options struct returned from tcp_parse_options.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   662
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   663
typedef struct tcp_opt_s {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   664
	uint32_t	tcp_opt_mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   665
	uint32_t	tcp_opt_wscale;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   666
	uint32_t	tcp_opt_ts_val;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   667
	uint32_t	tcp_opt_ts_ecr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   668
	tcp_t		*tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   669
} tcp_opt_t;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   670
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   671
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   672
 * RFC1323-recommended phrasing of TSTAMP option, for easier parsing
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   673
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   674
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   675
#ifdef _BIG_ENDIAN
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   676
#define	TCPOPT_NOP_NOP_TSTAMP ((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   677
	(TCPOPT_TSTAMP << 8) | 10)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   678
#else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   679
#define	TCPOPT_NOP_NOP_TSTAMP ((10 << 24) | (TCPOPT_TSTAMP << 16) | \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   680
	(TCPOPT_NOP << 8) | TCPOPT_NOP)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   681
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   682
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   683
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   684
 * Flags returned from tcp_parse_options.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   685
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   686
#define	TCP_OPT_MSS_PRESENT	1
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   687
#define	TCP_OPT_WSCALE_PRESENT	2
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   688
#define	TCP_OPT_TSTAMP_PRESENT	4
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   689
#define	TCP_OPT_SACK_OK_PRESENT	8
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   690
#define	TCP_OPT_SACK_PRESENT	16
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   691
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   692
/* TCP option length */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   693
#define	TCPOPT_NOP_LEN		1
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   694
#define	TCPOPT_MAXSEG_LEN	4
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   695
#define	TCPOPT_WS_LEN		3
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   696
#define	TCPOPT_REAL_WS_LEN	(TCPOPT_WS_LEN+1)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   697
#define	TCPOPT_TSTAMP_LEN	10
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   698
#define	TCPOPT_REAL_TS_LEN	(TCPOPT_TSTAMP_LEN+2)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   699
#define	TCPOPT_SACK_OK_LEN	2
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   700
#define	TCPOPT_REAL_SACK_OK_LEN	(TCPOPT_SACK_OK_LEN+2)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   701
#define	TCPOPT_REAL_SACK_LEN	4
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   702
#define	TCPOPT_MAX_SACK_LEN	36
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   703
#define	TCPOPT_HEADER_LEN	2
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   704
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   705
/* TCP cwnd burst factor. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   706
#define	TCP_CWND_INFINITE	65535
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   707
#define	TCP_CWND_SS		3
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   708
#define	TCP_CWND_NORMAL		5
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   709
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   710
/* Maximum TCP initial cwin (start/restart). */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   711
#define	TCP_MAX_INIT_CWND	8
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   712
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   713
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   714
 * Initialize cwnd according to RFC 3390.  def_max_init_cwnd is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   715
 * either tcp_slow_start_initial or tcp_slow_start_after idle
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   716
 * depending on the caller.  If the upper layer has not used the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   717
 * TCP_INIT_CWND option to change the initial cwnd, tcp_init_cwnd
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   718
 * should be 0 and we use the formula in RFC 3390 to set tcp_cwnd.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   719
 * If the upper layer has changed set the tcp_init_cwnd, just use
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   720
 * it to calculate the tcp_cwnd.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   721
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   722
#define	SET_TCP_INIT_CWND(tcp, mss, def_max_init_cwnd)			\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   723
{									\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   724
	if ((tcp)->tcp_init_cwnd == 0) {				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   725
		(tcp)->tcp_cwnd = MIN(def_max_init_cwnd * (mss),	\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   726
		    MIN(4 * (mss), MAX(2 * (mss), 4380 / (mss) * (mss)))); \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   727
	} else {							\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   728
		(tcp)->tcp_cwnd = (tcp)->tcp_init_cwnd * (mss);		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   729
	}								\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   730
	tcp->tcp_cwnd_cnt = 0;						\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   731
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   732
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   733
/* TCP Timer control structure */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   734
typedef struct tcpt_s {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   735
	pfv_t	tcpt_pfv;	/* The routine we are to call */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   736
	tcp_t	*tcpt_tcp;	/* The parameter we are to pass in */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   737
} tcpt_t;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   738
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   739
/* Host Specific Parameter structure */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   740
typedef struct tcp_hsp {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   741
	struct tcp_hsp	*tcp_hsp_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   742
	in6_addr_t	tcp_hsp_addr_v6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   743
	in6_addr_t	tcp_hsp_subnet_v6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   744
	uint_t		tcp_hsp_vers;	/* IPV4_VERSION | IPV6_VERSION */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   745
	int32_t		tcp_hsp_sendspace;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   746
	int32_t		tcp_hsp_recvspace;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   747
	int32_t		tcp_hsp_tstamp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   748
} tcp_hsp_t;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   749
#define	tcp_hsp_addr	V4_PART_OF_V6(tcp_hsp_addr_v6)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   750
#define	tcp_hsp_subnet	V4_PART_OF_V6(tcp_hsp_subnet_v6)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   751
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   752
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   753
 * Functions called directly via squeue having a prototype of edesc_t.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   754
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   755
void		tcp_conn_request(void *arg, mblk_t *mp, void *arg2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   756
static void	tcp_wput_nondata(void *arg, mblk_t *mp, void *arg2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   757
void		tcp_accept_finish(void *arg, mblk_t *mp, void *arg2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   758
static void	tcp_wput_ioctl(void *arg, mblk_t *mp, void *arg2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   759
static void	tcp_wput_proto(void *arg, mblk_t *mp, void *arg2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   760
void 		tcp_input(void *arg, mblk_t *mp, void *arg2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   761
void		tcp_rput_data(void *arg, mblk_t *mp, void *arg2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   762
static void	tcp_close_output(void *arg, mblk_t *mp, void *arg2);
898
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
   763
void		tcp_output(void *arg, mblk_t *mp, void *arg2);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   764
static void	tcp_rsrv_input(void *arg, mblk_t *mp, void *arg2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   765
static void	tcp_timer_handler(void *arg, mblk_t *mp, void *arg2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   766
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   767
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   768
/* Prototype for TCP functions */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   769
static void	tcp_random_init(void);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   770
int		tcp_random(void);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   771
static void	tcp_accept(tcp_t *tcp, mblk_t *mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   772
static void	tcp_accept_swap(tcp_t *listener, tcp_t *acceptor,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   773
		    tcp_t *eager);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   774
static int	tcp_adapt_ire(tcp_t *tcp, mblk_t *ire_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   775
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
   776
    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
   777
    boolean_t user_specified);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   778
static void	tcp_closei_local(tcp_t *tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   779
static void	tcp_close_detached(tcp_t *tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   780
static boolean_t tcp_conn_con(tcp_t *tcp, uchar_t *iphdr, tcph_t *tcph,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   781
			mblk_t *idmp, mblk_t **defermp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   782
static void	tcp_connect(tcp_t *tcp, mblk_t *mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   783
static void	tcp_connect_ipv4(tcp_t *tcp, mblk_t *mp, ipaddr_t *dstaddrp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   784
		    in_port_t dstport, uint_t srcid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   785
static void	tcp_connect_ipv6(tcp_t *tcp, mblk_t *mp, in6_addr_t *dstaddrp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   786
		    in_port_t dstport, uint32_t flowinfo, uint_t srcid,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   787
		    uint32_t scope_id);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   788
static int	tcp_clean_death(tcp_t *tcp, int err, uint8_t tag);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   789
static void	tcp_def_q_set(tcp_t *tcp, mblk_t *mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   790
static void	tcp_disconnect(tcp_t *tcp, mblk_t *mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   791
static char	*tcp_display(tcp_t *tcp, char *, char);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   792
static boolean_t tcp_eager_blowoff(tcp_t *listener, t_scalar_t seqnum);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   793
static void	tcp_eager_cleanup(tcp_t *listener, boolean_t q0_only);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   794
static void	tcp_eager_unlink(tcp_t *tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   795
static void	tcp_err_ack(tcp_t *tcp, mblk_t *mp, int tlierr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   796
		    int unixerr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   797
static void	tcp_err_ack_prim(tcp_t *tcp, mblk_t *mp, int primitive,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   798
		    int tlierr, int unixerr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   799
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
   800
		    cred_t *cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   801
static int	tcp_extra_priv_ports_add(queue_t *q, mblk_t *mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   802
		    char *value, caddr_t cp, cred_t *cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   803
static int	tcp_extra_priv_ports_del(queue_t *q, mblk_t *mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   804
		    char *value, caddr_t cp, cred_t *cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   805
static int	tcp_tpistate(tcp_t *tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   806
static void	tcp_bind_hash_insert(tf_t *tf, tcp_t *tcp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   807
    int caller_holds_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   808
static void	tcp_bind_hash_remove(tcp_t *tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   809
static tcp_t	*tcp_acceptor_hash_lookup(t_uscalar_t id);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   810
void		tcp_acceptor_hash_insert(t_uscalar_t id, tcp_t *tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   811
static void	tcp_acceptor_hash_remove(tcp_t *tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   812
static void	tcp_capability_req(tcp_t *tcp, mblk_t *mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   813
static void	tcp_info_req(tcp_t *tcp, mblk_t *mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   814
static void	tcp_addr_req(tcp_t *tcp, mblk_t *mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   815
static void	tcp_addr_req_ipv6(tcp_t *tcp, mblk_t *mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   816
static int	tcp_header_init_ipv4(tcp_t *tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   817
static int	tcp_header_init_ipv6(tcp_t *tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   818
int		tcp_init(tcp_t *tcp, queue_t *q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   819
static int	tcp_init_values(tcp_t *tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   820
static mblk_t	*tcp_ip_advise_mblk(void *addr, int addr_len, ipic_t **ipic);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   821
static mblk_t	*tcp_ip_bind_mp(tcp_t *tcp, t_scalar_t bind_prim,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   822
		    t_scalar_t addr_length);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   823
static void	tcp_ip_ire_mark_advice(tcp_t *tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   824
static void	tcp_ip_notify(tcp_t *tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   825
static mblk_t	*tcp_ire_mp(mblk_t *mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   826
static void	tcp_iss_init(tcp_t *tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   827
static void	tcp_keepalive_killer(void *arg);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   828
static int	tcp_parse_options(tcph_t *tcph, tcp_opt_t *tcpopt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   829
static void	tcp_mss_set(tcp_t *tcp, uint32_t size);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   830
static int	tcp_conprim_opt_process(tcp_t *tcp, mblk_t *mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   831
		    int *do_disconnectp, int *t_errorp, int *sys_errorp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   832
static boolean_t tcp_allow_connopt_set(int level, int name);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   833
int		tcp_opt_default(queue_t *q, int level, int name, uchar_t *ptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   834
int		tcp_opt_get(queue_t *q, int level, int name, uchar_t *ptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   835
static int	tcp_opt_get_user(ipha_t *ipha, uchar_t *ptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   836
int		tcp_opt_set(queue_t *q, uint_t optset_context, int level,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   837
		    int name, uint_t inlen, uchar_t *invalp, uint_t *outlenp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   838
		    uchar_t *outvalp, void *thisdg_attrs, cred_t *cr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   839
		    mblk_t *mblk);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   840
static void	tcp_opt_reverse(tcp_t *tcp, ipha_t *ipha);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   841
static int	tcp_opt_set_header(tcp_t *tcp, boolean_t checkonly,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   842
		    uchar_t *ptr, uint_t len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   843
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
   844
static boolean_t tcp_param_register(tcpparam_t *tcppa, int cnt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   845
static int	tcp_param_set(queue_t *q, mblk_t *mp, char *value,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   846
		    caddr_t cp, cred_t *cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   847
static int	tcp_param_set_aligned(queue_t *q, mblk_t *mp, char *value,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   848
		    caddr_t cp, cred_t *cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   849
static void	tcp_iss_key_init(uint8_t *phrase, int len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   850
static int	tcp_1948_phrase_set(queue_t *q, mblk_t *mp, char *value,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   851
		    caddr_t cp, cred_t *cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   852
static void	tcp_process_shrunk_swnd(tcp_t *tcp, uint32_t shrunk_cnt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   853
static mblk_t	*tcp_reass(tcp_t *tcp, mblk_t *mp, uint32_t start);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   854
static void	tcp_reass_elim_overlap(tcp_t *tcp, mblk_t *mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   855
static void	tcp_reinit(tcp_t *tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   856
static void	tcp_reinit_values(tcp_t *tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   857
static void	tcp_report_item(mblk_t *mp, tcp_t *tcp, int hashval,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   858
		    tcp_t *thisstream, cred_t *cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   859
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   860
static uint_t	tcp_rcv_drain(queue_t *q, tcp_t *tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   861
static void	tcp_sack_rxmit(tcp_t *tcp, uint_t *flags);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   862
static boolean_t tcp_send_rst_chk(void);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   863
static void	tcp_ss_rexmit(tcp_t *tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   864
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
   865
static void	tcp_process_options(tcp_t *, tcph_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   866
static void	tcp_rput_common(tcp_t *tcp, mblk_t *mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   867
static void	tcp_rsrv(queue_t *q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   868
static int	tcp_rwnd_set(tcp_t *tcp, uint32_t rwnd);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   869
static int	tcp_snmp_state(tcp_t *tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   870
static int	tcp_status_report(queue_t *q, mblk_t *mp, caddr_t cp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   871
		    cred_t *cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   872
static int	tcp_bind_hash_report(queue_t *q, mblk_t *mp, caddr_t cp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   873
		    cred_t *cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   874
static int	tcp_listen_hash_report(queue_t *q, mblk_t *mp, caddr_t cp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   875
		    cred_t *cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   876
static int	tcp_conn_hash_report(queue_t *q, mblk_t *mp, caddr_t cp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   877
		    cred_t *cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   878
static int	tcp_acceptor_hash_report(queue_t *q, mblk_t *mp, caddr_t cp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   879
		    cred_t *cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   880
static int	tcp_host_param_set(queue_t *q, mblk_t *mp, char *value,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   881
		    caddr_t cp, cred_t *cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   882
static int	tcp_host_param_set_ipv6(queue_t *q, mblk_t *mp, char *value,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   883
		    caddr_t cp, cred_t *cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   884
static int	tcp_host_param_report(queue_t *q, mblk_t *mp, caddr_t cp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   885
		    cred_t *cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   886
static void	tcp_timer(void *arg);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   887
static void	tcp_timer_callback(void *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   888
static in_port_t tcp_update_next_port(in_port_t port, boolean_t random);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   889
static in_port_t tcp_get_next_priv_port(void);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   890
static void	tcp_wput_sock(queue_t *q, mblk_t *mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   891
void		tcp_wput_accept(queue_t *q, mblk_t *mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   892
static void	tcp_wput_data(tcp_t *tcp, mblk_t *mp, boolean_t urgent);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   893
static void	tcp_wput_flush(tcp_t *tcp, mblk_t *mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   894
static void	tcp_wput_iocdata(tcp_t *tcp, mblk_t *mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   895
static int	tcp_send(queue_t *q, tcp_t *tcp, const int mss,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   896
		    const int tcp_hdr_len, const int tcp_tcp_hdr_len,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   897
		    const int num_sack_blk, int *usable, uint_t *snxt,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   898
		    int *tail_unsent, mblk_t **xmit_tail, mblk_t *local_time,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   899
		    const int mdt_thres);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   900
static int	tcp_multisend(queue_t *q, tcp_t *tcp, const int mss,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   901
		    const int tcp_hdr_len, const int tcp_tcp_hdr_len,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   902
		    const int num_sack_blk, int *usable, uint_t *snxt,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   903
		    int *tail_unsent, mblk_t **xmit_tail, mblk_t *local_time,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   904
		    const int mdt_thres);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   905
static void	tcp_fill_header(tcp_t *tcp, uchar_t *rptr, clock_t now,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   906
		    int num_sack_blk);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   907
static void	tcp_wsrv(queue_t *q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   908
static int	tcp_xmit_end(tcp_t *tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   909
void		tcp_xmit_listeners_reset(mblk_t *mp, uint_t ip_hdr_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   910
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
   911
		    int32_t *offset, mblk_t **end_mp, uint32_t seq,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   912
		    boolean_t sendall, uint32_t *seg_len, boolean_t rexmit);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   913
static void	tcp_ack_timer(void *arg);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   914
static mblk_t	*tcp_ack_mp(tcp_t *tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   915
static void	tcp_xmit_early_reset(char *str, mblk_t *mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   916
		    uint32_t seq, uint32_t ack, int ctl, uint_t ip_hdr_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   917
static void	tcp_xmit_ctl(char *str, tcp_t *tcp, uint32_t seq,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   918
		    uint32_t ack, int ctl);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   919
static tcp_hsp_t *tcp_hsp_lookup(ipaddr_t addr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   920
static tcp_hsp_t *tcp_hsp_lookup_ipv6(in6_addr_t *addr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   921
static int	setmaxps(queue_t *q, int maxpsz);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   922
static void	tcp_set_rto(tcp_t *, time_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   923
static boolean_t tcp_check_policy(tcp_t *, mblk_t *, ipha_t *, ip6_t *,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   924
		    boolean_t, boolean_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   925
static void	tcp_icmp_error_ipv6(tcp_t *tcp, mblk_t *mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   926
		    boolean_t ipsec_mctl);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   927
static boolean_t tcp_cmpbuf(void *a, uint_t alen,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   928
		    boolean_t b_valid, void *b, uint_t blen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   929
static boolean_t tcp_allocbuf(void **dstp, uint_t *dstlenp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   930
		    boolean_t src_valid, void *src, uint_t srclen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   931
static void	tcp_savebuf(void **dstp, uint_t *dstlenp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   932
		    boolean_t src_valid, void *src, uint_t srclen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   933
static mblk_t	*tcp_setsockopt_mp(int level, int cmd,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   934
		    char *opt, int optlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   935
static int	tcp_pkt_set(uchar_t *, uint_t, uchar_t **, uint_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   936
static int	tcp_build_hdrs(queue_t *, tcp_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   937
static void	tcp_time_wait_processing(tcp_t *tcp, mblk_t *mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   938
		    uint32_t seg_seq, uint32_t seg_ack, int seg_len,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   939
		    tcph_t *tcph);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   940
boolean_t	tcp_paws_check(tcp_t *tcp, tcph_t *tcph, tcp_opt_t *tcpoptp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   941
boolean_t	tcp_reserved_port_add(int, in_port_t *, in_port_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   942
boolean_t	tcp_reserved_port_del(in_port_t, in_port_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   943
boolean_t	tcp_reserved_port_check(in_port_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   944
static tcp_t	*tcp_alloc_temp_tcp(in_port_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   945
static int	tcp_reserved_port_list(queue_t *, mblk_t *, caddr_t, cred_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   946
static mblk_t	*tcp_mdt_info_mp(mblk_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   947
static void	tcp_mdt_update(tcp_t *, ill_mdt_capab_t *, boolean_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   948
static int	tcp_mdt_add_attrs(multidata_t *, const mblk_t *,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   949
		    const boolean_t, const uint32_t, const uint32_t,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   950
		    const uint32_t, const uint32_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   951
static void	tcp_multisend_data(tcp_t *, ire_t *, const ill_t *, mblk_t *,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   952
		    const uint_t, const uint_t, boolean_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   953
static void	tcp_send_data(tcp_t *, queue_t *, mblk_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   954
extern mblk_t	*tcp_timermp_alloc(int);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   955
extern void	tcp_timermp_free(tcp_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   956
static void	tcp_timer_free(tcp_t *tcp, mblk_t *mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   957
static void	tcp_stop_lingering(tcp_t *tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   958
static void	tcp_close_linger_timeout(void *arg);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   959
void		tcp_ddi_init(void);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   960
void		tcp_ddi_destroy(void);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   961
static void	tcp_kstat_init(void);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   962
static void	tcp_kstat_fini(void);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   963
static int	tcp_kstat_update(kstat_t *kp, int rw);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   964
void		tcp_reinput(conn_t *connp, mblk_t *mp, squeue_t *sqp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   965
static int	tcp_conn_create_v6(conn_t *lconnp, conn_t *connp, mblk_t *mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   966
			tcph_t *tcph, uint_t ipvers, mblk_t *idmp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   967
static int	tcp_conn_create_v4(conn_t *lconnp, conn_t *connp, ipha_t *ipha,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   968
			tcph_t *tcph, mblk_t *idmp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   969
static squeue_func_t tcp_squeue_switch(int);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   970
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   971
static int	tcp_open(queue_t *, dev_t *, int, int, cred_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   972
static int	tcp_close(queue_t *, int);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   973
static int	tcpclose_accept(queue_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   974
static int	tcp_modclose(queue_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   975
static void	tcp_wput_mod(queue_t *, mblk_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   976
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   977
static void	tcp_squeue_add(squeue_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   978
static boolean_t tcp_zcopy_check(tcp_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   979
static void	tcp_zcopy_notify(tcp_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   980
static mblk_t	*tcp_zcopy_disable(tcp_t *, mblk_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   981
static mblk_t	*tcp_zcopy_backoff(tcp_t *, mblk_t *, int);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   982
static void	tcp_ire_ill_check(tcp_t *, ire_t *, ill_t *, boolean_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   983
898
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
   984
extern void	tcp_kssl_input(tcp_t *, mblk_t *);
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
   985
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   986
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   987
 * Routines related to the TCP_IOC_ABORT_CONN ioctl command.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   988
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   989
 * TCP_IOC_ABORT_CONN is a non-transparent ioctl command used for aborting
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   990
 * TCP connections. To invoke this ioctl, a tcp_ioc_abort_conn_t structure
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   991
 * (defined in tcp.h) needs to be filled in and passed into the kernel
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   992
 * via an I_STR ioctl command (see streamio(7I)). The tcp_ioc_abort_conn_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   993
 * structure contains the four-tuple of a TCP connection and a range of TCP
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   994
 * states (specified by ac_start and ac_end). The use of wildcard addresses
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   995
 * and ports is allowed. Connections with a matching four tuple and a state
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   996
 * within the specified range will be aborted. The valid states for the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   997
 * 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
   998
 * inclusive.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   999
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1000
 * An application which has its connection aborted by this ioctl will receive
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1001
 * an error that is dependent on the connection state at the time of the abort.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1002
 * If the connection state is < TCPS_TIME_WAIT, an application should behave as
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1003
 * though a RST packet has been received.  If the connection state is equal to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1004
 * TCPS_TIME_WAIT, the 2MSL timeout will immediately be canceled by the kernel
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1005
 * and all resources associated with the connection will be freed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1006
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1007
static mblk_t	*tcp_ioctl_abort_build_msg(tcp_ioc_abort_conn_t *, tcp_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1008
static void	tcp_ioctl_abort_dump(tcp_ioc_abort_conn_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1009
static void	tcp_ioctl_abort_handler(tcp_t *, mblk_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1010
static int	tcp_ioctl_abort(tcp_ioc_abort_conn_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1011
static void	tcp_ioctl_abort_conn(queue_t *, mblk_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1012
static int	tcp_ioctl_abort_bucket(tcp_ioc_abort_conn_t *, int, int *,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1013
    boolean_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1014
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1015
static struct module_info tcp_rinfo =  {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  1016
	TCP_MOD_ID, TCP_MOD_NAME, 0, INFPSZ, TCP_RECV_HIWATER, TCP_RECV_LOWATER
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1017
};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1018
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1019
static struct module_info tcp_winfo =  {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  1020
	TCP_MOD_ID, TCP_MOD_NAME, 0, INFPSZ, 127, 16
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1021
};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1022
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1023
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1024
 * Entry points for TCP as a module. It only allows SNMP requests
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1025
 * to pass through.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1026
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1027
struct qinit tcp_mod_rinit = {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  1028
	(pfi_t)putnext, NULL, tcp_open, ip_snmpmod_close, NULL, &tcp_rinfo,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1029
};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1030
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1031
struct qinit tcp_mod_winit = {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  1032
	(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
  1033
	&tcp_rinfo
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1034
};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1035
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1036
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1037
 * Entry points for TCP as a device. The normal case which supports
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1038
 * the TCP functionality.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1039
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1040
struct qinit tcp_rinit = {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1041
	NULL, (pfi_t)tcp_rsrv, tcp_open, tcp_close, NULL, &tcp_rinfo
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1042
};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1043
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1044
struct qinit tcp_winit = {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1045
	(pfi_t)tcp_wput, (pfi_t)tcp_wsrv, NULL, NULL, NULL, &tcp_winfo
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1046
};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1047
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1048
/* Initial entry point for TCP in socket mode. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1049
struct qinit tcp_sock_winit = {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1050
	(pfi_t)tcp_wput_sock, (pfi_t)tcp_wsrv, NULL, NULL, NULL, &tcp_winfo
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1051
};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1052
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1053
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1054
 * Entry points for TCP as a acceptor STREAM opened by sockfs when doing
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1055
 * an accept. Avoid allocating data structures since eager has already
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1056
 * been created.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1057
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1058
struct qinit tcp_acceptor_rinit = {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1059
	NULL, (pfi_t)tcp_rsrv, NULL, tcpclose_accept, NULL, &tcp_winfo
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1060
};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1061
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1062
struct qinit tcp_acceptor_winit = {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1063
	(pfi_t)tcp_wput_accept, NULL, NULL, NULL, NULL, &tcp_winfo
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1064
};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1065
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  1066
/*
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  1067
 * Entry points for TCP loopback (read side only)
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  1068
 */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  1069
struct qinit tcp_loopback_rinit = {
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  1070
	(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
  1071
	&tcp_rinfo, NULL, tcp_fuse_rrw, tcp_fuse_rinfop, STRUIOT_STANDARD
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  1072
};
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  1073
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1074
struct streamtab tcpinfo = {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1075
	&tcp_rinit, &tcp_winit
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1076
};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1077
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1078
extern squeue_func_t tcp_squeue_wput_proc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1079
extern squeue_func_t tcp_squeue_timer_proc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1080
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1081
/* Protected by tcp_g_q_lock */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1082
static queue_t	*tcp_g_q;	/* Default queue used during detached closes */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1083
kmutex_t tcp_g_q_lock;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1084
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1085
/* Protected by tcp_hsp_lock */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1086
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1087
 * XXX The host param mechanism should go away and instead we should use
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1088
 * the metrics associated with the routes to determine the default sndspace
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1089
 * and rcvspace.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1090
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1091
static tcp_hsp_t	**tcp_hsp_hash;	/* Hash table for HSPs */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1092
krwlock_t tcp_hsp_lock;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1093
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1094
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1095
 * Extra privileged ports. In host byte order.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1096
 * Protected by tcp_epriv_port_lock.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1097
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1098
#define	TCP_NUM_EPRIV_PORTS	64
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1099
static int	tcp_g_num_epriv_ports = TCP_NUM_EPRIV_PORTS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1100
static uint16_t	tcp_g_epriv_ports[TCP_NUM_EPRIV_PORTS] = { 2049, 4045 };
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1101
kmutex_t tcp_epriv_port_lock;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1102
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1103
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1104
 * The smallest anonymous port in the priviledged port range which TCP
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1105
 * looks for free port.  Use in the option TCP_ANONPRIVBIND.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1106
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1107
static in_port_t tcp_min_anonpriv_port = 512;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1108
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1109
/* Only modified during _init and _fini thus no locking is needed. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1110
static caddr_t	tcp_g_nd;	/* Head of 'named dispatch' variable list */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1111
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1112
/* Hint not protected by any lock */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1113
static uint_t	tcp_next_port_to_try;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1114
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1115
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1116
/* TCP bind hash list - all tcp_t with state >= BOUND. */
898
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
  1117
tf_t	tcp_bind_fanout[TCP_BIND_FANOUT_SIZE];
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1118
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1119
/* TCP queue hash list - all tcp_t in case they will be an acceptor. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1120
static tf_t	tcp_acceptor_fanout[TCP_FANOUT_SIZE];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1121
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1122
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1123
 * TCP has a private interface for other kernel modules to reserve a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1124
 * port range for them to use.  Once reserved, TCP will not use any ports
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1125
 * in the range.  This interface relies on the TCP_EXCLBIND feature.  If
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1126
 * the semantics of TCP_EXCLBIND is changed, implementation of this interface
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1127
 * has to be verified.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1128
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1129
 * There can be TCP_RESERVED_PORTS_ARRAY_MAX_SIZE port ranges.  Each port
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1130
 * range can cover at most TCP_RESERVED_PORTS_RANGE_MAX ports.  A port
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1131
 * range is [port a, port b] inclusive.  And each port range is between
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1132
 * TCP_LOWESET_RESERVED_PORT and TCP_LARGEST_RESERVED_PORT inclusive.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1133
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1134
 * Note that the default anonymous port range starts from 32768.  There is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1135
 * no port "collision" between that and the reserved port range.  If there
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1136
 * is port collision (because the default smallest anonymous port is lowered
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1137
 * or some apps specifically bind to ports in the reserved port range), the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1138
 * system may not be able to reserve a port range even there are enough
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1139
 * unbound ports as a reserved port range contains consecutive ports .
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1140
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1141
#define	TCP_RESERVED_PORTS_ARRAY_MAX_SIZE	5
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1142
#define	TCP_RESERVED_PORTS_RANGE_MAX		1000
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1143
#define	TCP_SMALLEST_RESERVED_PORT		10240
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1144
#define	TCP_LARGEST_RESERVED_PORT		20480
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1145
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1146
/* Structure to represent those reserved port ranges. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1147
typedef struct tcp_rport_s {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1148
	in_port_t	lo_port;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1149
	in_port_t	hi_port;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1150
	tcp_t		**temp_tcp_array;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1151
} tcp_rport_t;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1152
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1153
/* The reserved port array. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1154
static tcp_rport_t tcp_reserved_port[TCP_RESERVED_PORTS_ARRAY_MAX_SIZE];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1155
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1156
/* Locks to protect the tcp_reserved_ports array. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1157
static krwlock_t tcp_reserved_port_lock;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1158
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1159
/* The number of ranges in the array. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1160
uint32_t tcp_reserved_port_array_size = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1161
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1162
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1163
 * MIB-2 stuff for SNMP
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1164
 * Note: tcpInErrs {tcp 15} is accumulated in ip.c
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1165
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1166
mib2_tcp_t	tcp_mib;	/* SNMP fixed size info */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1167
kstat_t		*tcp_mibkp;	/* kstat exporting tcp_mib data */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1168
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1169
boolean_t tcp_icmp_source_quench = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1170
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1171
 * Following assumes TPI alignment requirements stay along 32 bit
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1172
 * boundaries
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1173
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1174
#define	ROUNDUP32(x) \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1175
	(((x) + (sizeof (int32_t) - 1)) & ~(sizeof (int32_t) - 1))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1176
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1177
/* Template for response to info request. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1178
static struct T_info_ack tcp_g_t_info_ack = {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1179
	T_INFO_ACK,		/* PRIM_type */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1180
	0,			/* TSDU_size */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1181
	T_INFINITE,		/* ETSDU_size */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1182
	T_INVALID,		/* CDATA_size */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1183
	T_INVALID,		/* DDATA_size */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1184
	sizeof (sin_t),		/* ADDR_size */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1185
	0,			/* OPT_size - not initialized here */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1186
	TIDUSZ,			/* TIDU_size */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1187
	T_COTS_ORD,		/* SERV_type */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1188
	TCPS_IDLE,		/* CURRENT_state */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1189
	(XPG4_1|EXPINLINE)	/* PROVIDER_flag */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1190
};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1191
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1192
static struct T_info_ack tcp_g_t_info_ack_v6 = {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1193
	T_INFO_ACK,		/* PRIM_type */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1194
	0,			/* TSDU_size */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1195
	T_INFINITE,		/* ETSDU_size */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1196
	T_INVALID,		/* CDATA_size */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1197
	T_INVALID,		/* DDATA_size */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1198
	sizeof (sin6_t),	/* ADDR_size */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1199
	0,			/* OPT_size - not initialized here */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1200
	TIDUSZ,		/* TIDU_size */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1201
	T_COTS_ORD,		/* SERV_type */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1202
	TCPS_IDLE,		/* CURRENT_state */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1203
	(XPG4_1|EXPINLINE)	/* PROVIDER_flag */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1204
};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1205
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1206
#define	MS	1L
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1207
#define	SECONDS	(1000 * MS)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1208
#define	MINUTES	(60 * SECONDS)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1209
#define	HOURS	(60 * MINUTES)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1210
#define	DAYS	(24 * HOURS)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1211
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1212
#define	PARAM_MAX (~(uint32_t)0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1213
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1214
/* Max size IP datagram is 64k - 1 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1215
#define	TCP_MSS_MAX_IPV4 (IP_MAXPACKET - (sizeof (ipha_t) + sizeof (tcph_t)))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1216
#define	TCP_MSS_MAX_IPV6 (IP_MAXPACKET - (sizeof (ip6_t) + sizeof (tcph_t)))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1217
/* Max of the above */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1218
#define	TCP_MSS_MAX	TCP_MSS_MAX_IPV4
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1219
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1220
/* Largest TCP port number */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1221
#define	TCP_MAX_PORT	(64 * 1024 - 1)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1222
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1223
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1224
 * tcp_wroff_xtra is the extra space in front of TCP/IP header for link
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1225
 * layer header.  It has to be a multiple of 4.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1226
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1227
static tcpparam_t tcp_wroff_xtra_param = { 0, 256, 32, "tcp_wroff_xtra" };
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1228
#define	tcp_wroff_xtra	tcp_wroff_xtra_param.tcp_param_val
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1229
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1230
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1231
 * All of these are alterable, within the min/max values given, at run time.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1232
 * Note that the default value of "tcp_time_wait_interval" is four minutes,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1233
 * per the TCP spec.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1234
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1235
/* BEGIN CSTYLED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1236
tcpparam_t	tcp_param_arr[] = {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1237
 /*min		max		value		name */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1238
 { 1*SECONDS,	10*MINUTES,	1*MINUTES,	"tcp_time_wait_interval"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1239
 { 1,		PARAM_MAX,	128,		"tcp_conn_req_max_q" },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1240
 { 0,		PARAM_MAX,	1024,		"tcp_conn_req_max_q0" },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1241
 { 1,		1024,		1,		"tcp_conn_req_min" },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1242
 { 0*MS,	20*SECONDS,	0*MS,		"tcp_conn_grace_period" },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1243
 { 128,		(1<<30),	1024*1024,	"tcp_cwnd_max" },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1244
 { 0,		10,		0,		"tcp_debug" },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1245
 { 1024,	(32*1024),	1024,		"tcp_smallest_nonpriv_port"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1246
 { 1*SECONDS,	PARAM_MAX,	3*MINUTES,	"tcp_ip_abort_cinterval"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1247
 { 1*SECONDS,	PARAM_MAX,	3*MINUTES,	"tcp_ip_abort_linterval"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1248
 { 500*MS,	PARAM_MAX,	8*MINUTES,	"tcp_ip_abort_interval"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1249
 { 1*SECONDS,	PARAM_MAX,	10*SECONDS,	"tcp_ip_notify_cinterval"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1250
 { 500*MS,	PARAM_MAX,	10*SECONDS,	"tcp_ip_notify_interval"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1251
 { 1,		255,		64,		"tcp_ipv4_ttl"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1252
 { 10*SECONDS,	10*DAYS,	2*HOURS,	"tcp_keepalive_interval"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1253
 { 0,		100,		10,		"tcp_maxpsz_multiplier" },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1254
 { 1,		TCP_MSS_MAX_IPV4, 536,		"tcp_mss_def_ipv4"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1255
 { 1,		TCP_MSS_MAX_IPV4, TCP_MSS_MAX_IPV4, "tcp_mss_max_ipv4"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1256
 { 1,		TCP_MSS_MAX,	108,		"tcp_mss_min"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1257
 { 1,		(64*1024)-1,	(4*1024)-1,	"tcp_naglim_def"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1258
 { 1*MS,	20*SECONDS,	3*SECONDS,	"tcp_rexmit_interval_initial"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1259
 { 1*MS,	2*HOURS,	60*SECONDS,	"tcp_rexmit_interval_max"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1260
 { 1*MS,	2*HOURS,	400*MS,		"tcp_rexmit_interval_min"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1261
 { 1*MS,	1*MINUTES,	100*MS,		"tcp_deferred_ack_interval" },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1262
 { 0,		16,		0,		"tcp_snd_lowat_fraction" },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1263
 { 0,		128000,		0,		"tcp_sth_rcv_hiwat" },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1264
 { 0,		128000,		0,		"tcp_sth_rcv_lowat" },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1265
 { 1,		10000,		3,		"tcp_dupack_fast_retransmit" },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1266
 { 0,		1,		0,		"tcp_ignore_path_mtu" },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1267
 { 1024,	TCP_MAX_PORT,	32*1024,	"tcp_smallest_anon_port"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1268
 { 1024,	TCP_MAX_PORT,	TCP_MAX_PORT,	"tcp_largest_anon_port"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1269
 { TCP_XMIT_LOWATER, (1<<30), TCP_XMIT_HIWATER,"tcp_xmit_hiwat"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1270
 { TCP_XMIT_LOWATER, (1<<30), TCP_XMIT_LOWATER,"tcp_xmit_lowat"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1271
 { TCP_RECV_LOWATER, (1<<30), TCP_RECV_HIWATER,"tcp_recv_hiwat"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1272
 { 1,		65536,		4,		"tcp_recv_hiwat_minmss"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1273
 { 1*SECONDS,	PARAM_MAX,	675*SECONDS,	"tcp_fin_wait_2_flush_interval"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1274
 { 0,		TCP_MSS_MAX,	64,		"tcp_co_min"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1275
 { 8192,	(1<<30),	1024*1024,	"tcp_max_buf"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1276
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1277
 * Question:  What default value should I set for tcp_strong_iss?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1278
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1279
 { 0,		2,		1,		"tcp_strong_iss"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1280
 { 0,		65536,		20,		"tcp_rtt_updates"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1281
 { 0,		1,		1,		"tcp_wscale_always"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1282
 { 0,		1,		0,		"tcp_tstamp_always"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1283
 { 0,		1,		1,		"tcp_tstamp_if_wscale"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1284
 { 0*MS,	2*HOURS,	0*MS,		"tcp_rexmit_interval_extra"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1285
 { 0,		16,		2,		"tcp_deferred_acks_max"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1286
 { 1,		16384,		4,		"tcp_slow_start_after_idle"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1287
 { 1,		4,		4,		"tcp_slow_start_initial"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1288
 { 10*MS,	50*MS,		20*MS,		"tcp_co_timer_interval"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1289
 { 0,		2,		2,		"tcp_sack_permitted"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1290
 { 0,		1,		0,		"tcp_trace"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1291
 { 0,		1,		1,		"tcp_compression_enabled"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1292
 { 0,		IPV6_MAX_HOPS,	IPV6_DEFAULT_HOPS,	"tcp_ipv6_hoplimit"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1293
 { 1,		TCP_MSS_MAX_IPV6, 1220,		"tcp_mss_def_ipv6"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1294
 { 1,		TCP_MSS_MAX_IPV6, TCP_MSS_MAX_IPV6, "tcp_mss_max_ipv6"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1295
 { 0,		1,		0,		"tcp_rev_src_routes"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1296
 { 10*MS,	500*MS,		50*MS,		"tcp_local_dack_interval"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1297
 { 100*MS,	60*SECONDS,	1*SECONDS,	"tcp_ndd_get_info_interval"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1298
 { 0,		16,		8,		"tcp_local_dacks_max"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1299
 { 0,		2,		1,		"tcp_ecn_permitted"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1300
 { 0,		1,		1,		"tcp_rst_sent_rate_enabled"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1301
 { 0,		PARAM_MAX,	40,		"tcp_rst_sent_rate"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1302
 { 0,		100*MS,		50*MS,		"tcp_push_timer_interval"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1303
 { 0,		1,		0,		"tcp_use_smss_as_mss_opt"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1304
 { 0,		PARAM_MAX,	8*MINUTES,	"tcp_keepalive_abort_interval"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1305
};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1306
/* END CSTYLED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1307
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1308
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1309
 * tcp_mdt_hdr_{head,tail}_min are the leading and trailing spaces of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1310
 * each header fragment in the header buffer.  Each parameter value has
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1311
 * to be a multiple of 4 (32-bit aligned).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1312
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1313
static tcpparam_t tcp_mdt_head_param = { 32, 256, 32, "tcp_mdt_hdr_head_min" };
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1314
static tcpparam_t tcp_mdt_tail_param = { 0,  256, 32, "tcp_mdt_hdr_tail_min" };
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1315
#define	tcp_mdt_hdr_head_min	tcp_mdt_head_param.tcp_param_val
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1316
#define	tcp_mdt_hdr_tail_min	tcp_mdt_tail_param.tcp_param_val
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1317
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1318
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1319
 * tcp_mdt_max_pbufs is the upper limit value that tcp uses to figure out
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1320
 * the maximum number of payload buffers associated per Multidata.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1321
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1322
static tcpparam_t tcp_mdt_max_pbufs_param =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1323
	{ 1, MULTIDATA_MAX_PBUFS, MULTIDATA_MAX_PBUFS, "tcp_mdt_max_pbufs" };
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1324
#define	tcp_mdt_max_pbufs	tcp_mdt_max_pbufs_param.tcp_param_val
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1325
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1326
/* Round up the value to the nearest mss. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1327
#define	MSS_ROUNDUP(value, mss)		((((value) - 1) / (mss) + 1) * (mss))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1328
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1329
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1330
 * Set ECN capable transport (ECT) code point in IP header.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1331
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1332
 * Note that there are 2 ECT code points '01' and '10', which are called
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1333
 * ECT(1) and ECT(0) respectively.  Here we follow the original ECT code
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1334
 * point ECT(0) for TCP as described in RFC 2481.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1335
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1336
#define	SET_ECT(tcp, iph) \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1337
	if ((tcp)->tcp_ipversion == IPV4_VERSION) { \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1338
		/* We need to clear the code point first. */ \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1339
		((ipha_t *)(iph))->ipha_type_of_service &= 0xFC; \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1340
		((ipha_t *)(iph))->ipha_type_of_service |= IPH_ECN_ECT0; \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1341
	} else { \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1342
		((ip6_t *)(iph))->ip6_vcf &= htonl(0xFFCFFFFF); \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1343
		((ip6_t *)(iph))->ip6_vcf |= htonl(IPH_ECN_ECT0 << 20); \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1344
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1345
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1346
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1347
 * The format argument to pass to tcp_display().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1348
 * DISP_PORT_ONLY means that the returned string has only port info.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1349
 * DISP_ADDR_AND_PORT means that the returned string also contains the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1350
 * remote and local IP address.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1351
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1352
#define	DISP_PORT_ONLY		1
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1353
#define	DISP_ADDR_AND_PORT	2
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1354
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1355
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1356
 * This controls the rate some ndd info report functions can be used
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1357
 * by non-priviledged users.  It stores the last time such info is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1358
 * requested.  When those report functions are called again, this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1359
 * is checked with the current time and compare with the ndd param
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1360
 * tcp_ndd_get_info_interval.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1361
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1362
static clock_t tcp_last_ndd_get_info_time = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1363
#define	NDD_TOO_QUICK_MSG \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1364
	"ndd get info rate too high for non-priviledged users, try again " \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1365
	"later.\n"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1366
#define	NDD_OUT_OF_BUF_MSG	"<< Out of buffer >>\n"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1367
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1368
#define	IS_VMLOANED_MBLK(mp) \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1369
	(((mp)->b_datap->db_struioflag & STRUIO_ZC) != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1370
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1371
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1372
 * These two variables control the rate for TCP to generate RSTs in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1373
 * response to segments not belonging to any connections.  We limit
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1374
 * TCP to sent out tcp_rst_sent_rate (ndd param) number of RSTs in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1375
 * each 1 second interval.  This is to protect TCP against DoS attack.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1376
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1377
static clock_t tcp_last_rst_intrvl;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1378
static uint32_t tcp_rst_cnt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1379
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1380
/* The number of RST not sent because of the rate limit. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1381
static uint32_t tcp_rst_unsent;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1382
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1383
/* Enable or disable b_cont M_MULTIDATA chaining for MDT. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1384
boolean_t tcp_mdt_chain = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1385
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1386
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1387
 * MDT threshold in the form of effective send MSS multiplier; we take
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1388
 * the MDT path if the amount of unsent data exceeds the threshold value
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1389
 * (default threshold is 1*SMSS).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1390
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1391
uint_t tcp_mdt_smss_threshold = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1392
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1393
uint32_t do_tcpzcopy = 1;		/* 0: disable, 1: enable, 2: force */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1394
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1395
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1396
 * Forces all connections to obey the value of the tcp_maxpsz_multiplier
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1397
 * tunable settable via NDD.  Otherwise, the per-connection behavior is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1398
 * determined dynamically during tcp_adapt_ire(), which is the default.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1399
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1400
boolean_t tcp_static_maxpsz = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1401
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1402
/* If set to 0, pick ephemeral port sequentially; otherwise randomly. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1403
uint32_t tcp_random_anon_port = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1404
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1405
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1406
 * If tcp_drop_ack_unsent_cnt is greater than 0, when TCP receives more
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1407
 * than tcp_drop_ack_unsent_cnt number of ACKs which acknowledge unsent
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1408
 * data, TCP will not respond with an ACK.  RFC 793 requires that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1409
 * TCP responds with an ACK for such a bogus ACK.  By not following
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1410
 * the RFC, we prevent TCP from getting into an ACK storm if somehow
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1411
 * an attacker successfully spoofs an acceptable segment to our
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1412
 * peer; or when our peer is "confused."
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1413
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1414
uint32_t tcp_drop_ack_unsent_cnt = 10;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1415
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1416
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1417
 * Hook functions to enable cluster networking
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1418
 * On non-clustered systems these vectors must always be NULL.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1419
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1420
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1421
void (*cl_inet_listen)(uint8_t protocol, sa_family_t addr_family,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1422
			    uint8_t *laddrp, in_port_t lport) = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1423
void (*cl_inet_unlisten)(uint8_t protocol, sa_family_t addr_family,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1424
			    uint8_t *laddrp, in_port_t lport) = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1425
void (*cl_inet_connect)(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
void (*cl_inet_disconnect)(uint8_t protocol, sa_family_t addr_family,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1429
			    uint8_t *laddrp, in_port_t lport,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1430
			    uint8_t *faddrp, in_port_t fport) = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1431
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1432
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1433
 * The following are defined in ip.c
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1434
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1435
extern int (*cl_inet_isclusterwide)(uint8_t protocol, sa_family_t addr_family,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1436
				uint8_t *laddrp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1437
extern uint32_t (*cl_inet_ipident)(uint8_t protocol, sa_family_t addr_family,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1438
				uint8_t *laddrp, uint8_t *faddrp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1439
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1440
#define	CL_INET_CONNECT(tcp)		{			\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1441
	if (cl_inet_connect != NULL) {				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1442
		/*						\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1443
		 * Running in cluster mode - register active connection	\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1444
		 * information						\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1445
		 */							\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1446
		if ((tcp)->tcp_ipversion == IPV4_VERSION) {		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1447
			if ((tcp)->tcp_ipha->ipha_src != 0) {		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1448
				(*cl_inet_connect)(IPPROTO_TCP, AF_INET,\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1449
				    (uint8_t *)(&((tcp)->tcp_ipha->ipha_src)),\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1450
				    (in_port_t)(tcp)->tcp_lport,	\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1451
				    (uint8_t *)(&((tcp)->tcp_ipha->ipha_dst)),\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1452
				    (in_port_t)(tcp)->tcp_fport);	\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1453
			}						\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1454
		} else {						\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1455
			if (!IN6_IS_ADDR_UNSPECIFIED(			\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1456
			    &(tcp)->tcp_ip6h->ip6_src)) {\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1457
				(*cl_inet_connect)(IPPROTO_TCP, AF_INET6,\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1458
				    (uint8_t *)(&((tcp)->tcp_ip6h->ip6_src)),\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1459
				    (in_port_t)(tcp)->tcp_lport,	\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1460
				    (uint8_t *)(&((tcp)->tcp_ip6h->ip6_dst)),\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1461
				    (in_port_t)(tcp)->tcp_fport);	\
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
	}								\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1465
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1466
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1467
#define	CL_INET_DISCONNECT(tcp)	{				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1468
	if (cl_inet_disconnect != NULL) {				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1469
		/*							\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1470
		 * Running in cluster mode - deregister active		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1471
		 * connection information				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1472
		 */							\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1473
		if ((tcp)->tcp_ipversion == IPV4_VERSION) {		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1474
			if ((tcp)->tcp_ip_src != 0) {			\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1475
				(*cl_inet_disconnect)(IPPROTO_TCP,	\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1476
				    AF_INET,				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1477
				    (uint8_t *)(&((tcp)->tcp_ip_src)),\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1478
				    (in_port_t)(tcp)->tcp_lport,	\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1479
				    (uint8_t *)				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1480
				    (&((tcp)->tcp_ipha->ipha_dst)),\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1481
				    (in_port_t)(tcp)->tcp_fport);	\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1482
			}						\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1483
		} else {						\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1484
			if (!IN6_IS_ADDR_UNSPECIFIED(			\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1485
			    &(tcp)->tcp_ip_src_v6)) {			\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1486
				(*cl_inet_disconnect)(IPPROTO_TCP, AF_INET6,\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1487
				    (uint8_t *)(&((tcp)->tcp_ip_src_v6)),\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1488
				    (in_port_t)(tcp)->tcp_lport,	\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1489
				    (uint8_t *)				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1490
				    (&((tcp)->tcp_ip6h->ip6_dst)),\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1491
				    (in_port_t)(tcp)->tcp_fport);	\
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
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1496
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1497
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1498
 * Cluster networking hook for traversing current connection list.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1499
 * This routine is used to extract the current list of live connections
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1500
 * which must continue to to be dispatched to this node.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1501
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1502
int cl_tcp_walk_list(int (*callback)(cl_tcp_info_t *, void *), void *arg);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1503
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1504
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1505
 * Figure out the value of window scale opton.  Note that the rwnd is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1506
 * ASSUMED to be rounded up to the nearest MSS before the calculation.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1507
 * We cannot find the scale value and then do a round up of tcp_rwnd
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1508
 * because the scale value may not be correct after that.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1509
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1510
 * Set the compiler flag to make this function inline.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1511
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1512
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1513
tcp_set_ws_value(tcp_t *tcp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1514
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1515
	int i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1516
	uint32_t rwnd = tcp->tcp_rwnd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1517
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1518
	for (i = 0; rwnd > TCP_MAXWIN && i < TCP_MAX_WINSHIFT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1519
	    i++, rwnd >>= 1)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1520
		;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1521
	tcp->tcp_rcv_ws = i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1522
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1523
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1524
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1525
 * Remove a connection from the list of detached TIME_WAIT connections.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1526
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1527
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1528
tcp_time_wait_remove(tcp_t *tcp, tcp_squeue_priv_t *tcp_time_wait)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1529
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1530
	boolean_t	locked = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1531
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1532
	if (tcp_time_wait == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1533
		tcp_time_wait = *((tcp_squeue_priv_t **)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1534
		    squeue_getprivate(tcp->tcp_connp->conn_sqp, SQPRIVATE_TCP));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1535
		mutex_enter(&tcp_time_wait->tcp_time_wait_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1536
		locked = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1537
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1538
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1539
	if (tcp->tcp_time_wait_expire == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1540
		ASSERT(tcp->tcp_time_wait_next == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1541
		ASSERT(tcp->tcp_time_wait_prev == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1542
		if (locked)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1543
			mutex_exit(&tcp_time_wait->tcp_time_wait_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1544
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1545
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1546
	ASSERT(TCP_IS_DETACHED(tcp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1547
	ASSERT(tcp->tcp_state == TCPS_TIME_WAIT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1548
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1549
	if (tcp == tcp_time_wait->tcp_time_wait_head) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1550
		ASSERT(tcp->tcp_time_wait_prev == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1551
		tcp_time_wait->tcp_time_wait_head = tcp->tcp_time_wait_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1552
		if (tcp_time_wait->tcp_time_wait_head != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1553
			tcp_time_wait->tcp_time_wait_head->tcp_time_wait_prev =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1554
			    NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1555
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1556
			tcp_time_wait->tcp_time_wait_tail = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1557
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1558
	} else if (tcp == tcp_time_wait->tcp_time_wait_tail) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1559
		ASSERT(tcp != tcp_time_wait->tcp_time_wait_head);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1560
		ASSERT(tcp->tcp_time_wait_next == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1561
		tcp_time_wait->tcp_time_wait_tail = tcp->tcp_time_wait_prev;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1562
		ASSERT(tcp_time_wait->tcp_time_wait_tail != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1563
		tcp_time_wait->tcp_time_wait_tail->tcp_time_wait_next = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1564
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1565
		ASSERT(tcp->tcp_time_wait_prev->tcp_time_wait_next == tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1566
		ASSERT(tcp->tcp_time_wait_next->tcp_time_wait_prev == tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1567
		tcp->tcp_time_wait_prev->tcp_time_wait_next =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1568
		    tcp->tcp_time_wait_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1569
		tcp->tcp_time_wait_next->tcp_time_wait_prev =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1570
		    tcp->tcp_time_wait_prev;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1571
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1572
	tcp->tcp_time_wait_next = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1573
	tcp->tcp_time_wait_prev = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1574
	tcp->tcp_time_wait_expire = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1575
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1576
	if (locked)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1577
		mutex_exit(&tcp_time_wait->tcp_time_wait_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1578
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1579
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1580
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1581
 * Add a connection to the list of detached TIME_WAIT connections
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1582
 * and set its time to expire.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1583
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1584
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1585
tcp_time_wait_append(tcp_t *tcp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1586
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1587
	tcp_squeue_priv_t *tcp_time_wait =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1588
	    *((tcp_squeue_priv_t **)squeue_getprivate(tcp->tcp_connp->conn_sqp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1589
		SQPRIVATE_TCP));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1590
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1591
	tcp_timers_stop(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1592
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1593
	/* Freed above */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1594
	ASSERT(tcp->tcp_timer_tid == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1595
	ASSERT(tcp->tcp_ack_tid == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1596
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1597
	/* must have happened at the time of detaching the tcp */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1598
	ASSERT(tcp->tcp_ptpahn == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1599
	ASSERT(tcp->tcp_flow_stopped == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1600
	ASSERT(tcp->tcp_time_wait_next == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1601
	ASSERT(tcp->tcp_time_wait_prev == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1602
	ASSERT(tcp->tcp_time_wait_expire == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1603
	ASSERT(tcp->tcp_listener == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1604
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1605
	tcp->tcp_time_wait_expire = ddi_get_lbolt();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1606
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1607
	 * The value computed below in tcp->tcp_time_wait_expire may
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1608
	 * appear negative or wrap around. That is ok since our
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1609
	 * interest is only in the difference between the current lbolt
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1610
	 * value and tcp->tcp_time_wait_expire. But the value should not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1611
	 * be zero, since it means the tcp is not in the TIME_WAIT list.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1612
	 * The corresponding comparison in tcp_time_wait_collector() uses
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1613
	 * modular arithmetic.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1614
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1615
	tcp->tcp_time_wait_expire +=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1616
	    drv_usectohz(tcp_time_wait_interval * 1000);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1617
	if (tcp->tcp_time_wait_expire == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1618
		tcp->tcp_time_wait_expire = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1619
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1620
	ASSERT(TCP_IS_DETACHED(tcp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1621
	ASSERT(tcp->tcp_state == TCPS_TIME_WAIT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1622
	ASSERT(tcp->tcp_time_wait_next == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1623
	ASSERT(tcp->tcp_time_wait_prev == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1624
	TCP_DBGSTAT(tcp_time_wait);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1625
	mutex_enter(&tcp_time_wait->tcp_time_wait_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1626
	if (tcp_time_wait->tcp_time_wait_head == NULL) {
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
		tcp_time_wait->tcp_time_wait_head = tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1629
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1630
		ASSERT(tcp_time_wait->tcp_time_wait_tail != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1631
		ASSERT(tcp_time_wait->tcp_time_wait_tail->tcp_state ==
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1632
		    TCPS_TIME_WAIT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1633
		tcp_time_wait->tcp_time_wait_tail->tcp_time_wait_next = tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1634
		tcp->tcp_time_wait_prev = tcp_time_wait->tcp_time_wait_tail;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1635
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1636
	tcp_time_wait->tcp_time_wait_tail = tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1637
	mutex_exit(&tcp_time_wait->tcp_time_wait_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1638
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1639
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1640
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1641
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1642
tcp_timewait_output(void *arg, mblk_t *mp, void *arg2)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1643
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1644
	conn_t	*connp = (conn_t *)arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1645
	tcp_t	*tcp = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1646
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1647
	ASSERT(tcp != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1648
	if (tcp->tcp_state == TCPS_CLOSED) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1649
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1650
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1651
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1652
	ASSERT((tcp->tcp_family == AF_INET &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1653
	    tcp->tcp_ipversion == IPV4_VERSION) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1654
	    (tcp->tcp_family == AF_INET6 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1655
	    (tcp->tcp_ipversion == IPV4_VERSION ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1656
	    tcp->tcp_ipversion == IPV6_VERSION)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1657
	ASSERT(!tcp->tcp_listener);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1658
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1659
	TCP_STAT(tcp_time_wait_reap);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1660
	ASSERT(TCP_IS_DETACHED(tcp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1661
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1662
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1663
	 * Because they have no upstream client to rebind or tcp_close()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1664
	 * them later, we axe the connection here and now.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1665
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1666
	tcp_close_detached(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1667
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1668
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1669
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1670
tcp_cleanup(tcp_t *tcp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1671
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1672
	mblk_t		*mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1673
	char		*tcp_iphc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1674
	int		tcp_iphc_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1675
	int		tcp_hdr_grown;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1676
	tcp_sack_info_t	*tcp_sack_info;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1677
	conn_t		*connp = tcp->tcp_connp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1678
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1679
	tcp_bind_hash_remove(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1680
	tcp_free(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1681
898
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
  1682
	/* Release any SSL context */
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
  1683
	if (tcp->tcp_kssl_ent != NULL) {
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
  1684
		kssl_release_ent(tcp->tcp_kssl_ent, NULL, KSSL_NO_PROXY);
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
  1685
		tcp->tcp_kssl_ent = NULL;
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
  1686
	}
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
  1687
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
  1688
	if (tcp->tcp_kssl_ctx != NULL) {
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
  1689
		kssl_release_ctx(tcp->tcp_kssl_ctx);
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
  1690
		tcp->tcp_kssl_ctx = NULL;
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
  1691
	}
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
  1692
	tcp->tcp_kssl_pending = B_FALSE;
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
  1693
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1694
	conn_delete_ire(connp, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1695
	if (connp->conn_flags & IPCL_TCPCONN) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1696
		if (connp->conn_latch != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1697
			IPLATCH_REFRELE(connp->conn_latch);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1698
		if (connp->conn_policy != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1699
			IPPH_REFRELE(connp->conn_policy);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1700
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1701
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1702
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1703
	 * Since we will bzero the entire structure, we need to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1704
	 * remove it and reinsert it in global hash list. We
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1705
	 * know the walkers can't get to this conn because we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1706
	 * had set CONDEMNED flag earlier and checked reference
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1707
	 * under conn_lock so walker won't pick it and when we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1708
	 * go the ipcl_globalhash_remove() below, no walker
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1709
	 * can get to it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1710
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1711
	ipcl_globalhash_remove(connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1712
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1713
	/* Save some state */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1714
	mp = tcp->tcp_timercache;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1715
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1716
	tcp_sack_info = tcp->tcp_sack_info;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1717
	tcp_iphc = tcp->tcp_iphc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1718
	tcp_iphc_len = tcp->tcp_iphc_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1719
	tcp_hdr_grown = tcp->tcp_hdr_grown;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1720
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1721
	bzero(connp, sizeof (conn_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1722
	bzero(tcp, sizeof (tcp_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1723
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1724
	/* restore the state */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1725
	tcp->tcp_timercache = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1726
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1727
	tcp->tcp_sack_info = tcp_sack_info;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1728
	tcp->tcp_iphc = tcp_iphc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1729
	tcp->tcp_iphc_len = tcp_iphc_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1730
	tcp->tcp_hdr_grown = tcp_hdr_grown;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1731
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1732
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1733
	tcp->tcp_connp = connp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1734
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1735
	connp->conn_tcp = tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1736
	connp->conn_flags = IPCL_TCPCONN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1737
	connp->conn_state_flags = CONN_INCIPIENT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1738
	connp->conn_ulp = IPPROTO_TCP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1739
	connp->conn_ref = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1740
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1741
	ipcl_globalhash_insert(connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1742
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1743
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1744
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1745
 * Blows away all tcps whose TIME_WAIT has expired. List traversal
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1746
 * is done forwards from the head.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1747
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1748
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1749
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1750
tcp_time_wait_collector(void *arg)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1751
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1752
	tcp_t *tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1753
	clock_t now;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1754
	mblk_t *mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1755
	conn_t *connp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1756
	kmutex_t *lock;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1757
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1758
	squeue_t *sqp = (squeue_t *)arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1759
	tcp_squeue_priv_t *tcp_time_wait =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1760
	    *((tcp_squeue_priv_t **)squeue_getprivate(sqp, SQPRIVATE_TCP));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1761
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1762
	mutex_enter(&tcp_time_wait->tcp_time_wait_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1763
	tcp_time_wait->tcp_time_wait_tid = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1764
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1765
	if (tcp_time_wait->tcp_free_list != NULL &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1766
	    tcp_time_wait->tcp_free_list->tcp_in_free_list == B_TRUE) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1767
		TCP_STAT(tcp_freelist_cleanup);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1768
		while ((tcp = tcp_time_wait->tcp_free_list) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1769
			tcp_time_wait->tcp_free_list = tcp->tcp_time_wait_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1770
			CONN_DEC_REF(tcp->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1771
		}
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
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1775
	 * In order to reap time waits reliably, we should use a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1776
	 * source of time that is not adjustable by the user -- hence
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1777
	 * the call to ddi_get_lbolt().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1778
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1779
	now = ddi_get_lbolt();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1780
	while ((tcp = tcp_time_wait->tcp_time_wait_head) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1781
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1782
		 * Compare times using modular arithmetic, since
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1783
		 * lbolt can wrapover.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1784
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1785
		if ((now - tcp->tcp_time_wait_expire) < 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1786
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1787
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1788
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1789
		tcp_time_wait_remove(tcp, tcp_time_wait);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1790
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1791
		connp = tcp->tcp_connp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1792
		ASSERT(connp->conn_fanout != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1793
		lock = &connp->conn_fanout->connf_lock;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1794
		/*
487
511557ecdec8 6174818 Sun-Fire,serengeti system panicked during lckbugs testing in s10_69
rshoaib
parents: 269
diff changeset
  1795
		 * 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
  1796
		 * 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
  1797
		 * 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
  1798
		 * 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
  1799
		 * 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
  1800
		 * 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
  1801
		 * 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
  1802
		 * 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
  1803
		 * 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
  1804
		 * 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
  1805
		 * 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
  1806
		 * 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
  1807
		 * regarding the refcnt logic.
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1808
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1809
		 * Since we are holding the tcp_time_wait_lock, its better
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1810
		 * not to block on the fanout_lock because other connections
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1811
		 * can't add themselves to time_wait list. So we do a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1812
		 * tryenter instead of mutex_enter.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1813
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1814
		if (mutex_tryenter(lock)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1815
			mutex_enter(&connp->conn_lock);
487
511557ecdec8 6174818 Sun-Fire,serengeti system panicked during lckbugs testing in s10_69
rshoaib
parents: 269
diff changeset
  1816
			if ((connp->conn_ref == 2) &&
511557ecdec8 6174818 Sun-Fire,serengeti system panicked during lckbugs testing in s10_69
rshoaib
parents: 269
diff changeset
  1817
			    (cl_inet_disconnect == NULL)) {
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1818
				ipcl_hash_remove_locked(connp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1819
				    connp->conn_fanout);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1820
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1821
				 * Set the CONDEMNED flag now itself so that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1822
				 * the refcnt cannot increase due to any
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1823
				 * walker. But we have still not cleaned up
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1824
				 * conn_ire_cache. This is still ok since
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1825
				 * we are going to clean it up in tcp_cleanup
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1826
				 * immediately and any interface unplumb
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1827
				 * thread will wait till the ire is blown away
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1828
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1829
				connp->conn_state_flags |= CONN_CONDEMNED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1830
				mutex_exit(&tcp_time_wait->tcp_time_wait_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1831
				mutex_exit(lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1832
				mutex_exit(&connp->conn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1833
				tcp_cleanup(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1834
				mutex_enter(&tcp_time_wait->tcp_time_wait_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1835
				tcp->tcp_time_wait_next =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1836
				    tcp_time_wait->tcp_free_list;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1837
				tcp_time_wait->tcp_free_list = tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1838
				continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1839
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1840
				CONN_INC_REF_LOCKED(connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1841
				mutex_exit(lock);
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,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1852
				    SQTAG_TCP_TIMEWAIT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1853
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1854
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1855
			mutex_enter(&connp->conn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1856
			CONN_INC_REF_LOCKED(connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1857
			mutex_exit(&tcp_time_wait->tcp_time_wait_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1858
			mutex_exit(&connp->conn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1859
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1860
			 * We can reuse the closemp here since conn has
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1861
			 * detached (otherwise we wouldn't even be in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1862
			 * time_wait list).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1863
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1864
			mp = &tcp->tcp_closemp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1865
			squeue_fill(connp->conn_sqp, mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1866
			    tcp_timewait_output, connp, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1867
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1868
		mutex_enter(&tcp_time_wait->tcp_time_wait_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1869
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1870
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1871
	if (tcp_time_wait->tcp_free_list != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1872
		tcp_time_wait->tcp_free_list->tcp_in_free_list = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1873
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1874
	tcp_time_wait->tcp_time_wait_tid =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1875
	    timeout(tcp_time_wait_collector, sqp, TCP_TIME_WAIT_DELAY);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1876
	mutex_exit(&tcp_time_wait->tcp_time_wait_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1877
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1878
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1879
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1880
 * Reply to a clients T_CONN_RES TPI message. This function
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1881
 * is used only for TLI/XTI listener. Sockfs sends T_CONN_RES
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1882
 * on the acceptor STREAM and processed in tcp_wput_accept().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1883
 * Read the block comment on top of tcp_conn_request().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1884
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1885
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1886
tcp_accept(tcp_t *listener, mblk_t *mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1887
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1888
	tcp_t	*acceptor;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1889
	tcp_t	*eager;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1890
	tcp_t   *tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1891
	struct T_conn_res	*tcr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1892
	t_uscalar_t	acceptor_id;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1893
	t_scalar_t	seqnum;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1894
	mblk_t	*opt_mp = NULL;	/* T_OPTMGMT_REQ messages */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1895
	mblk_t	*ok_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1896
	mblk_t	*mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1897
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1898
	if ((mp->b_wptr - mp->b_rptr) < sizeof (*tcr)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1899
		tcp_err_ack(listener, mp, TPROTO, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1900
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1901
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1902
	tcr = (struct T_conn_res *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1903
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1904
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1905
	 * Under ILP32 the stream head points tcr->ACCEPTOR_id at the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1906
	 * read side queue of the streams device underneath us i.e. the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1907
	 * read side queue of 'ip'. Since we can't deference QUEUE_ptr we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1908
	 * look it up in the queue_hash.  Under LP64 it sends down the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1909
	 * minor_t of the accepting endpoint.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1910
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1911
	 * Once the acceptor/eager are modified (in tcp_accept_swap) the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1912
	 * fanout hash lock is held.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1913
	 * This prevents any thread from entering the acceptor queue from
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1914
	 * below (since it has not been hard bound yet i.e. any inbound
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1915
	 * packets will arrive on the listener or default tcp queue and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1916
	 * go through tcp_lookup).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1917
	 * The CONN_INC_REF will prevent the acceptor from closing.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1918
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1919
	 * XXX It is still possible for a tli application to send down data
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1920
	 * on the accepting stream while another thread calls t_accept.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1921
	 * This should not be a problem for well-behaved applications since
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1922
	 * the T_OK_ACK is sent after the queue swapping is completed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1923
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1924
	 * If the accepting fd is the same as the listening fd, avoid
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1925
	 * queue hash lookup since that will return an eager listener in a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1926
	 * already established state.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1927
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1928
	acceptor_id = tcr->ACCEPTOR_id;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1929
	mutex_enter(&listener->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1930
	if (listener->tcp_acceptor_id == acceptor_id) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1931
		eager = listener->tcp_eager_next_q;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1932
		/* only count how many T_CONN_INDs so don't count q0 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1933
		if ((listener->tcp_conn_req_cnt_q != 1) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1934
		    (eager->tcp_conn_req_seqnum != tcr->SEQ_number)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1935
			mutex_exit(&listener->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1936
			tcp_err_ack(listener, mp, TBADF, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1937
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1938
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1939
		if (listener->tcp_conn_req_cnt_q0 != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1940
			/* Throw away all the eagers on q0. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1941
			tcp_eager_cleanup(listener, 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1942
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1943
		if (listener->tcp_syn_defense) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1944
			listener->tcp_syn_defense = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1945
			if (listener->tcp_ip_addr_cache != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1946
				kmem_free(listener->tcp_ip_addr_cache,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1947
				    IP_ADDR_CACHE_SIZE * sizeof (ipaddr_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1948
				listener->tcp_ip_addr_cache = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1949
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1950
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1951
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1952
		 * Transfer tcp_conn_req_max to the eager so that when
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1953
		 * a disconnect occurs we can revert the endpoint to the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1954
		 * listen state.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1955
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1956
		eager->tcp_conn_req_max = listener->tcp_conn_req_max;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1957
		ASSERT(listener->tcp_conn_req_cnt_q0 == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1958
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1959
		 * Get a reference on the acceptor just like the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1960
		 * tcp_acceptor_hash_lookup below.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1961
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1962
		acceptor = listener;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1963
		CONN_INC_REF(acceptor->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1964
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1965
		acceptor = tcp_acceptor_hash_lookup(acceptor_id);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1966
		if (acceptor == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1967
			if (listener->tcp_debug) {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  1968
				(void) strlog(TCP_MOD_ID, 0, 1,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1969
				    SL_ERROR|SL_TRACE,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1970
				    "tcp_accept: did not find acceptor 0x%x\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1971
				    acceptor_id);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1972
			}
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, TPROVMISMATCH, 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
		 * Verify acceptor state. The acceptable states for an acceptor
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1979
		 * include TCPS_IDLE and TCPS_BOUND.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1980
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1981
		switch (acceptor->tcp_state) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1982
		case TCPS_IDLE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1983
			/* FALLTHRU */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1984
		case TCPS_BOUND:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1985
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1986
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1987
			CONN_DEC_REF(acceptor->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1988
			mutex_exit(&listener->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1989
			tcp_err_ack(listener, mp, TOUTSTATE, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1990
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1991
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1992
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1993
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1994
	/* The listener must be in TCPS_LISTEN */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1995
	if (listener->tcp_state != TCPS_LISTEN) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1996
		CONN_DEC_REF(acceptor->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1997
		mutex_exit(&listener->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1998
		tcp_err_ack(listener, mp, TOUTSTATE, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1999
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2000
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2001
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2002
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2003
	 * Rendezvous with an eager connection request packet hanging off
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2004
	 * 'tcp' that has the 'seqnum' tag.  We tagged the detached open
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2005
	 * tcp structure when the connection packet arrived in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2006
	 * tcp_conn_request().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2007
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2008
	seqnum = tcr->SEQ_number;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2009
	eager = listener;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2010
	do {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2011
		eager = eager->tcp_eager_next_q;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2012
		if (eager == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2013
			CONN_DEC_REF(acceptor->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2014
			mutex_exit(&listener->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2015
			tcp_err_ack(listener, mp, TBADSEQ, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2016
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2017
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2018
	} while (eager->tcp_conn_req_seqnum != seqnum);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2019
	mutex_exit(&listener->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2020
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2021
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2022
	 * At this point, both acceptor and listener have 2 ref
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2023
	 * that they begin with. Acceptor has one additional ref
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2024
	 * we placed in lookup while listener has 3 additional
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2025
	 * ref for being behind the squeue (tcp_accept() is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2026
	 * done on listener's squeue); being in classifier hash;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2027
	 * and eager's ref on listener.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2028
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2029
	ASSERT(listener->tcp_connp->conn_ref >= 5);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2030
	ASSERT(acceptor->tcp_connp->conn_ref >= 3);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2031
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2032
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2033
	 * The eager at this point is set in its own squeue and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2034
	 * could easily have been killed (tcp_accept_finish will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2035
	 * deal with that) because of a TH_RST so we can only
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2036
	 * ASSERT for a single ref.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2037
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2038
	ASSERT(eager->tcp_connp->conn_ref >= 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2039
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2040
	/* Pre allocate the stroptions mblk also */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2041
	opt_mp = allocb(sizeof (struct stroptions), BPRI_HI);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2042
	if (opt_mp == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2043
		CONN_DEC_REF(acceptor->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2044
		CONN_DEC_REF(eager->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2045
		tcp_err_ack(listener, mp, TSYSERR, ENOMEM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2046
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2047
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2048
	DB_TYPE(opt_mp) = M_SETOPTS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2049
	opt_mp->b_wptr += sizeof (struct stroptions);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2050
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2051
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2052
	 * Prepare for inheriting IPV6_BOUND_IF and IPV6_RECVPKTINFO
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2053
	 * from listener to acceptor. The message is chained on opt_mp
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2054
	 * which will be sent onto eager's squeue.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2055
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2056
	if (listener->tcp_bound_if != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2057
		/* allocate optmgmt req */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2058
		mp1 = tcp_setsockopt_mp(IPPROTO_IPV6,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2059
		    IPV6_BOUND_IF, (char *)&listener->tcp_bound_if,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2060
		    sizeof (int));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2061
		if (mp1 != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2062
			linkb(opt_mp, mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2063
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2064
	if (listener->tcp_ipv6_recvancillary & TCP_IPV6_RECVPKTINFO) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2065
		uint_t on = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2066
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2067
		/* allocate optmgmt req */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2068
		mp1 = tcp_setsockopt_mp(IPPROTO_IPV6,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2069
		    IPV6_RECVPKTINFO, (char *)&on, sizeof (on));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2070
		if (mp1 != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2071
			linkb(opt_mp, mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2072
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2073
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2074
	/* Re-use mp1 to hold a copy of mp, in case reallocb fails */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2075
	if ((mp1 = copymsg(mp)) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2076
		CONN_DEC_REF(acceptor->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2077
		CONN_DEC_REF(eager->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2078
		freemsg(opt_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2079
		tcp_err_ack(listener, mp, TSYSERR, ENOMEM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2080
		return;
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
	tcr = (struct T_conn_res *)mp1->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2084
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2085
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2086
	 * This is an expanded version of mi_tpi_ok_ack_alloc()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2087
	 * which allocates a larger mblk and appends the new
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2088
	 * local address to the ok_ack.  The address is copied by
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2089
	 * soaccept() for getsockname().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2090
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2091
	{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2092
		int extra;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2093
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2094
		extra = (eager->tcp_family == AF_INET) ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2095
		    sizeof (sin_t) : sizeof (sin6_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2096
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2097
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2098
		 * Try to re-use mp, if possible.  Otherwise, allocate
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2099
		 * an mblk and return it as ok_mp.  In any case, mp
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2100
		 * is no longer usable upon return.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2101
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2102
		if ((ok_mp = mi_tpi_ok_ack_alloc_extra(mp, extra)) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2103
			CONN_DEC_REF(acceptor->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2104
			CONN_DEC_REF(eager->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2105
			freemsg(opt_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2106
			/* Original mp has been freed by now, so use mp1 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2107
			tcp_err_ack(listener, mp1, TSYSERR, ENOMEM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2108
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2109
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2110
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2111
		mp = NULL;	/* We should never use mp after this point */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2112
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2113
		switch (extra) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2114
		case sizeof (sin_t): {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2115
				sin_t *sin = (sin_t *)ok_mp->b_wptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2116
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2117
				ok_mp->b_wptr += extra;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2118
				sin->sin_family = AF_INET;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2119
				sin->sin_port = eager->tcp_lport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2120
				sin->sin_addr.s_addr =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2121
				    eager->tcp_ipha->ipha_src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2122
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2123
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2124
		case sizeof (sin6_t): {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2125
				sin6_t *sin6 = (sin6_t *)ok_mp->b_wptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2126
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2127
				ok_mp->b_wptr += extra;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2128
				sin6->sin6_family = AF_INET6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2129
				sin6->sin6_port = eager->tcp_lport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2130
				if (eager->tcp_ipversion == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2131
					sin6->sin6_flowinfo = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2132
					IN6_IPADDR_TO_V4MAPPED(
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2133
					    eager->tcp_ipha->ipha_src,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2134
					    &sin6->sin6_addr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2135
				} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2136
					ASSERT(eager->tcp_ip6h != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2137
					sin6->sin6_flowinfo =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2138
					    eager->tcp_ip6h->ip6_vcf &
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2139
					    ~IPV6_VERS_AND_FLOW_MASK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2140
					sin6->sin6_addr =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2141
					    eager->tcp_ip6h->ip6_src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2142
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2143
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2144
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2145
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2146
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2147
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2148
		ASSERT(ok_mp->b_wptr <= ok_mp->b_datap->db_lim);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2149
	}
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
	 * If there are no options we know that the T_CONN_RES will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2153
	 * succeed. However, we can't send the T_OK_ACK upstream until
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2154
	 * the tcp_accept_swap is done since it would be dangerous to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2155
	 * let the application start using the new fd prior to the swap.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2156
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2157
	tcp_accept_swap(listener, acceptor, eager);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2158
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2159
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2160
	 * tcp_accept_swap unlinks eager from listener but does not drop
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2161
	 * the eager's reference on the listener.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2162
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2163
	ASSERT(eager->tcp_listener == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2164
	ASSERT(listener->tcp_connp->conn_ref >= 5);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2165
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2166
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2167
	 * The eager is now associated with its own queue. Insert in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2168
	 * the hash so that the connection can be reused for a future
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2169
	 * T_CONN_RES.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2170
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2171
	tcp_acceptor_hash_insert(acceptor_id, eager);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2172
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2173
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2174
	 * We now do the processing of options with T_CONN_RES.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2175
	 * We delay till now since we wanted to have queue to pass to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2176
	 * option processing routines that points back to the right
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2177
	 * instance structure which does not happen until after
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2178
	 * tcp_accept_swap().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2179
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2180
	 * Note:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2181
	 * The sanity of the logic here assumes that whatever options
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2182
	 * are appropriate to inherit from listner=>eager are done
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2183
	 * before this point, and whatever were to be overridden (or not)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2184
	 * in transfer logic from eager=>acceptor in tcp_accept_swap().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2185
	 * [ Warning: acceptor endpoint can have T_OPTMGMT_REQ done to it
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2186
	 *   before its ACCEPTOR_id comes down in T_CONN_RES ]
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2187
	 * This may not be true at this point in time but can be fixed
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2188
	 * independently. This option processing code starts with
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2189
	 * the instantiated acceptor instance and the final queue at
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2190
	 * this point.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2191
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2192
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2193
	if (tcr->OPT_length != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2194
		/* Options to process */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2195
		int t_error = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2196
		int sys_error = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2197
		int do_disconnect = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2198
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2199
		if (tcp_conprim_opt_process(eager, mp1,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2200
		    &do_disconnect, &t_error, &sys_error) < 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2201
			eager->tcp_accept_error = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2202
			if (do_disconnect) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2203
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2204
				 * An option failed which does not allow
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2205
				 * connection to be accepted.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2206
				 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2207
				 * We allow T_CONN_RES to succeed and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2208
				 * put a T_DISCON_IND on the eager queue.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2209
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2210
				ASSERT(t_error == 0 && sys_error == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2211
				eager->tcp_send_discon_ind = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2212
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2213
				ASSERT(t_error != 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2214
				freemsg(ok_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2215
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2216
				 * Original mp was either freed or set
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2217
				 * to ok_mp above, so use mp1 instead.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2218
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2219
				tcp_err_ack(listener, mp1, t_error, sys_error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2220
				goto finish;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2221
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2222
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2223
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2224
		 * Most likely success in setting options (except if
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2225
		 * eager->tcp_send_discon_ind set).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2226
		 * mp1 option buffer represented by OPT_length/offset
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2227
		 * potentially modified and contains results of setting
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2228
		 * options at this point
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2229
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2230
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2231
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2232
	/* We no longer need mp1, since all options processing has passed */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2233
	freemsg(mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2234
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2235
	putnext(listener->tcp_rq, ok_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2236
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2237
	mutex_enter(&listener->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2238
	if (listener->tcp_eager_prev_q0->tcp_conn_def_q0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2239
		tcp_t	*tail;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2240
		mblk_t	*conn_ind;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2241
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2242
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2243
		 * This path should not be executed if listener and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2244
		 * acceptor streams are the same.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2245
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2246
		ASSERT(listener != acceptor);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2247
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2248
		tcp = listener->tcp_eager_prev_q0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2249
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2250
		 * listener->tcp_eager_prev_q0 points to the TAIL of the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2251
		 * deferred T_conn_ind queue. We need to get to the head of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2252
		 * the queue in order to send up T_conn_ind the same order as
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2253
		 * how the 3WHS is completed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2254
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2255
		while (tcp != listener) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2256
			if (!tcp->tcp_eager_prev_q0->tcp_conn_def_q0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2257
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2258
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2259
				tcp = tcp->tcp_eager_prev_q0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2260
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2261
		ASSERT(tcp != listener);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2262
		conn_ind = tcp->tcp_conn.tcp_eager_conn_ind;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2263
		ASSERT(conn_ind != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2264
		tcp->tcp_conn.tcp_eager_conn_ind = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2265
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2266
		/* Move from q0 to q */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2267
		ASSERT(listener->tcp_conn_req_cnt_q0 > 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2268
		listener->tcp_conn_req_cnt_q0--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2269
		listener->tcp_conn_req_cnt_q++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2270
		tcp->tcp_eager_next_q0->tcp_eager_prev_q0 =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2271
		    tcp->tcp_eager_prev_q0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2272
		tcp->tcp_eager_prev_q0->tcp_eager_next_q0 =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2273
		    tcp->tcp_eager_next_q0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2274
		tcp->tcp_eager_prev_q0 = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2275
		tcp->tcp_eager_next_q0 = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2276
		tcp->tcp_conn_def_q0 = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2277
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2278
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2279
		 * Insert at end of the queue because sockfs sends
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2280
		 * down T_CONN_RES in chronological order. Leaving
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2281
		 * the older conn indications at front of the queue
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2282
		 * helps reducing search time.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2283
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2284
		tail = listener->tcp_eager_last_q;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2285
		if (tail != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2286
			tail->tcp_eager_next_q = tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2287
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2288
			listener->tcp_eager_next_q = tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2289
		listener->tcp_eager_last_q = tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2290
		tcp->tcp_eager_next_q = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2291
		mutex_exit(&listener->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2292
		putnext(tcp->tcp_rq, conn_ind);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2293
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2294
		mutex_exit(&listener->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2295
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2296
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2297
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2298
	 * Done with the acceptor - free it
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2299
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2300
	 * Note: from this point on, no access to listener should be made
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2301
	 * as listener can be equal to acceptor.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2302
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2303
finish:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2304
	ASSERT(acceptor->tcp_detached);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2305
	acceptor->tcp_rq = tcp_g_q;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2306
	acceptor->tcp_wq = WR(tcp_g_q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2307
	(void) tcp_clean_death(acceptor, 0, 2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2308
	CONN_DEC_REF(acceptor->tcp_connp);
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
	 * In case we already received a FIN we have to make tcp_rput send
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2312
	 * the ordrel_ind. This will also send up a window update if the window
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2313
	 * has opened up.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2314
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2315
	 * In the normal case of a successful connection acceptance
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2316
	 * we give the O_T_BIND_REQ to the read side put procedure as an
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2317
	 * indication that this was just accepted. This tells tcp_rput to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2318
	 * pass up any data queued in tcp_rcv_list.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2319
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2320
	 * In the fringe case where options sent with T_CONN_RES failed and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2321
	 * we required, we would be indicating a T_DISCON_IND to blow
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2322
	 * away this connection.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2323
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2324
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2325
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2326
	 * XXX: we currently have a problem if XTI application closes the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2327
	 * acceptor stream in between. This problem exists in on10-gate also
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2328
	 * and is well know but nothing can be done short of major rewrite
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2329
	 * 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
  2330
	 * eager same squeue as listener (we can distinguish non socket
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2331
	 * listeners at the time of handling a SYN in tcp_conn_request)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2332
	 * and do most of the work that tcp_accept_finish does here itself
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2333
	 * and then get behind the acceptor squeue to access the acceptor
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2334
	 * queue.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2335
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2336
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2337
	 * 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
  2338
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2339
	squeue_fill(eager->tcp_connp->conn_sqp, opt_mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2340
	    tcp_accept_finish, eager->tcp_connp, SQTAG_TCP_ACCEPT_FINISH);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2341
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2342
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2343
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2344
 * Swap information between the eager and acceptor for a TLI/XTI client.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2345
 * The sockfs accept is done on the acceptor stream and control goes
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2346
 * through tcp_wput_accept() and tcp_accept()/tcp_accept_swap() is not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2347
 * called. In either case, both the eager and listener are in their own
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2348
 * perimeter (squeue) and the code has to deal with potential race.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2349
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2350
 * See the block comment on top of tcp_accept() and tcp_wput_accept().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2351
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2352
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2353
tcp_accept_swap(tcp_t *listener, tcp_t *acceptor, tcp_t *eager)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2354
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2355
	conn_t	*econnp, *aconnp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2356
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2357
	ASSERT(eager->tcp_rq == listener->tcp_rq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2358
	ASSERT(eager->tcp_detached && !acceptor->tcp_detached);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2359
	ASSERT(!eager->tcp_hard_bound);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2360
	ASSERT(!TCP_IS_SOCKET(acceptor));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2361
	ASSERT(!TCP_IS_SOCKET(eager));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2362
	ASSERT(!TCP_IS_SOCKET(listener));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2363
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2364
	acceptor->tcp_detached = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2365
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2366
	 * To permit stream re-use by TLI/XTI, the eager needs a copy of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2367
	 * the acceptor id.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2368
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2369
	eager->tcp_acceptor_id = acceptor->tcp_acceptor_id;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2370
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2371
	/* remove eager from listen list... */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2372
	mutex_enter(&listener->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2373
	tcp_eager_unlink(eager);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2374
	ASSERT(eager->tcp_eager_next_q == NULL &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2375
	    eager->tcp_eager_last_q == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2376
	ASSERT(eager->tcp_eager_next_q0 == NULL &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2377
	    eager->tcp_eager_prev_q0 == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2378
	mutex_exit(&listener->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2379
	eager->tcp_rq = acceptor->tcp_rq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2380
	eager->tcp_wq = acceptor->tcp_wq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2381
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2382
	econnp = eager->tcp_connp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2383
	aconnp = acceptor->tcp_connp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2384
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2385
	eager->tcp_rq->q_ptr = econnp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2386
	eager->tcp_wq->q_ptr = econnp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2387
	eager->tcp_detached = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2388
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2389
	ASSERT(eager->tcp_ack_tid == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2390
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2391
	econnp->conn_dev = aconnp->conn_dev;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2392
	eager->tcp_cred = econnp->conn_cred = aconnp->conn_cred;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2393
	econnp->conn_zoneid = aconnp->conn_zoneid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2394
	aconnp->conn_cred = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2395
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2396
	/* Do the IPC initialization */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2397
	CONN_INC_REF(econnp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2398
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2399
	econnp->conn_multicast_loop = aconnp->conn_multicast_loop;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2400
	econnp->conn_af_isv6 = aconnp->conn_af_isv6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2401
	econnp->conn_pkt_isv6 = aconnp->conn_pkt_isv6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2402
	econnp->conn_ulp = aconnp->conn_ulp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2403
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2404
	/* Done with old IPC. Drop its ref on its connp */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2405
	CONN_DEC_REF(aconnp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2406
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2407
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2408
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2409
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2410
 * Adapt to the information, such as rtt and rtt_sd, provided from the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2411
 * ire cached in conn_cache_ire. If no ire cached, do a ire lookup.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2412
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2413
 * Checks for multicast and broadcast destination address.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2414
 * Returns zero on failure; non-zero if ok.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2415
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2416
 * Note that the MSS calculation here is based on the info given in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2417
 * the IRE.  We do not do any calculation based on TCP options.  They
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2418
 * will be handled in tcp_rput_other() and tcp_rput_data() when TCP
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2419
 * knows which options to use.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2420
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2421
 * Note on how TCP gets its parameters for a connection.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2422
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2423
 * When a tcp_t structure is allocated, it gets all the default parameters.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2424
 * In tcp_adapt_ire(), it gets those metric parameters, like rtt, rtt_sd,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2425
 * spipe, rpipe, ... from the route metrics.  Route metric overrides the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2426
 * default.  But if there is an associated tcp_host_param, it will override
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2427
 * the metrics.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2428
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2429
 * An incoming SYN with a multicast or broadcast destination address, is dropped
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2430
 * in 1 of 2 places.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2431
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2432
 * 1. If the packet was received over the wire it is dropped in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2433
 * ip_rput_process_broadcast()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2434
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2435
 * 2. If the packet was received through internal IP loopback, i.e. the packet
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2436
 * was generated and received on the same machine, it is dropped in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2437
 * ip_wput_local()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2438
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2439
 * An incoming SYN with a multicast or broadcast source address is always
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2440
 * dropped in tcp_adapt_ire. The same logic in tcp_adapt_ire also serves to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2441
 * reject an attempt to connect to a broadcast or multicast (destination)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2442
 * address.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2443
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2444
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2445
tcp_adapt_ire(tcp_t *tcp, mblk_t *ire_mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2446
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2447
	tcp_hsp_t	*hsp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2448
	ire_t		*ire;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2449
	ire_t		*sire = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2450
	iulp_t		*ire_uinfo;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2451
	uint32_t	mss_max;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2452
	uint32_t	mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2453
	boolean_t	tcp_detached = TCP_IS_DETACHED(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2454
	conn_t		*connp = tcp->tcp_connp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2455
	boolean_t	ire_cacheable = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2456
	zoneid_t	zoneid = connp->conn_zoneid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2457
	ill_t		*ill = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2458
	boolean_t	incoming = (ire_mp == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2459
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2460
	ASSERT(connp->conn_ire_cache == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2461
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2462
	if (tcp->tcp_ipversion == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2463
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2464
		if (CLASSD(tcp->tcp_connp->conn_rem)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2465
			BUMP_MIB(&ip_mib, ipInDiscards);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2466
			return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2467
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2468
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2469
		ire = ire_cache_lookup(tcp->tcp_connp->conn_rem, zoneid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2470
		if (ire != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2471
			ire_cacheable = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2472
			ire_uinfo = (ire_mp != NULL) ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2473
			    &((ire_t *)ire_mp->b_rptr)->ire_uinfo:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2474
			    &ire->ire_uinfo;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2475
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2476
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2477
			if (ire_mp == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2478
				ire = ire_ftable_lookup(
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2479
				    tcp->tcp_connp->conn_rem,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2480
				    0, 0, 0, NULL, &sire, zoneid, 0,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2481
				    (MATCH_IRE_RECURSIVE | MATCH_IRE_DEFAULT));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2482
				if (ire == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2483
					return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2484
				ire_uinfo = (sire != NULL) ? &sire->ire_uinfo :
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2485
				    &ire->ire_uinfo;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2486
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2487
				ire = (ire_t *)ire_mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2488
				ire_uinfo =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2489
				    &((ire_t *)ire_mp->b_rptr)->ire_uinfo;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2490
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2491
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2492
		ASSERT(ire != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2493
		ASSERT(ire_uinfo != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2494
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2495
		if ((ire->ire_src_addr == INADDR_ANY) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2496
		    (ire->ire_type & IRE_BROADCAST)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2497
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2498
			 * ire->ire_mp is non null when ire_mp passed in is used
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2499
			 * ire->ire_mp is set in ip_bind_insert_ire[_v6]().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2500
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2501
			if (ire->ire_mp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2502
				ire_refrele(ire);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2503
			if (sire != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2504
				ire_refrele(sire);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2505
			return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2506
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2507
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2508
		if (tcp->tcp_ipha->ipha_src == INADDR_ANY) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2509
			ipaddr_t src_addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2510
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2511
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2512
			 * ip_bind_connected() has stored the correct source
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2513
			 * address in conn_src.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2514
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2515
			src_addr = tcp->tcp_connp->conn_src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2516
			tcp->tcp_ipha->ipha_src = src_addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2517
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2518
			 * Copy of the src addr. in tcp_t is needed
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2519
			 * for the lookup funcs.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2520
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2521
			IN6_IPADDR_TO_V4MAPPED(src_addr, &tcp->tcp_ip_src_v6);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2522
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2523
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2524
		 * Set the fragment bit so that IP will tell us if the MTU
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2525
		 * should change. IP tells us the latest setting of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2526
		 * ip_path_mtu_discovery through ire_frag_flag.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2527
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2528
		if (ip_path_mtu_discovery) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2529
			tcp->tcp_ipha->ipha_fragment_offset_and_flags =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2530
			    htons(IPH_DF);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2531
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2532
		tcp->tcp_localnet = (ire->ire_gateway_addr == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2533
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2534
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2535
		 * For incoming connection ire_mp = NULL
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2536
		 * For outgoing connection ire_mp != NULL
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2537
		 * Technically we should check conn_incoming_ill
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2538
		 * when ire_mp is NULL and conn_outgoing_ill when
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2539
		 * ire_mp is non-NULL. But this is performance
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2540
		 * critical path and for IPV*_BOUND_IF, outgoing
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2541
		 * and incoming ill are always set to the same value.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2542
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2543
		ill_t	*dst_ill = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2544
		ipif_t  *dst_ipif = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2545
		int match_flags = MATCH_IRE_RECURSIVE | MATCH_IRE_DEFAULT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2546
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2547
		ASSERT(connp->conn_outgoing_ill == connp->conn_incoming_ill);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2548
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2549
		if (connp->conn_outgoing_ill != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2550
			/* Outgoing or incoming path */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2551
			int   err;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2552
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2553
			dst_ill = conn_get_held_ill(connp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2554
			    &connp->conn_outgoing_ill, &err);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2555
			if (err == ILL_LOOKUP_FAILED || dst_ill == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2556
				ip1dbg(("tcp_adapt_ire: ill_lookup failed\n"));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2557
				return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2558
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2559
			match_flags |= MATCH_IRE_ILL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2560
			dst_ipif = dst_ill->ill_ipif;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2561
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2562
		ire = ire_ctable_lookup_v6(&tcp->tcp_connp->conn_remv6,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2563
		    0, 0, dst_ipif, zoneid, match_flags);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2564
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2565
		if (ire != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2566
			ire_cacheable = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2567
			ire_uinfo = (ire_mp != NULL) ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2568
			    &((ire_t *)ire_mp->b_rptr)->ire_uinfo:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2569
			    &ire->ire_uinfo;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2570
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2571
			if (ire_mp == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2572
				ire = ire_ftable_lookup_v6(
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2573
				    &tcp->tcp_connp->conn_remv6,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2574
				    0, 0, 0, dst_ipif, &sire, zoneid,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2575
				    0, match_flags);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2576
				if (ire == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2577
					if (dst_ill != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2578
						ill_refrele(dst_ill);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2579
					return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2580
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2581
				ire_uinfo = (sire != NULL) ? &sire->ire_uinfo :
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2582
				    &ire->ire_uinfo;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2583
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2584
				ire = (ire_t *)ire_mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2585
				ire_uinfo =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2586
				    &((ire_t *)ire_mp->b_rptr)->ire_uinfo;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2587
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2588
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2589
		if (dst_ill != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2590
			ill_refrele(dst_ill);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2591
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2592
		ASSERT(ire != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2593
		ASSERT(ire_uinfo != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2594
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2595
		if (IN6_IS_ADDR_UNSPECIFIED(&ire->ire_src_addr_v6) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2596
		    IN6_IS_ADDR_MULTICAST(&ire->ire_addr_v6)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2597
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2598
			 * ire->ire_mp is non null when ire_mp passed in is used
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2599
			 * ire->ire_mp is set in ip_bind_insert_ire[_v6]().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2600
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2601
			if (ire->ire_mp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2602
				ire_refrele(ire);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2603
			if (sire != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2604
				ire_refrele(sire);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2605
			return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2606
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2607
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2608
		if (IN6_IS_ADDR_UNSPECIFIED(&tcp->tcp_ip6h->ip6_src)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2609
			in6_addr_t	src_addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2610
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2611
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2612
			 * ip_bind_connected_v6() has stored the correct source
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2613
			 * address per IPv6 addr. selection policy in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2614
			 * conn_src_v6.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2615
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2616
			src_addr = tcp->tcp_connp->conn_srcv6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2617
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2618
			tcp->tcp_ip6h->ip6_src = src_addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2619
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2620
			 * Copy of the src addr. in tcp_t is needed
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2621
			 * for the lookup funcs.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2622
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2623
			tcp->tcp_ip_src_v6 = src_addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2624
			ASSERT(IN6_ARE_ADDR_EQUAL(&tcp->tcp_ip6h->ip6_src,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2625
			    &connp->conn_srcv6));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2626
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2627
		tcp->tcp_localnet =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2628
		    IN6_IS_ADDR_UNSPECIFIED(&ire->ire_gateway_addr_v6);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2629
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2630
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2631
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2632
	 * This allows applications to fail quickly when connections are made
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2633
	 * to dead hosts. Hosts can be labeled dead by adding a reject route
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2634
	 * with both the RTF_REJECT and RTF_PRIVATE flags set.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2635
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2636
	if ((ire->ire_flags & RTF_REJECT) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2637
	    (ire->ire_flags & RTF_PRIVATE))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2638
		goto error;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2639
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2640
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2641
	 * Make use of the cached rtt and rtt_sd values to calculate the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2642
	 * initial RTO.  Note that they are already initialized in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2643
	 * tcp_init_values().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2644
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2645
	if (ire_uinfo->iulp_rtt != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2646
		clock_t	rto;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2647
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2648
		tcp->tcp_rtt_sa = ire_uinfo->iulp_rtt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2649
		tcp->tcp_rtt_sd = ire_uinfo->iulp_rtt_sd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2650
		rto = (tcp->tcp_rtt_sa >> 3) + tcp->tcp_rtt_sd +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2651
		    tcp_rexmit_interval_extra + (tcp->tcp_rtt_sa >> 5);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2652
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2653
		if (rto > tcp_rexmit_interval_max) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2654
			tcp->tcp_rto = tcp_rexmit_interval_max;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2655
		} else if (rto < tcp_rexmit_interval_min) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2656
			tcp->tcp_rto = tcp_rexmit_interval_min;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2657
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2658
			tcp->tcp_rto = rto;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2659
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2660
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2661
	if (ire_uinfo->iulp_ssthresh != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2662
		tcp->tcp_cwnd_ssthresh = ire_uinfo->iulp_ssthresh;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2663
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2664
		tcp->tcp_cwnd_ssthresh = TCP_MAX_LARGEWIN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2665
	if (ire_uinfo->iulp_spipe > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2666
		tcp->tcp_xmit_hiwater = MIN(ire_uinfo->iulp_spipe,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2667
		    tcp_max_buf);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2668
		if (tcp_snd_lowat_fraction != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2669
			tcp->tcp_xmit_lowater = tcp->tcp_xmit_hiwater /
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2670
			    tcp_snd_lowat_fraction;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2671
		(void) tcp_maxpsz_set(tcp, B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2672
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2673
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2674
	 * Note that up till now, acceptor always inherits receive
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2675
	 * window from the listener.  But if there is a metrics associated
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2676
	 * with a host, we should use that instead of inheriting it from
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2677
	 * listener.  Thus we need to pass this info back to the caller.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2678
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2679
	if (ire_uinfo->iulp_rpipe > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2680
		tcp->tcp_rwnd = MIN(ire_uinfo->iulp_rpipe, tcp_max_buf);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2681
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2682
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2683
		 * For passive open, set tcp_rwnd to 0 so that the caller
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2684
		 * knows that there is no rpipe metric for this connection.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2685
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2686
		if (tcp_detached)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2687
			tcp->tcp_rwnd = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2688
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2689
	if (ire_uinfo->iulp_rtomax > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2690
		tcp->tcp_second_timer_threshold = ire_uinfo->iulp_rtomax;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2691
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2692
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2693
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2694
	 * Use the metric option settings, iulp_tstamp_ok and iulp_wscale_ok,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2695
	 * only for active open.  What this means is that if the other side
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2696
	 * uses timestamp or window scale option, TCP will also use those
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2697
	 * options.  That is for passive open.  If the application sets a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2698
	 * large window, window scale is enabled regardless of the value in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2699
	 * iulp_wscale_ok.  This is the behavior since 2.6.  So we keep it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2700
	 * The only case left in passive open processing is the check for SACK.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2701
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2702
	 * For ECN, it should probably be like SACK.  But the current
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2703
	 * value is binary, so we treat it like the other cases.  The
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2704
	 * metric only controls active open.  For passive open, the ndd
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2705
	 * param, tcp_ecn_permitted, controls the behavior.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2706
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2707
	if (!tcp_detached) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2708
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2709
		 * The if check means that the following can only be turned
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2710
		 * on by the metrics only IRE, but not off.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2711
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2712
		if (ire_uinfo->iulp_tstamp_ok)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2713
			tcp->tcp_snd_ts_ok = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2714
		if (ire_uinfo->iulp_wscale_ok)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2715
			tcp->tcp_snd_ws_ok = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2716
		if (ire_uinfo->iulp_sack == 2)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2717
			tcp->tcp_snd_sack_ok = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2718
		if (ire_uinfo->iulp_ecn_ok)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2719
			tcp->tcp_ecn_ok = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2720
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2721
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2722
		 * Passive open.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2723
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2724
		 * As above, the if check means that SACK can only be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2725
		 * turned on by the metric only IRE.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2726
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2727
		if (ire_uinfo->iulp_sack > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2728
			tcp->tcp_snd_sack_ok = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2729
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2730
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2731
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2732
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2733
	 * XXX: Note that currently, ire_max_frag can be as small as 68
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2734
	 * because of PMTUd.  So tcp_mss may go to negative if combined
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2735
	 * length of all those options exceeds 28 bytes.  But because
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2736
	 * of the tcp_mss_min check below, we may not have a problem if
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2737
	 * tcp_mss_min is of a reasonable value.  The default is 1 so
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2738
	 * the negative problem still exists.  And the check defeats PMTUd.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2739
	 * In fact, if PMTUd finds that the MSS should be smaller than
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2740
	 * tcp_mss_min, TCP should turn off PMUTd and use the tcp_mss_min
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2741
	 * value.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2742
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2743
	 * We do not deal with that now.  All those problems related to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2744
	 * PMTUd will be fixed later.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2745
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2746
	ASSERT(ire->ire_max_frag != 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2747
	mss = tcp->tcp_if_mtu = ire->ire_max_frag;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2748
	if (tcp->tcp_ipp_fields & IPPF_USE_MIN_MTU) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2749
		if (tcp->tcp_ipp_use_min_mtu == IPV6_USE_MIN_MTU_NEVER) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2750
			mss = MIN(mss, IPV6_MIN_MTU);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2751
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2752
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2753
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2754
	/* Sanity check for MSS value. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2755
	if (tcp->tcp_ipversion == IPV4_VERSION)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2756
		mss_max = tcp_mss_max_ipv4;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2757
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2758
		mss_max = tcp_mss_max_ipv6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2759
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2760
	if (tcp->tcp_ipversion == IPV6_VERSION &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2761
	    (ire->ire_frag_flag & IPH_FRAG_HDR)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2762
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2763
		 * After receiving an ICMPv6 "packet too big" message with a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2764
		 * MTU < 1280, and for multirouted IPv6 packets, the IP layer
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2765
		 * will insert a 8-byte fragment header in every packet; we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2766
		 * reduce the MSS by that amount here.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2767
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2768
		mss -= sizeof (ip6_frag_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2769
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2770
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2771
	if (tcp->tcp_ipsec_overhead == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2772
		tcp->tcp_ipsec_overhead = conn_ipsec_length(connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2773
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2774
	mss -= tcp->tcp_ipsec_overhead;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2775
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2776
	if (mss < tcp_mss_min)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2777
		mss = tcp_mss_min;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2778
	if (mss > mss_max)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2779
		mss = mss_max;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2780
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2781
	/* Note that this is the maximum MSS, excluding all options. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2782
	tcp->tcp_mss = mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2783
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2784
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2785
	 * Initialize the ISS here now that we have the full connection ID.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2786
	 * The RFC 1948 method of initial sequence number generation requires
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2787
	 * knowledge of the full connection ID before setting the ISS.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2788
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2789
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2790
	tcp_iss_init(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2791
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2792
	if (ire->ire_type & (IRE_LOOPBACK | IRE_LOCAL))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2793
		tcp->tcp_loopback = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2794
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2795
	if (tcp->tcp_ipversion == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2796
		hsp = tcp_hsp_lookup(tcp->tcp_remote);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2797
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2798
		hsp = tcp_hsp_lookup_ipv6(&tcp->tcp_remote_v6);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2799
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2800
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2801
	if (hsp != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2802
		/* Only modify if we're going to make them bigger */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2803
		if (hsp->tcp_hsp_sendspace > tcp->tcp_xmit_hiwater) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2804
			tcp->tcp_xmit_hiwater = hsp->tcp_hsp_sendspace;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2805
			if (tcp_snd_lowat_fraction != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2806
				tcp->tcp_xmit_lowater = tcp->tcp_xmit_hiwater /
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2807
					tcp_snd_lowat_fraction;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2808
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2809
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2810
		if (hsp->tcp_hsp_recvspace > tcp->tcp_rwnd) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2811
			tcp->tcp_rwnd = hsp->tcp_hsp_recvspace;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2812
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2813
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2814
		/* Copy timestamp flag only for active open */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2815
		if (!tcp_detached)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2816
			tcp->tcp_snd_ts_ok = hsp->tcp_hsp_tstamp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2817
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2818
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2819
	if (sire != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2820
		IRE_REFRELE(sire);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2821
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2822
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2823
	 * If we got an IRE_CACHE and an ILL, go through their properties;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2824
	 * otherwise, this is deferred until later when we have an IRE_CACHE.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2825
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2826
	if (tcp->tcp_loopback ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2827
	    (ire_cacheable && (ill = ire_to_ill(ire)) != NULL)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2828
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2829
		 * For incoming, see if this tcp may be MDT-capable.  For
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2830
		 * outgoing, this process has been taken care of through
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2831
		 * tcp_rput_other.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2832
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2833
		tcp_ire_ill_check(tcp, ire, ill, incoming);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2834
		tcp->tcp_ire_ill_check_done = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2835
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2836
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2837
	mutex_enter(&connp->conn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2838
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2839
	 * Make sure that conn is not marked incipient
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2840
	 * for incoming connections. A blind
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2841
	 * removal of incipient flag is cheaper than
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2842
	 * check and removal.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2843
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2844
	connp->conn_state_flags &= ~CONN_INCIPIENT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2845
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2846
	/* Must not cache forwarding table routes. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2847
	if (ire_cacheable) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2848
		rw_enter(&ire->ire_bucket->irb_lock, RW_READER);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2849
		if (!(ire->ire_marks & IRE_MARK_CONDEMNED)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2850
			connp->conn_ire_cache = ire;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2851
			IRE_UNTRACE_REF(ire);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2852
			rw_exit(&ire->ire_bucket->irb_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2853
			mutex_exit(&connp->conn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2854
			return (1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2855
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2856
		rw_exit(&ire->ire_bucket->irb_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2857
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2858
	mutex_exit(&connp->conn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2859
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2860
	if (ire->ire_mp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2861
		ire_refrele(ire);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2862
	return (1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2863
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2864
error:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2865
	if (ire->ire_mp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2866
		ire_refrele(ire);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2867
	if (sire != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2868
		ire_refrele(sire);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2869
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2870
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2871
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2872
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2873
 * tcp_bind is called (holding the writer lock) by tcp_wput_proto to process a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2874
 * O_T_BIND_REQ/T_BIND_REQ message.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2875
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2876
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2877
tcp_bind(tcp_t *tcp, mblk_t *mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2878
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2879
	sin_t	*sin;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2880
	sin6_t	*sin6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2881
	mblk_t	*mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2882
	in_port_t requested_port;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2883
	in_port_t allocated_port;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2884
	struct T_bind_req *tbr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2885
	boolean_t	bind_to_req_port_only;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2886
	boolean_t	backlog_update = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2887
	boolean_t	user_specified;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2888
	in6_addr_t	v6addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2889
	ipaddr_t	v4addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2890
	uint_t	origipversion;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2891
	int	err;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2892
	queue_t *q = tcp->tcp_wq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2893
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2894
	ASSERT((uintptr_t)(mp->b_wptr - mp->b_rptr) <= (uintptr_t)INT_MAX);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2895
	if ((mp->b_wptr - mp->b_rptr) < sizeof (*tbr)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2896
		if (tcp->tcp_debug) {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  2897
			(void) strlog(TCP_MOD_ID, 0, 1, SL_ERROR|SL_TRACE,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2898
			    "tcp_bind: bad req, len %u",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2899
			    (uint_t)(mp->b_wptr - mp->b_rptr));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2900
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2901
		tcp_err_ack(tcp, mp, TPROTO, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2902
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2903
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2904
	/* Make sure the largest address fits */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2905
	mp1 = reallocb(mp, sizeof (struct T_bind_ack) + sizeof (sin6_t) + 1, 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2906
	if (mp1 == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2907
		tcp_err_ack(tcp, mp, TSYSERR, ENOMEM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2908
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2909
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2910
	mp = mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2911
	tbr = (struct T_bind_req *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2912
	if (tcp->tcp_state >= TCPS_BOUND) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2913
		if ((tcp->tcp_state == TCPS_BOUND ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2914
		    tcp->tcp_state == TCPS_LISTEN) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2915
		    tcp->tcp_conn_req_max != tbr->CONIND_number &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2916
		    tbr->CONIND_number > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2917
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2918
			 * Handle listen() increasing CONIND_number.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2919
			 * This is more "liberal" then what the TPI spec
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2920
			 * requires but is needed to avoid a t_unbind
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2921
			 * when handling listen() since the port number
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2922
			 * might be "stolen" between the unbind and bind.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2923
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2924
			backlog_update = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2925
			goto do_bind;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2926
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2927
		if (tcp->tcp_debug) {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  2928
			(void) strlog(TCP_MOD_ID, 0, 1, SL_ERROR|SL_TRACE,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2929
			    "tcp_bind: bad state, %d", tcp->tcp_state);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2930
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2931
		tcp_err_ack(tcp, mp, TOUTSTATE, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2932
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2933
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2934
	origipversion = tcp->tcp_ipversion;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2935
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2936
	switch (tbr->ADDR_length) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2937
	case 0:			/* request for a generic port */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2938
		tbr->ADDR_offset = sizeof (struct T_bind_req);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2939
		if (tcp->tcp_family == AF_INET) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2940
			tbr->ADDR_length = sizeof (sin_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2941
			sin = (sin_t *)&tbr[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2942
			*sin = sin_null;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2943
			sin->sin_family = AF_INET;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2944
			mp->b_wptr = (uchar_t *)&sin[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2945
			tcp->tcp_ipversion = IPV4_VERSION;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2946
			IN6_IPADDR_TO_V4MAPPED(INADDR_ANY, &v6addr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2947
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2948
			ASSERT(tcp->tcp_family == AF_INET6);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2949
			tbr->ADDR_length = sizeof (sin6_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2950
			sin6 = (sin6_t *)&tbr[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2951
			*sin6 = sin6_null;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2952
			sin6->sin6_family = AF_INET6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2953
			mp->b_wptr = (uchar_t *)&sin6[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2954
			tcp->tcp_ipversion = IPV6_VERSION;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2955
			V6_SET_ZERO(v6addr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2956
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2957
		requested_port = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2958
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2959
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2960
	case sizeof (sin_t):	/* Complete IPv4 address */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2961
		sin = (sin_t *)mi_offset_param(mp, tbr->ADDR_offset,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2962
		    sizeof (sin_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2963
		if (sin == NULL || !OK_32PTR((char *)sin)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2964
			if (tcp->tcp_debug) {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  2965
				(void) strlog(TCP_MOD_ID, 0, 1,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2966
				    SL_ERROR|SL_TRACE,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2967
				    "tcp_bind: bad address parameter, "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2968
				    "offset %d, len %d",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2969
				    tbr->ADDR_offset, tbr->ADDR_length);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2970
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2971
			tcp_err_ack(tcp, mp, TPROTO, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2972
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2973
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2974
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2975
		 * With sockets sockfs will accept bogus sin_family in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2976
		 * bind() and replace it with the family used in the socket
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2977
		 * call.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2978
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2979
		if (sin->sin_family != AF_INET ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2980
		    tcp->tcp_family != AF_INET) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2981
			tcp_err_ack(tcp, mp, TSYSERR, EAFNOSUPPORT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2982
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2983
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2984
		requested_port = ntohs(sin->sin_port);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2985
		tcp->tcp_ipversion = IPV4_VERSION;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2986
		v4addr = sin->sin_addr.s_addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2987
		IN6_IPADDR_TO_V4MAPPED(v4addr, &v6addr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2988
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2989
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2990
	case sizeof (sin6_t): /* Complete IPv6 address */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2991
		sin6 = (sin6_t *)mi_offset_param(mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2992
		    tbr->ADDR_offset, sizeof (sin6_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2993
		if (sin6 == NULL || !OK_32PTR((char *)sin6)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2994
			if (tcp->tcp_debug) {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  2995
				(void) strlog(TCP_MOD_ID, 0, 1,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2996
				    SL_ERROR|SL_TRACE,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2997
				    "tcp_bind: bad IPv6 address parameter, "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2998
				    "offset %d, len %d", tbr->ADDR_offset,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2999
				    tbr->ADDR_length);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3000
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3001
			tcp_err_ack(tcp, mp, TSYSERR, EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3002
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3003
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3004
		if (sin6->sin6_family != AF_INET6 ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3005
		    tcp->tcp_family != AF_INET6) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3006
			tcp_err_ack(tcp, mp, TSYSERR, EAFNOSUPPORT);
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
		requested_port = ntohs(sin6->sin6_port);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3010
		tcp->tcp_ipversion = IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr) ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3011
		    IPV4_VERSION : IPV6_VERSION;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3012
		v6addr = sin6->sin6_addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3013
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3014
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3015
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3016
		if (tcp->tcp_debug) {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  3017
			(void) strlog(TCP_MOD_ID, 0, 1, SL_ERROR|SL_TRACE,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3018
			    "tcp_bind: bad address length, %d",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3019
			    tbr->ADDR_length);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3020
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3021
		tcp_err_ack(tcp, mp, TBADADDR, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3022
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3023
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3024
	tcp->tcp_bound_source_v6 = v6addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3025
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3026
	/* Check for change in ipversion */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3027
	if (origipversion != tcp->tcp_ipversion) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3028
		ASSERT(tcp->tcp_family == AF_INET6);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3029
		err = tcp->tcp_ipversion == IPV6_VERSION ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3030
		    tcp_header_init_ipv6(tcp) : tcp_header_init_ipv4(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3031
		if (err) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3032
			tcp_err_ack(tcp, mp, TSYSERR, ENOMEM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3033
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3034
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3035
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3036
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3037
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3038
	 * Initialize family specific fields. Copy of the src addr.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3039
	 * in tcp_t is needed for the lookup funcs.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3040
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3041
	if (tcp->tcp_ipversion == IPV6_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3042
		tcp->tcp_ip6h->ip6_src = v6addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3043
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3044
		IN6_V4MAPPED_TO_IPADDR(&v6addr, tcp->tcp_ipha->ipha_src);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3045
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3046
	tcp->tcp_ip_src_v6 = v6addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3047
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3048
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3049
	 * For O_T_BIND_REQ:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3050
	 * Verify that the target port/addr is available, or choose
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3051
	 * another.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3052
	 * For  T_BIND_REQ:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3053
	 * Verify that the target port/addr is available or fail.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3054
	 * In both cases when it succeeds the tcp is inserted in the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3055
	 * bind hash table. This ensures that the operation is atomic
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3056
	 * under the lock on the hash bucket.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3057
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3058
	bind_to_req_port_only = requested_port != 0 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3059
	    tbr->PRIM_type != O_T_BIND_REQ;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3060
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3061
	 * Get a valid port (within the anonymous range and should not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3062
	 * be a privileged one) to use if the user has not given a port.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3063
	 * If multiple threads are here, they may all start with
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3064
	 * with the same initial port. But, it should be fine as long as
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3065
	 * tcp_bindi will ensure that no two threads will be assigned
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3066
	 * the same port.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3067
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3068
	 * NOTE: XXX If a privileged process asks for an anonymous port, we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3069
	 * still check for ports only in the range > tcp_smallest_non_priv_port,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3070
	 * unless TCP_ANONPRIVBIND option is set.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3071
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3072
	if (requested_port == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3073
		requested_port = tcp->tcp_anon_priv_bind ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3074
		    tcp_get_next_priv_port() :
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3075
		    tcp_update_next_port(tcp_next_port_to_try, B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3076
		user_specified = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3077
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3078
		int i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3079
		boolean_t priv = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3080
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3081
		 * If the requested_port is in the well-known privileged range,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3082
		 * verify that the stream was opened by a privileged user.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3083
		 * Note: No locks are held when inspecting tcp_g_*epriv_ports
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3084
		 * but instead the code relies on:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3085
		 * - the fact that the address of the array and its size never
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3086
		 *   changes
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3087
		 * - the atomic assignment of the elements of the array
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3088
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3089
		if (requested_port < tcp_smallest_nonpriv_port) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3090
			priv = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3091
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3092
			for (i = 0; i < tcp_g_num_epriv_ports; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3093
				if (requested_port ==
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3094
				    tcp_g_epriv_ports[i]) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3095
					priv = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3096
					break;
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
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3100
		if (priv) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3101
			cred_t *cr = DB_CREDDEF(mp, tcp->tcp_cred);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3102
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3103
			if (secpolicy_net_privaddr(cr, requested_port) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3104
				if (tcp->tcp_debug) {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  3105
					(void) strlog(TCP_MOD_ID, 0, 1,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3106
					    SL_ERROR|SL_TRACE,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3107
					    "tcp_bind: no priv for port %d",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3108
					    requested_port);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3109
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3110
				tcp_err_ack(tcp, mp, TACCES, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3111
				return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3112
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3113
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3114
		user_specified = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3115
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3116
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3117
	allocated_port = tcp_bindi(tcp, requested_port, &v6addr,
646
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  3118
	    tcp->tcp_reuseaddr, B_FALSE, bind_to_req_port_only, user_specified);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3119
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3120
	if (allocated_port == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3121
		if (bind_to_req_port_only) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3122
			if (tcp->tcp_debug) {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  3123
				(void) strlog(TCP_MOD_ID, 0, 1,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3124
				    SL_ERROR|SL_TRACE,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3125
				    "tcp_bind: requested addr busy");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3126
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3127
			tcp_err_ack(tcp, mp, TADDRBUSY, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3128
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3129
			/* If we are out of ports, fail the bind. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3130
			if (tcp->tcp_debug) {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  3131
				(void) strlog(TCP_MOD_ID, 0, 1,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3132
				    SL_ERROR|SL_TRACE,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3133
				    "tcp_bind: out of ports?");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3134
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3135
			tcp_err_ack(tcp, mp, TNOADDR, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3136
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3137
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3138
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3139
	ASSERT(tcp->tcp_state == TCPS_BOUND);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3140
do_bind:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3141
	if (!backlog_update) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3142
		if (tcp->tcp_family == AF_INET)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3143
			sin->sin_port = htons(allocated_port);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3144
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3145
			sin6->sin6_port = htons(allocated_port);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3146
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3147
	if (tcp->tcp_family == AF_INET) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3148
		if (tbr->CONIND_number != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3149
			mp1 = tcp_ip_bind_mp(tcp, tbr->PRIM_type,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3150
			    sizeof (sin_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3151
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3152
			/* Just verify the local IP address */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3153
			mp1 = tcp_ip_bind_mp(tcp, tbr->PRIM_type, IP_ADDR_LEN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3154
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3155
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3156
		if (tbr->CONIND_number != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3157
			mp1 = tcp_ip_bind_mp(tcp, tbr->PRIM_type,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3158
			    sizeof (sin6_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3159
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3160
			/* Just verify the local IP address */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3161
			mp1 = tcp_ip_bind_mp(tcp, tbr->PRIM_type,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3162
			    IPV6_ADDR_LEN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3163
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3164
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3165
	if (!mp1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3166
		tcp_err_ack(tcp, mp, TSYSERR, ENOMEM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3167
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3168
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3169
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3170
	tbr->PRIM_type = T_BIND_ACK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3171
	mp->b_datap->db_type = M_PCPROTO;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3172
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3173
	/* Chain in the reply mp for tcp_rput() */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3174
	mp1->b_cont = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3175
	mp = mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3176
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3177
	tcp->tcp_conn_req_max = tbr->CONIND_number;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3178
	if (tcp->tcp_conn_req_max) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3179
		if (tcp->tcp_conn_req_max < tcp_conn_req_min)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3180
			tcp->tcp_conn_req_max = tcp_conn_req_min;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3181
		if (tcp->tcp_conn_req_max > tcp_conn_req_max_q)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3182
			tcp->tcp_conn_req_max = tcp_conn_req_max_q;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3183
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3184
		 * If this is a listener, do not reset the eager list
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3185
		 * and other stuffs.  Note that we don't check if the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3186
		 * existing eager list meets the new tcp_conn_req_max
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3187
		 * requirement.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3188
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3189
		if (tcp->tcp_state != TCPS_LISTEN) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3190
			tcp->tcp_state = TCPS_LISTEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3191
			/* Initialize the chain. Don't need the eager_lock */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3192
			tcp->tcp_eager_next_q0 = tcp->tcp_eager_prev_q0 = tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3193
			tcp->tcp_second_ctimer_threshold =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3194
			    tcp_ip_abort_linterval;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3195
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3196
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3197
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3198
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3199
	 * We can call ip_bind directly which returns a T_BIND_ACK mp. The
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3200
	 * processing continues in tcp_rput_other().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3201
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3202
	if (tcp->tcp_family == AF_INET6) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3203
		ASSERT(tcp->tcp_connp->conn_af_isv6);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3204
		mp = ip_bind_v6(q, mp, tcp->tcp_connp, &tcp->tcp_sticky_ipp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3205
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3206
		ASSERT(!tcp->tcp_connp->conn_af_isv6);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3207
		mp = ip_bind_v4(q, mp, 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
	 * If the bind cannot complete immediately
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3211
	 * IP will arrange to call tcp_rput_other
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3212
	 * when the bind completes.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3213
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3214
	if (mp != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3215
		tcp_rput_other(tcp, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3216
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3217
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3218
		 * Bind will be resumed later. Need to ensure
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3219
		 * that conn doesn't disappear when that happens.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3220
		 * This will be decremented in ip_resume_tcp_bind().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3221
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3222
		CONN_INC_REF(tcp->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3223
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3224
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3225
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3226
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3227
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3228
 * If the "bind_to_req_port_only" parameter is set, if the requested port
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3229
 * number is available, return it, If not return 0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3230
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3231
 * If "bind_to_req_port_only" parameter is not set and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3232
 * If the requested port number is available, return it.  If not, return
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3233
 * the first anonymous port we happen across.  If no anonymous ports are
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3234
 * available, return 0. addr is the requested local address, if any.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3235
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3236
 * In either case, when succeeding update the tcp_t to record the port number
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3237
 * and insert it in the bind hash table.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3238
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3239
 * Note that TCP over IPv4 and IPv6 sockets can use the same port number
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3240
 * without setting SO_REUSEADDR. This is needed so that they
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3241
 * can be viewed as two independent transport protocols.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3242
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3243
static in_port_t
646
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  3244
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
  3245
    int reuseaddr, boolean_t quick_connect,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3246
    boolean_t bind_to_req_port_only, boolean_t user_specified)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3247
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3248
	/* number of times we have run around the loop */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3249
	int count = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3250
	/* maximum number of times to run around the loop */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3251
	int loopmax;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3252
	zoneid_t zoneid = tcp->tcp_connp->conn_zoneid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3253
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3254
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3255
	 * Lookup for free addresses is done in a loop and "loopmax"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3256
	 * influences how long we spin in the loop
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3257
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3258
	if (bind_to_req_port_only) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3259
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3260
		 * If the requested port is busy, don't bother to look
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3261
		 * for a new one. Setting loop maximum count to 1 has
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3262
		 * that effect.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3263
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3264
		loopmax = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3265
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3266
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3267
		 * If the requested port is busy, look for a free one
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3268
		 * in the anonymous port range.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3269
		 * Set loopmax appropriately so that one does not look
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3270
		 * forever in the case all of the anonymous ports are in use.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3271
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3272
		if (tcp->tcp_anon_priv_bind) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3273
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3274
			 * loopmax =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3275
			 * 	(IPPORT_RESERVED-1) - tcp_min_anonpriv_port + 1
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3276
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3277
			loopmax = IPPORT_RESERVED - tcp_min_anonpriv_port;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3278
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3279
			loopmax = (tcp_largest_anon_port -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3280
			    tcp_smallest_anon_port + 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3281
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3282
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3283
	do {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3284
		uint16_t	lport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3285
		tf_t		*tbf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3286
		tcp_t		*ltcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3287
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3288
		lport = htons(port);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3289
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3290
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3291
		 * Ensure that the tcp_t is not currently in the bind hash.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3292
		 * Hold the lock on the hash bucket to ensure that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3293
		 * the duplicate check plus the insertion is an atomic
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3294
		 * operation.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3295
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3296
		 * This function does an inline lookup on the bind hash list
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3297
		 * Make sure that we access only members of tcp_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3298
		 * and that we don't look at tcp_tcp, since we are not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3299
		 * doing a CONN_INC_REF.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3300
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3301
		tcp_bind_hash_remove(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3302
		tbf = &tcp_bind_fanout[TCP_BIND_HASH(lport)];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3303
		mutex_enter(&tbf->tf_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3304
		for (ltcp = tbf->tf_tcp; ltcp != NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3305
		    ltcp = ltcp->tcp_bind_hash) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3306
			if (lport != ltcp->tcp_lport ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3307
			    ltcp->tcp_connp->conn_zoneid != zoneid) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3308
				continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3309
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3310
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3311
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3312
			 * If TCP_EXCLBIND is set for either the bound or
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3313
			 * binding endpoint, the semantics of bind
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3314
			 * is changed according to the following.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3315
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3316
			 * spec = specified address (v4 or v6)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3317
			 * unspec = unspecified address (v4 or v6)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3318
			 * A = specified addresses are different for endpoints
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3319
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3320
			 * bound	bind to		allowed
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3321
			 * -------------------------------------
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3322
			 * unspec	unspec		no
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3323
			 * unspec	spec		no
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3324
			 * spec		unspec		no
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3325
			 * spec		spec		yes if A
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3326
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3327
			 * Note:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3328
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3329
			 * 1. Because of TLI semantics, an endpoint can go
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3330
			 * back from, say TCP_ESTABLISHED to TCPS_LISTEN or
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3331
			 * TCPS_BOUND, depending on whether it is originally
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3332
			 * a listener or not.  That is why we need to check
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3333
			 * for states greater than or equal to TCPS_BOUND
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3334
			 * here.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3335
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3336
			 * 2. Ideally, we should only check for state equals
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3337
			 * to TCPS_LISTEN. And the following check should be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3338
			 * added.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3339
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3340
			 * if (ltcp->tcp_state == TCPS_LISTEN ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3341
			 *	!reuseaddr || !ltcp->tcp_reuseaddr) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3342
			 *		...
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3343
			 * }
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3344
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3345
			 * The semantics will be changed to this.  If the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3346
			 * endpoint on the list is in state not equal to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3347
			 * TCPS_LISTEN and both endpoints have SO_REUSEADDR
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3348
			 * set, let the bind succeed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3349
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3350
			 * But because of (1), we cannot do that now.  If
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3351
			 * in future, we can change this going back semantics,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3352
			 * we can add the above check.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3353
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3354
			if (ltcp->tcp_exclbind || tcp->tcp_exclbind) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3355
				if (V6_OR_V4_INADDR_ANY(
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3356
				    ltcp->tcp_bound_source_v6) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3357
				    V6_OR_V4_INADDR_ANY(*laddr) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3358
				    IN6_ARE_ADDR_EQUAL(laddr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3359
				    &ltcp->tcp_bound_source_v6)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3360
					break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3361
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3362
				continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3363
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3364
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3365
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3366
			 * Check ipversion to allow IPv4 and IPv6 sockets to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3367
			 * have disjoint port number spaces, if *_EXCLBIND
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3368
			 * is not set and only if the application binds to a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3369
			 * specific port. We use the same autoassigned port
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3370
			 * number space for IPv4 and IPv6 sockets.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3371
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3372
			if (tcp->tcp_ipversion != ltcp->tcp_ipversion &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3373
			    bind_to_req_port_only)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3374
				continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3375
646
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  3376
			/*
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  3377
			 * Ideally, we should make sure that the source
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  3378
			 * address, remote address, and remote port in the
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  3379
			 * four tuple for this tcp-connection is unique.
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  3380
			 * However, trying to find out the local source
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  3381
			 * address would require too much code duplication
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  3382
			 * 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
  3383
			 * to support userland TCP implementations.
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  3384
			 */
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  3385
			if (quick_connect &&
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  3386
			    (ltcp->tcp_state > TCPS_LISTEN) &&
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  3387
			    ((tcp->tcp_fport != ltcp->tcp_fport) ||
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  3388
				!IN6_ARE_ADDR_EQUAL(&tcp->tcp_remote_v6,
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  3389
				    &ltcp->tcp_remote_v6)))
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  3390
				continue;
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  3391
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3392
			if (!reuseaddr) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3393
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3394
				 * No socket option SO_REUSEADDR.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3395
				 * If existing port is bound to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3396
				 * a non-wildcard IP address
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3397
				 * and the requesting stream is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3398
				 * bound to a distinct
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3399
				 * different IP addresses
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3400
				 * (non-wildcard, also), keep
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3401
				 * going.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3402
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3403
				if (!V6_OR_V4_INADDR_ANY(*laddr) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3404
				    !V6_OR_V4_INADDR_ANY(
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3405
				    ltcp->tcp_bound_source_v6) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3406
				    !IN6_ARE_ADDR_EQUAL(laddr,
646
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  3407
					&ltcp->tcp_bound_source_v6))
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3408
					continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3409
				if (ltcp->tcp_state >= TCPS_BOUND) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3410
					/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3411
					 * This port is being used and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3412
					 * its state is >= TCPS_BOUND,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3413
					 * so we can't bind to it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3414
					 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3415
					break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3416
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3417
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3418
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3419
				 * socket option SO_REUSEADDR is set on the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3420
				 * binding tcp_t.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3421
				 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3422
				 * If two streams are bound to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3423
				 * same IP address or both addr
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3424
				 * and bound source are wildcards
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3425
				 * (INADDR_ANY), we want to stop
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3426
				 * searching.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3427
				 * We have found a match of IP source
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3428
				 * address and source port, which is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3429
				 * refused regardless of the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3430
				 * SO_REUSEADDR setting, so we break.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3431
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3432
				if (IN6_ARE_ADDR_EQUAL(laddr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3433
				    &ltcp->tcp_bound_source_v6) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3434
				    (ltcp->tcp_state == TCPS_LISTEN ||
646
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  3435
					ltcp->tcp_state == TCPS_BOUND))
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3436
					break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3437
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3438
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3439
		if (ltcp != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3440
			/* The port number is busy */
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
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3443
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3444
			 * This port is ours. Insert in fanout and mark as
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3445
			 * bound to prevent others from getting the port
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3446
			 * number.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3447
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3448
			tcp->tcp_state = TCPS_BOUND;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3449
			tcp->tcp_lport = htons(port);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3450
			*(uint16_t *)tcp->tcp_tcph->th_lport = tcp->tcp_lport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3451
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3452
			ASSERT(&tcp_bind_fanout[TCP_BIND_HASH(
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3453
			    tcp->tcp_lport)] == tbf);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3454
			tcp_bind_hash_insert(tbf, tcp, 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3455
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3456
			mutex_exit(&tbf->tf_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3457
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3458
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3459
			 * We don't want tcp_next_port_to_try to "inherit"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3460
			 * a port number supplied by the user in a bind.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3461
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3462
			if (user_specified)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3463
				return (port);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3464
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3465
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3466
			 * This is the only place where tcp_next_port_to_try
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3467
			 * is updated. After the update, it may or may not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3468
			 * be in the valid range.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3469
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3470
			if (!tcp->tcp_anon_priv_bind)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3471
				tcp_next_port_to_try = port + 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3472
			return (port);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3473
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3474
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3475
		if (tcp->tcp_anon_priv_bind) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3476
			port = tcp_get_next_priv_port();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3477
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3478
			if (count == 0 && user_specified) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3479
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3480
				 * We may have to return an anonymous port. So
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3481
				 * get one to start with.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3482
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3483
				port =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3484
				    tcp_update_next_port(tcp_next_port_to_try,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3485
					B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3486
				user_specified = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3487
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3488
				port = tcp_update_next_port(port + 1, B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3489
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3490
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3491
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3492
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3493
		 * Don't let this loop run forever in the case where
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3494
		 * all of the anonymous ports are in use.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3495
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3496
	} while (++count < loopmax);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3497
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3498
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3499
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3500
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3501
 * We are dying for some reason.  Try to do it gracefully.  (May be called
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3502
 * as writer.)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3503
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3504
 * Return -1 if the structure was not cleaned up (if the cleanup had to be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3505
 * done by a service procedure).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3506
 * TBD - Should the return value distinguish between the tcp_t being
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3507
 * freed and it being reinitialized?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3508
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3509
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3510
tcp_clean_death(tcp_t *tcp, int err, uint8_t tag)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3511
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3512
	mblk_t	*mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3513
	queue_t	*q;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3514
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3515
	TCP_CLD_STAT(tag);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3516
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3517
#if TCP_TAG_CLEAN_DEATH
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3518
	tcp->tcp_cleandeathtag = tag;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3519
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3520
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3521
	if (tcp->tcp_linger_tid != 0 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3522
	    TCP_TIMER_CANCEL(tcp, tcp->tcp_linger_tid) >= 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3523
		tcp_stop_lingering(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3524
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3525
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3526
	ASSERT(tcp != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3527
	ASSERT((tcp->tcp_family == AF_INET &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3528
	    tcp->tcp_ipversion == IPV4_VERSION) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3529
	    (tcp->tcp_family == AF_INET6 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3530
	    (tcp->tcp_ipversion == IPV4_VERSION ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3531
	    tcp->tcp_ipversion == IPV6_VERSION)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3532
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3533
	if (TCP_IS_DETACHED(tcp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3534
		if (tcp->tcp_hard_binding) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3535
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3536
			 * Its an eager that we are dealing with. We close the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3537
			 * eager but in case a conn_ind has already gone to the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3538
			 * listener, let tcp_accept_finish() send a discon_ind
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3539
			 * to the listener and drop the last reference. If the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3540
			 * listener doesn't even know about the eager i.e. the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3541
			 * conn_ind hasn't gone up, blow away the eager and drop
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3542
			 * the last reference as well. If the conn_ind has gone
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3543
			 * up, state should be BOUND. tcp_accept_finish
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3544
			 * will figure out that the connection has received a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3545
			 * RST and will send a DISCON_IND to the application.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3546
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3547
			tcp_closei_local(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3548
			if (tcp->tcp_conn.tcp_eager_conn_ind != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3549
				CONN_DEC_REF(tcp->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3550
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3551
				tcp->tcp_state = TCPS_BOUND;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3552
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3553
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3554
			tcp_close_detached(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3555
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3556
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3557
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3558
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3559
	TCP_STAT(tcp_clean_death_nondetached);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3560
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3561
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3562
	 * If T_ORDREL_IND has not been sent yet (done when service routine
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3563
	 * is run) postpone cleaning up the endpoint until service routine
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3564
	 * has sent up the T_ORDREL_IND. Avoid clearing out an existing
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3565
	 * client_errno since tcp_close uses the client_errno field.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3566
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3567
	if (tcp->tcp_fin_rcvd && !tcp->tcp_ordrel_done) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3568
		if (err != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3569
			tcp->tcp_client_errno = err;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3570
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3571
		tcp->tcp_deferred_clean_death = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3572
		return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3573
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3574
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3575
	q = tcp->tcp_rq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3576
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3577
	/* Trash all inbound data */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3578
	flushq(q, FLUSHALL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3579
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3580
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3581
	 * If we are at least part way open and there is error
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3582
	 * (err==0 implies no error)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3583
	 * notify our client by a T_DISCON_IND.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3584
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3585
	if ((tcp->tcp_state >= TCPS_SYN_SENT) && err) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3586
		if (tcp->tcp_state >= TCPS_ESTABLISHED &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3587
		    !TCP_IS_SOCKET(tcp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3588
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3589
			 * Send M_FLUSH according to TPI. Because sockets will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3590
			 * (and must) ignore FLUSHR we do that only for TPI
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3591
			 * endpoints and sockets in STREAMS mode.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3592
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3593
			(void) putnextctl1(q, M_FLUSH, FLUSHR);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3594
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3595
		if (tcp->tcp_debug) {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  3596
			(void) strlog(TCP_MOD_ID, 0, 1, SL_TRACE|SL_ERROR,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3597
			    "tcp_clean_death: discon err %d", err);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3598
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3599
		mp = mi_tpi_discon_ind(NULL, err, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3600
		if (mp != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3601
			putnext(q, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3602
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3603
			if (tcp->tcp_debug) {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  3604
				(void) strlog(TCP_MOD_ID, 0, 1,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3605
				    SL_ERROR|SL_TRACE,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3606
				    "tcp_clean_death, sending M_ERROR");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3607
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3608
			(void) putnextctl1(q, M_ERROR, EPROTO);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3609
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3610
		if (tcp->tcp_state <= TCPS_SYN_RCVD) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3611
			/* SYN_SENT or SYN_RCVD */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3612
			BUMP_MIB(&tcp_mib, tcpAttemptFails);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3613
		} else if (tcp->tcp_state <= TCPS_CLOSE_WAIT) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3614
			/* ESTABLISHED or CLOSE_WAIT */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3615
			BUMP_MIB(&tcp_mib, tcpEstabResets);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3616
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3617
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3618
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3619
	tcp_reinit(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3620
	return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3621
}
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
 * In case tcp is in the "lingering state" and waits for the SO_LINGER timeout
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3625
 * to expire, stop the wait and finish the close.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3626
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3627
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3628
tcp_stop_lingering(tcp_t *tcp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3629
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3630
	clock_t	delta = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3631
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3632
	tcp->tcp_linger_tid = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3633
	if (tcp->tcp_state > TCPS_LISTEN) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3634
		tcp_acceptor_hash_remove(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3635
		if (tcp->tcp_flow_stopped) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3636
			tcp_clrqfull(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3637
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3638
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3639
		if (tcp->tcp_timer_tid != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3640
			delta = TCP_TIMER_CANCEL(tcp, tcp->tcp_timer_tid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3641
			tcp->tcp_timer_tid = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3642
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3643
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3644
		 * Need to cancel those timers which will not be used when
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3645
		 * TCP is detached.  This has to be done before the tcp_wq
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3646
		 * is set to the global queue.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3647
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3648
		tcp_timers_stop(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3649
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3650
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3651
		tcp->tcp_detached = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3652
		tcp->tcp_rq = tcp_g_q;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3653
		tcp->tcp_wq = WR(tcp_g_q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3654
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3655
		if (tcp->tcp_state == TCPS_TIME_WAIT) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3656
			tcp_time_wait_append(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3657
			TCP_DBGSTAT(tcp_detach_time_wait);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3658
			goto finish;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3659
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3660
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3661
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3662
		 * If delta is zero the timer event wasn't executed and was
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3663
		 * successfully canceled. In this case we need to restart it
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3664
		 * with the minimal delta possible.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3665
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3666
		if (delta >= 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3667
			tcp->tcp_timer_tid = TCP_TIMER(tcp, tcp_timer,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3668
			    delta ? delta : 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3669
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3670
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3671
		tcp_closei_local(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3672
		CONN_DEC_REF(tcp->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3673
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3674
finish:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3675
	/* Signal closing thread that it can complete close */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3676
	mutex_enter(&tcp->tcp_closelock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3677
	tcp->tcp_detached = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3678
	tcp->tcp_rq = tcp_g_q;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3679
	tcp->tcp_wq = WR(tcp_g_q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3680
	tcp->tcp_closed = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3681
	cv_signal(&tcp->tcp_closecv);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3682
	mutex_exit(&tcp->tcp_closelock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3683
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3684
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3685
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3686
 * Handle lingering timeouts. This function is called when the SO_LINGER timeout
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3687
 * expires.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3688
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3689
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3690
tcp_close_linger_timeout(void *arg)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3691
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3692
	conn_t	*connp = (conn_t *)arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3693
	tcp_t 	*tcp = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3694
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3695
	tcp->tcp_client_errno = ETIMEDOUT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3696
	tcp_stop_lingering(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3697
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3698
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3699
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3700
tcp_close(queue_t *q, int flags)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3701
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3702
	conn_t		*connp = Q_TO_CONN(q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3703
	tcp_t		*tcp = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3704
	mblk_t 		*mp = &tcp->tcp_closemp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3705
	boolean_t	conn_ioctl_cleanup_reqd = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3706
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3707
	ASSERT(WR(q)->q_next == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3708
	ASSERT(connp->conn_ref >= 2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3709
	ASSERT((connp->conn_flags & IPCL_TCPMOD) == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3710
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3711
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3712
	 * We are being closed as /dev/tcp or /dev/tcp6.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3713
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3714
	 * Mark the conn as closing. ill_pending_mp_add will not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3715
	 * add any mp to the pending mp list, after this conn has
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3716
	 * started closing. Same for sq_pending_mp_add
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3717
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3718
	mutex_enter(&connp->conn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3719
	connp->conn_state_flags |= CONN_CLOSING;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3720
	if (connp->conn_oper_pending_ill != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3721
		conn_ioctl_cleanup_reqd = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3722
	CONN_INC_REF_LOCKED(connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3723
	mutex_exit(&connp->conn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3724
	tcp->tcp_closeflags = (uint8_t)flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3725
	ASSERT(connp->conn_ref >= 3);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3726
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3727
	(*tcp_squeue_close_proc)(connp->conn_sqp, mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3728
	    tcp_close_output, connp, SQTAG_IP_TCP_CLOSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3729
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3730
	mutex_enter(&tcp->tcp_closelock);
898
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
  3731
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3732
	while (!tcp->tcp_closed)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3733
		cv_wait(&tcp->tcp_closecv, &tcp->tcp_closelock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3734
	mutex_exit(&tcp->tcp_closelock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3735
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3736
	 * In the case of listener streams that have eagers in the q or q0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3737
	 * we wait for the eagers to drop their reference to us. tcp_rq and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3738
	 * tcp_wq of the eagers point to our queues. By waiting for the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3739
	 * refcnt to drop to 1, we are sure that the eagers have cleaned
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3740
	 * up their queue pointers and also dropped their references to us.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3741
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3742
	if (tcp->tcp_wait_for_eagers) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3743
		mutex_enter(&connp->conn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3744
		while (connp->conn_ref != 1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3745
			cv_wait(&connp->conn_cv, &connp->conn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3746
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3747
		mutex_exit(&connp->conn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3748
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3749
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3750
	 * ioctl cleanup. The mp is queued in the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3751
	 * ill_pending_mp or in the sq_pending_mp.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3752
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3753
	if (conn_ioctl_cleanup_reqd)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3754
		conn_ioctl_cleanup(connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3755
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3756
	qprocsoff(q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3757
	inet_minor_free(ip_minor_arena, connp->conn_dev);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3758
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3759
	ASSERT(connp->conn_cred != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3760
	crfree(connp->conn_cred);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3761
	tcp->tcp_cred = connp->conn_cred = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3762
	tcp->tcp_cpid = -1;
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
	 * Drop IP's reference on the conn. This is the last reference
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3766
	 * on the connp if the state was less than established. If the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3767
	 * connection has gone into timewait state, then we will have
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3768
	 * one ref for the TCP and one more ref (total of two) for the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3769
	 * classifier connected hash list (a timewait connections stays
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3770
	 * in connected hash till closed).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3771
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3772
	 * We can't assert the references because there might be other
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3773
	 * transient reference places because of some walkers or queued
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3774
	 * packets in squeue for the timewait state.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3775
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3776
	CONN_DEC_REF(connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3777
	q->q_ptr = WR(q)->q_ptr = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3778
	return (0);
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
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3782
tcpclose_accept(queue_t *q)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3783
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3784
	ASSERT(WR(q)->q_qinfo == &tcp_acceptor_winit);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3785
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3786
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3787
	 * We had opened an acceptor STREAM for sockfs which is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3788
	 * now being closed due to some error.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3789
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3790
	qprocsoff(q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3791
	inet_minor_free(ip_minor_arena, (dev_t)q->q_ptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3792
	q->q_ptr = WR(q)->q_ptr = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3793
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3794
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3795
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3796
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3797
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3798
 * Called by streams close routine via squeues when our client blows off her
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3799
 * descriptor, we take this to mean: "close the stream state NOW, close the tcp
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3800
 * connection politely" When SO_LINGER is set (with a non-zero linger time and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3801
 * it is not a nonblocking socket) then this routine sleeps until the FIN is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3802
 * acked.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3803
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3804
 * NOTE: tcp_close potentially returns error when lingering.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3805
 * However, the stream head currently does not pass these errors
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3806
 * to the application. 4.4BSD only returns EINTR and EWOULDBLOCK
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3807
 * errors to the application (from tsleep()) and not errors
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3808
 * like ECONNRESET caused by receiving a reset packet.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3809
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3810
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3811
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3812
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3813
tcp_close_output(void *arg, mblk_t *mp, void *arg2)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3814
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3815
	char	*msg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3816
	conn_t	*connp = (conn_t *)arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3817
	tcp_t	*tcp = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3818
	clock_t	delta = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3819
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3820
	ASSERT((connp->conn_fanout != NULL && connp->conn_ref >= 4) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3821
	    (connp->conn_fanout == NULL && connp->conn_ref >= 3));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3822
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3823
	/* Cancel any pending timeout */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3824
	if (tcp->tcp_ordrelid != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3825
		if (tcp->tcp_timeout) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3826
			(void) TCP_TIMER_CANCEL(tcp, tcp->tcp_ordrelid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3827
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3828
		tcp->tcp_ordrelid = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3829
		tcp->tcp_timeout = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3830
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3831
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3832
	mutex_enter(&tcp->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3833
	if (tcp->tcp_conn_req_cnt_q0 != 0 || tcp->tcp_conn_req_cnt_q != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3834
		/* Cleanup for listener */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3835
		tcp_eager_cleanup(tcp, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3836
		tcp->tcp_wait_for_eagers = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3837
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3838
	mutex_exit(&tcp->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3839
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3840
	connp->conn_mdt_ok = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3841
	tcp->tcp_mdt = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3842
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3843
	msg = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3844
	switch (tcp->tcp_state) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3845
	case TCPS_CLOSED:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3846
	case TCPS_IDLE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3847
	case TCPS_BOUND:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3848
	case TCPS_LISTEN:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3849
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3850
	case TCPS_SYN_SENT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3851
		msg = "tcp_close, during connect";
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3852
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3853
	case TCPS_SYN_RCVD:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3854
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3855
		 * Close during the connect 3-way handshake
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3856
		 * but here there may or may not be pending data
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3857
		 * already on queue. Process almost same as in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3858
		 * the ESTABLISHED state.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3859
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3860
		/* FALLTHRU */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3861
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3862
		if (tcp->tcp_fused)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3863
			tcp_unfuse(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3864
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3865
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3866
		 * If SO_LINGER has set a zero linger time, abort the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3867
		 * connection with a reset.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3868
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3869
		if (tcp->tcp_linger && tcp->tcp_lingertime == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3870
			msg = "tcp_close, zero lingertime";
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3871
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3872
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3873
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3874
		ASSERT(tcp->tcp_hard_bound || tcp->tcp_hard_binding);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3875
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3876
		 * Abort connection if there is unread data queued.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3877
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3878
		if (tcp->tcp_rcv_list || tcp->tcp_reass_head) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3879
			msg = "tcp_close, unread data";
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3880
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3881
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3882
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3883
		 * tcp_hard_bound is now cleared thus all packets go through
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3884
		 * tcp_lookup. This fact is used by tcp_detach below.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3885
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3886
		 * We have done a qwait() above which could have possibly
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3887
		 * drained more messages in turn causing transition to a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3888
		 * different state. Check whether we have to do the rest
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3889
		 * of the processing or not.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3890
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3891
		if (tcp->tcp_state <= TCPS_LISTEN)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3892
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3893
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3894
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3895
		 * Transmit the FIN before detaching the tcp_t.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3896
		 * After tcp_detach returns this queue/perimeter
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3897
		 * no longer owns the tcp_t thus others can modify it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3898
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3899
		(void) tcp_xmit_end(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3900
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3901
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3902
		 * If lingering on close then wait until the fin is acked,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3903
		 * the SO_LINGER time passes, or a reset is sent/received.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3904
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3905
		if (tcp->tcp_linger && tcp->tcp_lingertime > 0 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3906
		    !(tcp->tcp_fin_acked) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3907
		    tcp->tcp_state >= TCPS_ESTABLISHED) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3908
			if (tcp->tcp_closeflags & (FNDELAY|FNONBLOCK)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3909
				tcp->tcp_client_errno = EWOULDBLOCK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3910
			} else if (tcp->tcp_client_errno == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3911
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3912
				ASSERT(tcp->tcp_linger_tid == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3913
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3914
				tcp->tcp_linger_tid = TCP_TIMER(tcp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3915
				    tcp_close_linger_timeout,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3916
				    tcp->tcp_lingertime * hz);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3917
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3918
				/* tcp_close_linger_timeout will finish close */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3919
				if (tcp->tcp_linger_tid == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3920
					tcp->tcp_client_errno = ENOSR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3921
				else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3922
					return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3923
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3924
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3925
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3926
			 * Check if we need to detach or just close
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3927
			 * the instance.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3928
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3929
			if (tcp->tcp_state <= TCPS_LISTEN)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3930
				break;
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
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3934
		 * Make sure that no other thread will access the tcp_rq of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3935
		 * this instance (through lookups etc.) as tcp_rq will go
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3936
		 * away shortly.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3937
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3938
		tcp_acceptor_hash_remove(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3939
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3940
		if (tcp->tcp_flow_stopped) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3941
			tcp_clrqfull(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3942
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3943
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3944
		if (tcp->tcp_timer_tid != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3945
			delta = TCP_TIMER_CANCEL(tcp, tcp->tcp_timer_tid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3946
			tcp->tcp_timer_tid = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3947
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3948
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3949
		 * Need to cancel those timers which will not be used when
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3950
		 * TCP is detached.  This has to be done before the tcp_wq
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3951
		 * is set to the global queue.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3952
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3953
		tcp_timers_stop(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3954
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3955
		tcp->tcp_detached = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3956
		if (tcp->tcp_state == TCPS_TIME_WAIT) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3957
			tcp_time_wait_append(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3958
			TCP_DBGSTAT(tcp_detach_time_wait);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3959
			ASSERT(connp->conn_ref >= 3);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3960
			goto finish;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3961
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3962
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3963
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3964
		 * If delta is zero the timer event wasn't executed and was
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3965
		 * successfully canceled. In this case we need to restart it
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3966
		 * with the minimal delta possible.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3967
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3968
		if (delta >= 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3969
			tcp->tcp_timer_tid = TCP_TIMER(tcp, tcp_timer,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3970
			    delta ? delta : 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3971
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3972
		ASSERT(connp->conn_ref >= 3);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3973
		goto finish;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3974
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3975
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3976
	/* Detach did not complete. Still need to remove q from stream. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3977
	if (msg) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3978
		if (tcp->tcp_state == TCPS_ESTABLISHED ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3979
		    tcp->tcp_state == TCPS_CLOSE_WAIT)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3980
			BUMP_MIB(&tcp_mib, tcpEstabResets);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3981
		if (tcp->tcp_state == TCPS_SYN_SENT ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3982
		    tcp->tcp_state == TCPS_SYN_RCVD)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3983
			BUMP_MIB(&tcp_mib, tcpAttemptFails);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3984
		tcp_xmit_ctl(msg, tcp,  tcp->tcp_snxt, 0, TH_RST);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3985
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3986
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3987
	tcp_closei_local(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3988
	CONN_DEC_REF(connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3989
	ASSERT(connp->conn_ref >= 2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3990
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3991
finish:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3992
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3993
	 * Although packets are always processed on the correct
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3994
	 * tcp's perimeter and access is serialized via squeue's,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3995
	 * IP still needs a queue when sending packets in time_wait
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3996
	 * state so use WR(tcp_g_q) till ip_output() can be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3997
	 * changed to deal with just connp. For read side, we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3998
	 * could have set tcp_rq to NULL but there are some cases
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3999
	 * in tcp_rput_data() from early days of this code which
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4000
	 * do a putnext without checking if tcp is closed. Those
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4001
	 * need to be identified before both tcp_rq and tcp_wq
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4002
	 * can be set to NULL and tcp_q_q can disappear forever.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4003
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4004
	mutex_enter(&tcp->tcp_closelock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4005
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4006
	 * Don't change the queues in the case of a listener that has
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4007
	 * eagers in its q or q0. It could surprise the eagers.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4008
	 * Instead wait for the eagers outside the squeue.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4009
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4010
	if (!tcp->tcp_wait_for_eagers) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4011
		tcp->tcp_detached = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4012
		tcp->tcp_rq = tcp_g_q;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4013
		tcp->tcp_wq = WR(tcp_g_q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4014
	}
898
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
  4015
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4016
	/* Signal tcp_close() to finish closing. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4017
	tcp->tcp_closed = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4018
	cv_signal(&tcp->tcp_closecv);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4019
	mutex_exit(&tcp->tcp_closelock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4020
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4021
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4022
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4023
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4024
 * 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
  4025
 * Some stream heads get upset if they see these later on as anything but NULL.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4026
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4027
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4028
tcp_close_mpp(mblk_t **mpp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4029
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4030
	mblk_t	*mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4031
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4032
	if ((mp = *mpp) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4033
		do {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4034
			mp->b_next = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4035
			mp->b_prev = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4036
		} while ((mp = mp->b_cont) != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4037
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4038
		mp = *mpp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4039
		*mpp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4040
		freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4041
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4042
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4043
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4044
/* Do detached close. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4045
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4046
tcp_close_detached(tcp_t *tcp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4047
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4048
	if (tcp->tcp_fused)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4049
		tcp_unfuse(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4050
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4051
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4052
	 * Clustering code serializes TCP disconnect callbacks and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4053
	 * cluster tcp list walks by blocking a TCP disconnect callback
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4054
	 * if a cluster tcp list walk is in progress. This ensures
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4055
	 * accurate accounting of TCPs in the cluster code even though
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4056
	 * the TCP list walk itself is not atomic.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4057
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4058
	tcp_closei_local(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4059
	CONN_DEC_REF(tcp->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4060
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4061
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4062
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4063
 * Stop all TCP timers, and free the timer mblks if requested.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4064
 */
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  4065
void
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4066
tcp_timers_stop(tcp_t *tcp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4067
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4068
	if (tcp->tcp_timer_tid != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4069
		(void) TCP_TIMER_CANCEL(tcp, tcp->tcp_timer_tid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4070
		tcp->tcp_timer_tid = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4071
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4072
	if (tcp->tcp_ka_tid != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4073
		(void) TCP_TIMER_CANCEL(tcp, tcp->tcp_ka_tid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4074
		tcp->tcp_ka_tid = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4075
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4076
	if (tcp->tcp_ack_tid != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4077
		(void) TCP_TIMER_CANCEL(tcp, tcp->tcp_ack_tid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4078
		tcp->tcp_ack_tid = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4079
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4080
	if (tcp->tcp_push_tid != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4081
		(void) TCP_TIMER_CANCEL(tcp, tcp->tcp_push_tid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4082
		tcp->tcp_push_tid = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4083
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4084
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4085
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4086
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4087
 * The tcp_t is going away. Remove it from all lists and set it
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4088
 * to TCPS_CLOSED. The freeing up of memory is deferred until
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4089
 * tcp_inactive. This is needed since a thread in tcp_rput might have
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4090
 * done a CONN_INC_REF on this structure before it was removed from the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4091
 * hashes.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4092
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4093
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4094
tcp_closei_local(tcp_t *tcp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4095
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4096
	ire_t 	*ire;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4097
	conn_t	*connp = tcp->tcp_connp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4098
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4099
	if (!TCP_IS_SOCKET(tcp))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4100
		tcp_acceptor_hash_remove(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4101
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4102
	UPDATE_MIB(&tcp_mib, tcpInSegs, tcp->tcp_ibsegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4103
	tcp->tcp_ibsegs = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4104
	UPDATE_MIB(&tcp_mib, tcpOutSegs, tcp->tcp_obsegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4105
	tcp->tcp_obsegs = 0;
898
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
  4106
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4107
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4108
	 * If we are an eager connection hanging off a listener that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4109
	 * hasn't formally accepted the connection yet, get off his
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4110
	 * list and blow off any data that we have accumulated.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4111
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4112
	if (tcp->tcp_listener != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4113
		tcp_t	*listener = tcp->tcp_listener;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4114
		mutex_enter(&listener->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4115
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4116
		 * tcp_eager_conn_ind == NULL means that the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4117
		 * conn_ind has already gone to listener. At
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4118
		 * this point, eager will be closed but we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4119
		 * leave it in listeners eager list so that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4120
		 * if listener decides to close without doing
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4121
		 * accept, we can clean this up. In tcp_wput_accept
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4122
		 * we take case of the case of accept on closed
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4123
		 * eager.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4124
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4125
		if (tcp->tcp_conn.tcp_eager_conn_ind != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4126
			tcp_eager_unlink(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4127
			mutex_exit(&listener->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4128
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4129
			 * We don't want to have any pointers to the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4130
			 * listener queue, after we have released our
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4131
			 * reference on the listener
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4132
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4133
			tcp->tcp_rq = tcp_g_q;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4134
			tcp->tcp_wq = WR(tcp_g_q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4135
			CONN_DEC_REF(listener->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4136
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4137
			mutex_exit(&listener->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4138
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4139
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4140
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4141
	/* Stop all the timers */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4142
	tcp_timers_stop(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4143
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4144
	if (tcp->tcp_state == TCPS_LISTEN) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4145
		if (tcp->tcp_ip_addr_cache) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4146
			kmem_free((void *)tcp->tcp_ip_addr_cache,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4147
			    IP_ADDR_CACHE_SIZE * sizeof (ipaddr_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4148
			tcp->tcp_ip_addr_cache = NULL;
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
	if (tcp->tcp_flow_stopped)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4152
		tcp_clrqfull(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4153
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4154
	tcp_bind_hash_remove(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4155
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4156
	 * If the tcp_time_wait_collector (which runs outside the squeue)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4157
	 * is trying to remove this tcp from the time wait list, we will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4158
	 * block in tcp_time_wait_remove while trying to acquire the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4159
	 * tcp_time_wait_lock. The logic in tcp_time_wait_collector also
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4160
	 * requires the ipcl_hash_remove to be ordered after the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4161
	 * tcp_time_wait_remove for the refcnt checks to work correctly.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4162
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4163
	if (tcp->tcp_state == TCPS_TIME_WAIT)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4164
		tcp_time_wait_remove(tcp, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4165
	CL_INET_DISCONNECT(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4166
	ipcl_hash_remove(connp);
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
	 * Delete the cached ire in conn_ire_cache and also mark
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4170
	 * the conn as CONDEMNED
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4171
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4172
	mutex_enter(&connp->conn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4173
	connp->conn_state_flags |= CONN_CONDEMNED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4174
	ire = connp->conn_ire_cache;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4175
	connp->conn_ire_cache = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4176
	mutex_exit(&connp->conn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4177
	if (ire != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4178
		IRE_REFRELE_NOTR(ire);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4179
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4180
	/* Need to cleanup any pending ioctls */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4181
	ASSERT(tcp->tcp_time_wait_next == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4182
	ASSERT(tcp->tcp_time_wait_prev == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4183
	ASSERT(tcp->tcp_time_wait_expire == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4184
	tcp->tcp_state = TCPS_CLOSED;
898
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
  4185
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
  4186
	/* Release any SSL context */
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
  4187
	if (tcp->tcp_kssl_ent != NULL) {
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
  4188
		kssl_release_ent(tcp->tcp_kssl_ent, NULL, KSSL_NO_PROXY);
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
  4189
		tcp->tcp_kssl_ent = NULL;
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
  4190
	}
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
  4191
	if (tcp->tcp_kssl_ctx != NULL) {
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
  4192
		kssl_release_ctx(tcp->tcp_kssl_ctx);
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
  4193
		tcp->tcp_kssl_ctx = NULL;
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
  4194
	}
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
  4195
	tcp->tcp_kssl_pending = B_FALSE;
0
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
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4199
 * tcp is dying (called from ipcl_conn_destroy and error cases).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4200
 * Free the tcp_t in either case.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4201
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4202
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4203
tcp_free(tcp_t *tcp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4204
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4205
	mblk_t	*mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4206
	ip6_pkt_t	*ipp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4207
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4208
	ASSERT(tcp != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4209
	ASSERT(tcp->tcp_ptpahn == NULL && tcp->tcp_acceptor_hash == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4210
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4211
	tcp->tcp_rq = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4212
	tcp->tcp_wq = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4213
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4214
	tcp_close_mpp(&tcp->tcp_xmit_head);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4215
	tcp_close_mpp(&tcp->tcp_reass_head);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4216
	if (tcp->tcp_rcv_list != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4217
		/* Free b_next chain */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4218
		tcp_close_mpp(&tcp->tcp_rcv_list);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4219
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4220
	if ((mp = tcp->tcp_urp_mp) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4221
		freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4222
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4223
	if ((mp = tcp->tcp_urp_mark_mp) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4224
		freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4225
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4226
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4227
	if (tcp->tcp_fused_sigurg_mp != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4228
		freeb(tcp->tcp_fused_sigurg_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4229
		tcp->tcp_fused_sigurg_mp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4230
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4231
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4232
	if (tcp->tcp_sack_info != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4233
		if (tcp->tcp_notsack_list != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4234
			TCP_NOTSACK_REMOVE_ALL(tcp->tcp_notsack_list);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4235
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4236
		bzero(tcp->tcp_sack_info, sizeof (tcp_sack_info_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4237
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4238
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4239
	if (tcp->tcp_hopopts != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4240
		mi_free(tcp->tcp_hopopts);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4241
		tcp->tcp_hopopts = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4242
		tcp->tcp_hopoptslen = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4243
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4244
	ASSERT(tcp->tcp_hopoptslen == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4245
	if (tcp->tcp_dstopts != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4246
		mi_free(tcp->tcp_dstopts);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4247
		tcp->tcp_dstopts = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4248
		tcp->tcp_dstoptslen = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4249
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4250
	ASSERT(tcp->tcp_dstoptslen == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4251
	if (tcp->tcp_rtdstopts != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4252
		mi_free(tcp->tcp_rtdstopts);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4253
		tcp->tcp_rtdstopts = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4254
		tcp->tcp_rtdstoptslen = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4255
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4256
	ASSERT(tcp->tcp_rtdstoptslen == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4257
	if (tcp->tcp_rthdr != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4258
		mi_free(tcp->tcp_rthdr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4259
		tcp->tcp_rthdr = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4260
		tcp->tcp_rthdrlen = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4261
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4262
	ASSERT(tcp->tcp_rthdrlen == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4263
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4264
	ipp = &tcp->tcp_sticky_ipp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4265
	if ((ipp->ipp_fields & (IPPF_HOPOPTS | IPPF_RTDSTOPTS |
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4266
	    IPPF_DSTOPTS | IPPF_RTHDR)) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4267
		if ((ipp->ipp_fields & IPPF_HOPOPTS) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4268
			kmem_free(ipp->ipp_hopopts, ipp->ipp_hopoptslen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4269
			ipp->ipp_hopopts = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4270
			ipp->ipp_hopoptslen = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4271
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4272
		if ((ipp->ipp_fields & IPPF_RTDSTOPTS) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4273
			kmem_free(ipp->ipp_rtdstopts, ipp->ipp_rtdstoptslen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4274
			ipp->ipp_rtdstopts = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4275
			ipp->ipp_rtdstoptslen = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4276
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4277
		if ((ipp->ipp_fields & IPPF_DSTOPTS) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4278
			kmem_free(ipp->ipp_dstopts, ipp->ipp_dstoptslen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4279
			ipp->ipp_dstopts = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4280
			ipp->ipp_dstoptslen = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4281
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4282
		if ((ipp->ipp_fields & IPPF_RTHDR) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4283
			kmem_free(ipp->ipp_rthdr, ipp->ipp_rthdrlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4284
			ipp->ipp_rthdr = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4285
			ipp->ipp_rthdrlen = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4286
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4287
		ipp->ipp_fields &= ~(IPPF_HOPOPTS | IPPF_RTDSTOPTS |
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4288
		    IPPF_DSTOPTS | IPPF_RTHDR);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4289
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4290
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4291
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4292
	 * Free memory associated with the tcp/ip header template.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4293
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4294
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4295
	if (tcp->tcp_iphc != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4296
		bzero(tcp->tcp_iphc, tcp->tcp_iphc_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4297
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4298
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4299
	 * Following is really a blowing away a union.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4300
	 * It happens to have exactly two members of identical size
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4301
	 * the following code is enough.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4302
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4303
	tcp_close_mpp(&tcp->tcp_conn.tcp_eager_conn_ind);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4304
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4305
	if (tcp->tcp_tracebuf != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4306
		kmem_free(tcp->tcp_tracebuf, sizeof (tcptrch_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4307
		tcp->tcp_tracebuf = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4308
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4309
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4310
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4311
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4312
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4313
 * Put a connection confirmation message upstream built from the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4314
 * address information within 'iph' and 'tcph'.  Report our success or failure.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4315
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4316
static boolean_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4317
tcp_conn_con(tcp_t *tcp, uchar_t *iphdr, tcph_t *tcph, mblk_t *idmp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4318
    mblk_t **defermp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4319
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4320
	sin_t	sin;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4321
	sin6_t	sin6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4322
	mblk_t	*mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4323
	char	*optp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4324
	int	optlen = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4325
	cred_t	*cr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4326
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4327
	if (defermp != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4328
		*defermp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4329
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4330
	if (tcp->tcp_conn.tcp_opts_conn_req != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4331
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4332
		 * Return in T_CONN_CON results of option negotiation through
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4333
		 * the T_CONN_REQ. Note: If there is an real end-to-end option
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4334
		 * negotiation, then what is received from remote end needs
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4335
		 * to be taken into account but there is no such thing (yet?)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4336
		 * in our TCP/IP.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4337
		 * Note: We do not use mi_offset_param() here as
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4338
		 * tcp_opts_conn_req contents do not directly come from
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4339
		 * an application and are either generated in kernel or
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4340
		 * from user input that was already verified.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4341
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4342
		mp = tcp->tcp_conn.tcp_opts_conn_req;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4343
		optp = (char *)(mp->b_rptr +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4344
		    ((struct T_conn_req *)mp->b_rptr)->OPT_offset);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4345
		optlen = (int)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4346
		    ((struct T_conn_req *)mp->b_rptr)->OPT_length;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4347
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4348
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4349
	if (IPH_HDR_VERSION(iphdr) == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4350
		ipha_t *ipha = (ipha_t *)iphdr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4351
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4352
		/* packet is IPv4 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4353
		if (tcp->tcp_family == AF_INET) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4354
			sin = sin_null;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4355
			sin.sin_addr.s_addr = ipha->ipha_src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4356
			sin.sin_port = *(uint16_t *)tcph->th_lport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4357
			sin.sin_family = AF_INET;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4358
			mp = mi_tpi_conn_con(NULL, (char *)&sin,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4359
			    (int)sizeof (sin_t), optp, optlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4360
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4361
			sin6 = sin6_null;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4362
			IN6_IPADDR_TO_V4MAPPED(ipha->ipha_src, &sin6.sin6_addr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4363
			sin6.sin6_port = *(uint16_t *)tcph->th_lport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4364
			sin6.sin6_family = AF_INET6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4365
			mp = mi_tpi_conn_con(NULL, (char *)&sin6,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4366
			    (int)sizeof (sin6_t), optp, optlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4367
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4368
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4369
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4370
		ip6_t	*ip6h = (ip6_t *)iphdr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4371
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4372
		ASSERT(IPH_HDR_VERSION(iphdr) == IPV6_VERSION);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4373
		ASSERT(tcp->tcp_family == AF_INET6);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4374
		sin6 = sin6_null;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4375
		sin6.sin6_addr = ip6h->ip6_src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4376
		sin6.sin6_port = *(uint16_t *)tcph->th_lport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4377
		sin6.sin6_family = AF_INET6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4378
		sin6.sin6_flowinfo = ip6h->ip6_vcf & ~IPV6_VERS_AND_FLOW_MASK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4379
		mp = mi_tpi_conn_con(NULL, (char *)&sin6,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4380
		    (int)sizeof (sin6_t), optp, optlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4381
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4382
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4383
	if (!mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4384
		return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4385
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4386
	if ((cr = DB_CRED(idmp)) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4387
		mblk_setcred(mp, cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4388
		DB_CPID(mp) = DB_CPID(idmp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4389
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4390
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4391
	if (defermp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4392
		putnext(tcp->tcp_rq, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4393
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4394
		*defermp = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4395
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4396
	if (tcp->tcp_conn.tcp_opts_conn_req != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4397
		tcp_close_mpp(&tcp->tcp_conn.tcp_opts_conn_req);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4398
	return (B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4399
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4400
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4401
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4402
 * Defense for the SYN attack -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4403
 * 1. When q0 is full, drop from the tail (tcp_eager_prev_q0) the oldest
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4404
 *    one that doesn't have the dontdrop bit set.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4405
 * 2. Don't drop a SYN request before its first timeout. This gives every
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4406
 *    request at least til the first timeout to complete its 3-way handshake.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4407
 * 3. Maintain tcp_syn_rcvd_timeout as an accurate count of how many
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4408
 *    requests currently on the queue that has timed out. This will be used
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4409
 *    as an indicator of whether an attack is under way, so that appropriate
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4410
 *    actions can be taken. (It's incremented in tcp_timer() and decremented
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4411
 *    either when eager goes into ESTABLISHED, or gets freed up.)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4412
 * 4. The current threshold is - # of timeout > q0len/4 => SYN alert on
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4413
 *    # of timeout drops back to <= q0len/32 => SYN alert off
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4414
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4415
static boolean_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4416
tcp_drop_q0(tcp_t *tcp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4417
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4418
	tcp_t	*eager;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4419
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4420
	ASSERT(MUTEX_HELD(&tcp->tcp_eager_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4421
	ASSERT(tcp->tcp_eager_next_q0 != tcp->tcp_eager_prev_q0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4422
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4423
	 * New one is added after next_q0 so prev_q0 points to the oldest
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4424
	 * Also do not drop any established connections that are deferred on
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4425
	 * q0 due to q being full
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4426
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4427
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4428
	eager = tcp->tcp_eager_prev_q0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4429
	while (eager->tcp_dontdrop || eager->tcp_conn_def_q0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4430
		eager = eager->tcp_eager_prev_q0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4431
		if (eager == tcp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4432
			eager = tcp->tcp_eager_prev_q0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4433
			break;
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
	if (eager->tcp_syn_rcvd_timeout == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4437
		return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4438
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4439
	if (tcp->tcp_debug) {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  4440
		(void) strlog(TCP_MOD_ID, 0, 3, SL_TRACE,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4441
		    "tcp_drop_q0: listen half-open queue (max=%d) overflow"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4442
		    " (%d pending) on %s, drop one", tcp_conn_req_max_q0,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4443
		    tcp->tcp_conn_req_cnt_q0,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4444
		    tcp_display(tcp, NULL, DISP_PORT_ONLY));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4445
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4446
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4447
	BUMP_MIB(&tcp_mib, tcpHalfOpenDrop);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4448
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4449
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4450
	 * need to do refhold here because the selected eager could
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4451
	 * be removed by someone else if we release the eager lock.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4452
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4453
	CONN_INC_REF(eager->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4454
	mutex_exit(&tcp->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4455
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4456
	/* Mark the IRE created for this SYN request temporary */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4457
	tcp_ip_ire_mark_advice(eager);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4458
	(void) tcp_clean_death(eager, ETIMEDOUT, 5);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4459
	CONN_DEC_REF(eager->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4460
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4461
	mutex_enter(&tcp->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4462
	return (B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4463
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4464
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4465
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4466
tcp_conn_create_v6(conn_t *lconnp, conn_t *connp, mblk_t *mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4467
    tcph_t *tcph, uint_t ipvers, mblk_t *idmp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4468
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4469
	tcp_t 		*ltcp = lconnp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4470
	tcp_t		*tcp = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4471
	mblk_t		*tpi_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4472
	ipha_t		*ipha;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4473
	ip6_t		*ip6h;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4474
	sin6_t 		sin6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4475
	in6_addr_t 	v6dst;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4476
	int		err;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4477
	int		ifindex = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4478
	cred_t		*cr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4479
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4480
	if (ipvers == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4481
		ipha = (ipha_t *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4482
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4483
		connp->conn_send = ip_output;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4484
		connp->conn_recv = tcp_input;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4485
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4486
		IN6_IPADDR_TO_V4MAPPED(ipha->ipha_dst, &connp->conn_srcv6);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4487
		IN6_IPADDR_TO_V4MAPPED(ipha->ipha_src, &connp->conn_remv6);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4488
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4489
		sin6 = sin6_null;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4490
		IN6_IPADDR_TO_V4MAPPED(ipha->ipha_src, &sin6.sin6_addr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4491
		IN6_IPADDR_TO_V4MAPPED(ipha->ipha_dst, &v6dst);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4492
		sin6.sin6_port = *(uint16_t *)tcph->th_lport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4493
		sin6.sin6_family = AF_INET6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4494
		sin6.__sin6_src_id = ip_srcid_find_addr(&v6dst,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4495
		    lconnp->conn_zoneid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4496
		if (tcp->tcp_recvdstaddr) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4497
			sin6_t	sin6d;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4498
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4499
			sin6d = sin6_null;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4500
			IN6_IPADDR_TO_V4MAPPED(ipha->ipha_dst,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4501
			    &sin6d.sin6_addr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4502
			sin6d.sin6_port = *(uint16_t *)tcph->th_fport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4503
			sin6d.sin6_family = AF_INET;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4504
			tpi_mp = mi_tpi_extconn_ind(NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4505
			    (char *)&sin6d, sizeof (sin6_t),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4506
			    (char *)&tcp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4507
			    (t_scalar_t)sizeof (intptr_t),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4508
			    (char *)&sin6d, sizeof (sin6_t),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4509
			    (t_scalar_t)ltcp->tcp_conn_req_seqnum);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4510
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4511
			tpi_mp = mi_tpi_conn_ind(NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4512
			    (char *)&sin6, sizeof (sin6_t),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4513
			    (char *)&tcp, (t_scalar_t)sizeof (intptr_t),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4514
			    (t_scalar_t)ltcp->tcp_conn_req_seqnum);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4515
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4516
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4517
		ip6h = (ip6_t *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4518
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4519
		connp->conn_send = ip_output_v6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4520
		connp->conn_recv = tcp_input;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4521
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4522
		connp->conn_srcv6 = ip6h->ip6_dst;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4523
		connp->conn_remv6 = ip6h->ip6_src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4524
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4525
		/* db_cksumstuff is set at ip_fanout_tcp_v6 */
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  4526
		ifindex = (int)DB_CKSUMSTUFF(mp);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  4527
		DB_CKSUMSTUFF(mp) = 0;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4528
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4529
		sin6 = sin6_null;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4530
		sin6.sin6_addr = ip6h->ip6_src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4531
		sin6.sin6_port = *(uint16_t *)tcph->th_lport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4532
		sin6.sin6_family = AF_INET6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4533
		sin6.sin6_flowinfo = ip6h->ip6_vcf & ~IPV6_VERS_AND_FLOW_MASK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4534
		sin6.__sin6_src_id = ip_srcid_find_addr(&ip6h->ip6_dst,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4535
		    lconnp->conn_zoneid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4536
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4537
		if (IN6_IS_ADDR_LINKSCOPE(&ip6h->ip6_src)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4538
			/* Pass up the scope_id of remote addr */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4539
			sin6.sin6_scope_id = ifindex;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4540
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4541
			sin6.sin6_scope_id = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4542
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4543
		if (tcp->tcp_recvdstaddr) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4544
			sin6_t	sin6d;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4545
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4546
			sin6d = sin6_null;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4547
			sin6.sin6_addr = ip6h->ip6_dst;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4548
			sin6d.sin6_port = *(uint16_t *)tcph->th_fport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4549
			sin6d.sin6_family = AF_INET;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4550
			tpi_mp = mi_tpi_extconn_ind(NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4551
			    (char *)&sin6d, sizeof (sin6_t),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4552
			    (char *)&tcp, (t_scalar_t)sizeof (intptr_t),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4553
			    (char *)&sin6d, sizeof (sin6_t),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4554
			    (t_scalar_t)ltcp->tcp_conn_req_seqnum);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4555
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4556
			tpi_mp = mi_tpi_conn_ind(NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4557
			    (char *)&sin6, sizeof (sin6_t),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4558
			    (char *)&tcp, (t_scalar_t)sizeof (intptr_t),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4559
			    (t_scalar_t)ltcp->tcp_conn_req_seqnum);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4560
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4561
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4562
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4563
	if (tpi_mp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4564
		return (ENOMEM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4565
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4566
	connp->conn_fport = *(uint16_t *)tcph->th_lport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4567
	connp->conn_lport = *(uint16_t *)tcph->th_fport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4568
	connp->conn_flags |= (IPCL_TCP6|IPCL_EAGER);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4569
	connp->conn_fully_bound = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4570
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4571
	if (tcp_trace)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4572
		tcp->tcp_tracebuf = kmem_zalloc(sizeof (tcptrch_t), KM_NOSLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4573
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4574
	/* Inherit information from the "parent" */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4575
	tcp->tcp_ipversion = ltcp->tcp_ipversion;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4576
	tcp->tcp_family = ltcp->tcp_family;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4577
	tcp->tcp_wq = ltcp->tcp_wq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4578
	tcp->tcp_rq = ltcp->tcp_rq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4579
	tcp->tcp_mss = tcp_mss_def_ipv6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4580
	tcp->tcp_detached = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4581
	if ((err = tcp_init_values(tcp)) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4582
		freemsg(tpi_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4583
		return (err);
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
	if (ipvers == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4587
		if ((err = tcp_header_init_ipv4(tcp)) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4588
			freemsg(tpi_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4589
			return (err);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4590
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4591
		ASSERT(tcp->tcp_ipha != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4592
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4593
		/* ifindex must be already set */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4594
		ASSERT(ifindex != 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4595
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4596
		if (ltcp->tcp_bound_if != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4597
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4598
			 * Set newtcp's bound_if equal to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4599
			 * listener's value. If ifindex is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4600
			 * not the same as ltcp->tcp_bound_if,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4601
			 * it must be a packet for the ipmp group
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4602
			 * of interfaces
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4603
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4604
			tcp->tcp_bound_if = ltcp->tcp_bound_if;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4605
		} else if (IN6_IS_ADDR_LINKSCOPE(&ip6h->ip6_src)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4606
			tcp->tcp_bound_if = ifindex;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4607
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4608
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4609
		tcp->tcp_ipv6_recvancillary = ltcp->tcp_ipv6_recvancillary;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4610
		tcp->tcp_recvifindex = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4611
		tcp->tcp_recvhops = 0xffffffffU;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4612
		ASSERT(tcp->tcp_ip6h != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4613
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4614
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4615
	tcp->tcp_lport = ltcp->tcp_lport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4616
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4617
	if (ltcp->tcp_ipversion == tcp->tcp_ipversion) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4618
		if (tcp->tcp_iphc_len != ltcp->tcp_iphc_len) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4619
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4620
			 * Listener had options of some sort; eager inherits.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4621
			 * Free up the eager template and allocate one
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4622
			 * of the right size.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4623
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4624
			if (tcp->tcp_hdr_grown) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4625
				kmem_free(tcp->tcp_iphc, tcp->tcp_iphc_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4626
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4627
				bzero(tcp->tcp_iphc, tcp->tcp_iphc_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4628
				kmem_cache_free(tcp_iphc_cache, tcp->tcp_iphc);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4629
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4630
			tcp->tcp_iphc = kmem_zalloc(ltcp->tcp_iphc_len,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4631
			    KM_NOSLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4632
			if (tcp->tcp_iphc == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4633
				tcp->tcp_iphc_len = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4634
				freemsg(tpi_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4635
				return (ENOMEM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4636
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4637
			tcp->tcp_iphc_len = ltcp->tcp_iphc_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4638
			tcp->tcp_hdr_grown = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4639
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4640
		tcp->tcp_hdr_len = ltcp->tcp_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4641
		tcp->tcp_ip_hdr_len = ltcp->tcp_ip_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4642
		tcp->tcp_tcp_hdr_len = ltcp->tcp_tcp_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4643
		tcp->tcp_ip6_hops = ltcp->tcp_ip6_hops;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4644
		tcp->tcp_ip6_vcf = ltcp->tcp_ip6_vcf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4645
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4646
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4647
		 * Copy the IP+TCP header template from listener to eager
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4648
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4649
		bcopy(ltcp->tcp_iphc, tcp->tcp_iphc, ltcp->tcp_hdr_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4650
		if (tcp->tcp_ipversion == IPV6_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4651
			if (((ip6i_t *)(tcp->tcp_iphc))->ip6i_nxt ==
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4652
			    IPPROTO_RAW) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4653
				tcp->tcp_ip6h =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4654
				    (ip6_t *)(tcp->tcp_iphc +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4655
					sizeof (ip6i_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4656
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4657
				tcp->tcp_ip6h =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4658
				    (ip6_t *)(tcp->tcp_iphc);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4659
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4660
			tcp->tcp_ipha = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4661
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4662
			tcp->tcp_ipha = (ipha_t *)tcp->tcp_iphc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4663
			tcp->tcp_ip6h = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4664
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4665
		tcp->tcp_tcph = (tcph_t *)(tcp->tcp_iphc +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4666
		    tcp->tcp_ip_hdr_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4667
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4668
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4669
		 * only valid case when ipversion of listener and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4670
		 * eager differ is when listener is IPv6 and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4671
		 * eager is IPv4.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4672
		 * Eager header template has been initialized to the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4673
		 * maximum v4 header sizes, which includes space for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4674
		 * TCP and IP options.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4675
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4676
		ASSERT((ltcp->tcp_ipversion == IPV6_VERSION) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4677
		    (tcp->tcp_ipversion == IPV4_VERSION));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4678
		ASSERT(tcp->tcp_iphc_len >=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4679
		    TCP_MAX_COMBINED_HEADER_LENGTH);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4680
		tcp->tcp_tcp_hdr_len = ltcp->tcp_tcp_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4681
		/* copy IP header fields individually */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4682
		tcp->tcp_ipha->ipha_ttl =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4683
		    ltcp->tcp_ip6h->ip6_hops;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4684
		bcopy(ltcp->tcp_tcph->th_lport,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4685
		    tcp->tcp_tcph->th_lport, sizeof (ushort_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4686
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4687
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4688
	bcopy(tcph->th_lport, tcp->tcp_tcph->th_fport, sizeof (in_port_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4689
	bcopy(tcp->tcp_tcph->th_fport, &tcp->tcp_fport,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4690
	    sizeof (in_port_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4691
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4692
	if (ltcp->tcp_lport == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4693
		tcp->tcp_lport = *(in_port_t *)tcph->th_fport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4694
		bcopy(tcph->th_fport, tcp->tcp_tcph->th_lport,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4695
		    sizeof (in_port_t));
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
	if (tcp->tcp_ipversion == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4699
		ASSERT(ipha != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4700
		tcp->tcp_ipha->ipha_dst = ipha->ipha_src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4701
		tcp->tcp_ipha->ipha_src = ipha->ipha_dst;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4702
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4703
		/* Source routing option copyover (reverse it) */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4704
		if (tcp_rev_src_routes)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4705
			tcp_opt_reverse(tcp, ipha);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4706
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4707
		ASSERT(ip6h != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4708
		tcp->tcp_ip6h->ip6_dst = ip6h->ip6_src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4709
		tcp->tcp_ip6h->ip6_src = ip6h->ip6_dst;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4710
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4711
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4712
	ASSERT(tcp->tcp_conn.tcp_eager_conn_ind == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4713
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4714
	 * If the SYN contains a credential, it's a loopback packet; attach
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4715
	 * the credential to the TPI message.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4716
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4717
	if ((cr = DB_CRED(idmp)) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4718
		mblk_setcred(tpi_mp, cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4719
		DB_CPID(tpi_mp) = DB_CPID(idmp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4720
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4721
	tcp->tcp_conn.tcp_eager_conn_ind = tpi_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4722
898
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
  4723
	/* Inherit the listener's SSL protection state */
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
  4724
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
  4725
	if ((tcp->tcp_kssl_ent = ltcp->tcp_kssl_ent) != NULL) {
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
  4726
		kssl_hold_ent(tcp->tcp_kssl_ent);
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
  4727
		tcp->tcp_kssl_pending = B_TRUE;
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
  4728
	}
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
  4729
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4730
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4731
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4732
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4733
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4734
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4735
tcp_conn_create_v4(conn_t *lconnp, conn_t *connp, ipha_t *ipha,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4736
    tcph_t *tcph, mblk_t *idmp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4737
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4738
	tcp_t 		*ltcp = lconnp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4739
	tcp_t		*tcp = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4740
	sin_t		sin;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4741
	mblk_t		*tpi_mp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4742
	int		err;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4743
	cred_t		*cr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4744
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4745
	sin = sin_null;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4746
	sin.sin_addr.s_addr = ipha->ipha_src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4747
	sin.sin_port = *(uint16_t *)tcph->th_lport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4748
	sin.sin_family = AF_INET;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4749
	if (ltcp->tcp_recvdstaddr) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4750
		sin_t	sind;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4751
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4752
		sind = sin_null;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4753
		sind.sin_addr.s_addr = ipha->ipha_dst;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4754
		sind.sin_port = *(uint16_t *)tcph->th_fport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4755
		sind.sin_family = AF_INET;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4756
		tpi_mp = mi_tpi_extconn_ind(NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4757
		    (char *)&sind, sizeof (sin_t), (char *)&tcp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4758
		    (t_scalar_t)sizeof (intptr_t), (char *)&sind,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4759
		    sizeof (sin_t), (t_scalar_t)ltcp->tcp_conn_req_seqnum);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4760
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4761
		tpi_mp = mi_tpi_conn_ind(NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4762
		    (char *)&sin, sizeof (sin_t),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4763
		    (char *)&tcp, (t_scalar_t)sizeof (intptr_t),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4764
		    (t_scalar_t)ltcp->tcp_conn_req_seqnum);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4765
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4766
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4767
	if (tpi_mp == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4768
		return (ENOMEM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4769
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4770
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4771
	connp->conn_flags |= (IPCL_TCP4|IPCL_EAGER);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4772
	connp->conn_send = ip_output;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4773
	connp->conn_recv = tcp_input;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4774
	connp->conn_fully_bound = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4775
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4776
	IN6_IPADDR_TO_V4MAPPED(ipha->ipha_dst, &connp->conn_srcv6);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4777
	IN6_IPADDR_TO_V4MAPPED(ipha->ipha_src, &connp->conn_remv6);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4778
	connp->conn_fport = *(uint16_t *)tcph->th_lport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4779
	connp->conn_lport = *(uint16_t *)tcph->th_fport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4780
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4781
	if (tcp_trace) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4782
		tcp->tcp_tracebuf = kmem_zalloc(sizeof (tcptrch_t), KM_NOSLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4783
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4784
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4785
	/* Inherit information from the "parent" */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4786
	tcp->tcp_ipversion = ltcp->tcp_ipversion;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4787
	tcp->tcp_family = ltcp->tcp_family;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4788
	tcp->tcp_wq = ltcp->tcp_wq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4789
	tcp->tcp_rq = ltcp->tcp_rq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4790
	tcp->tcp_mss = tcp_mss_def_ipv4;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4791
	tcp->tcp_detached = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4792
	if ((err = tcp_init_values(tcp)) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4793
		freemsg(tpi_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4794
		return (err);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4795
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4796
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4797
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4798
	 * Let's make sure that eager tcp template has enough space to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4799
	 * copy IPv4 listener's tcp template. Since the conn_t structure is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4800
	 * preserved and tcp_iphc_len is also preserved, an eager conn_t may
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4801
	 * have a tcp_template of total len TCP_MAX_COMBINED_HEADER_LENGTH or
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4802
	 * more (in case of re-allocation of conn_t with tcp-IPv6 template with
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4803
	 * extension headers or with ip6i_t struct). Note that bcopy() below
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4804
	 * copies listener tcp's hdr_len which cannot be greater than TCP_MAX_
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4805
	 * COMBINED_HEADER_LENGTH as this listener must be a IPv4 listener.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4806
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4807
	ASSERT(tcp->tcp_iphc_len >= TCP_MAX_COMBINED_HEADER_LENGTH);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4808
	ASSERT(ltcp->tcp_hdr_len <= TCP_MAX_COMBINED_HEADER_LENGTH);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4809
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4810
	tcp->tcp_hdr_len = ltcp->tcp_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4811
	tcp->tcp_ip_hdr_len = ltcp->tcp_ip_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4812
	tcp->tcp_tcp_hdr_len = ltcp->tcp_tcp_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4813
	tcp->tcp_ttl = ltcp->tcp_ttl;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4814
	tcp->tcp_tos = ltcp->tcp_tos;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4815
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4816
	/* Copy the IP+TCP header template from listener to eager */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4817
	bcopy(ltcp->tcp_iphc, tcp->tcp_iphc, ltcp->tcp_hdr_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4818
	tcp->tcp_ipha = (ipha_t *)tcp->tcp_iphc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4819
	tcp->tcp_ip6h = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4820
	tcp->tcp_tcph = (tcph_t *)(tcp->tcp_iphc +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4821
	    tcp->tcp_ip_hdr_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4822
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4823
	/* Initialize the IP addresses and Ports */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4824
	tcp->tcp_ipha->ipha_dst = ipha->ipha_src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4825
	tcp->tcp_ipha->ipha_src = ipha->ipha_dst;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4826
	bcopy(tcph->th_lport, tcp->tcp_tcph->th_fport, sizeof (in_port_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4827
	bcopy(tcph->th_fport, tcp->tcp_tcph->th_lport, sizeof (in_port_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4828
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4829
	/* Source routing option copyover (reverse it) */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4830
	if (tcp_rev_src_routes)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4831
		tcp_opt_reverse(tcp, ipha);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4832
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4833
	ASSERT(tcp->tcp_conn.tcp_eager_conn_ind == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4834
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4835
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4836
	 * If the SYN contains a credential, it's a loopback packet; attach
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4837
	 * the credential to the TPI message.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4838
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4839
	if ((cr = DB_CRED(idmp)) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4840
		mblk_setcred(tpi_mp, cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4841
		DB_CPID(tpi_mp) = DB_CPID(idmp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4842
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4843
	tcp->tcp_conn.tcp_eager_conn_ind = tpi_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4844
898
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
  4845
	/* Inherit the listener's SSL protection state */
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
  4846
	if ((tcp->tcp_kssl_ent = ltcp->tcp_kssl_ent) != NULL) {
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
  4847
		kssl_hold_ent(tcp->tcp_kssl_ent);
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
  4848
		tcp->tcp_kssl_pending = B_TRUE;
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
  4849
	}
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
  4850
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4851
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4852
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4853
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4854
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4855
 * sets up conn for ipsec.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4856
 * if the first mblk is M_CTL it is consumed and mpp is updated.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4857
 * in case of error mpp is freed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4858
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4859
conn_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4860
tcp_get_ipsec_conn(tcp_t *tcp, squeue_t *sqp, mblk_t **mpp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4861
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4862
	conn_t 		*connp = tcp->tcp_connp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4863
	conn_t 		*econnp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4864
	squeue_t 	*new_sqp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4865
	mblk_t 		*first_mp = *mpp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4866
	mblk_t		*mp = *mpp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4867
	boolean_t	mctl_present = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4868
	uint_t		ipvers;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4869
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4870
	econnp = tcp_get_conn(sqp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4871
	if (econnp == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4872
		freemsg(first_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4873
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4874
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4875
	if (DB_TYPE(mp) == M_CTL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4876
		if (mp->b_cont == NULL ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4877
		    mp->b_cont->b_datap->db_type != M_DATA) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4878
			freemsg(first_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4879
			return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4880
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4881
		mp = mp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4882
		if ((mp->b_datap->db_struioflag & STRUIO_EAGER) == 0) {
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
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4887
		mp->b_datap->db_struioflag &= ~STRUIO_EAGER;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4888
		first_mp->b_datap->db_struioflag &= ~STRUIO_POLICY;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4889
		mctl_present = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4890
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4891
		ASSERT(mp->b_datap->db_struioflag & STRUIO_POLICY);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4892
		mp->b_datap->db_struioflag &= ~STRUIO_POLICY;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4893
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4894
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  4895
	new_sqp = (squeue_t *)DB_CKSUMSTART(mp);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  4896
	DB_CKSUMSTART(mp) = 0;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4897
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4898
	ASSERT(OK_32PTR(mp->b_rptr));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4899
	ipvers = IPH_HDR_VERSION(mp->b_rptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4900
	if (ipvers == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4901
		uint16_t  	*up;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4902
		uint32_t	ports;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4903
		ipha_t		*ipha;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4904
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4905
		ipha = (ipha_t *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4906
		up = (uint16_t *)((uchar_t *)ipha +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4907
		    IPH_HDR_LENGTH(ipha) + TCP_PORTS_OFFSET);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4908
		ports = *(uint32_t *)up;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4909
		IPCL_TCP_EAGER_INIT(econnp, IPPROTO_TCP,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4910
		    ipha->ipha_dst, ipha->ipha_src, ports);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4911
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4912
		uint16_t  	*up;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4913
		uint32_t	ports;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4914
		uint16_t	ip_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4915
		uint8_t		*nexthdrp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4916
		ip6_t 		*ip6h;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4917
		tcph_t		*tcph;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4918
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4919
		ip6h = (ip6_t *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4920
		if (ip6h->ip6_nxt == IPPROTO_TCP) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4921
			ip_hdr_len = IPV6_HDR_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4922
		} else if (!ip_hdr_length_nexthdr_v6(mp, ip6h, &ip_hdr_len,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4923
		    &nexthdrp) || *nexthdrp != IPPROTO_TCP) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4924
			CONN_DEC_REF(econnp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4925
			freemsg(first_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4926
			return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4927
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4928
		tcph = (tcph_t *)&mp->b_rptr[ip_hdr_len];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4929
		up = (uint16_t *)tcph->th_lport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4930
		ports = *(uint32_t *)up;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4931
		IPCL_TCP_EAGER_INIT_V6(econnp, IPPROTO_TCP,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4932
		    ip6h->ip6_dst, ip6h->ip6_src, ports);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4933
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4934
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4935
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4936
	 * The caller already ensured that there is a sqp present.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4937
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4938
	econnp->conn_sqp = new_sqp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4939
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4940
	if (connp->conn_policy != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4941
		ipsec_in_t *ii;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4942
		ii = (ipsec_in_t *)(first_mp->b_rptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4943
		ASSERT(ii->ipsec_in_policy == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4944
		IPPH_REFHOLD(connp->conn_policy);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4945
		ii->ipsec_in_policy = connp->conn_policy;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4946
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4947
		first_mp->b_datap->db_type = IPSEC_POLICY_SET;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4948
		if (!ip_bind_ipsec_policy_set(econnp, first_mp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4949
			CONN_DEC_REF(econnp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4950
			freemsg(first_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4951
			return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4952
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4953
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4954
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4955
	if (ipsec_conn_cache_policy(econnp, ipvers == IPV4_VERSION) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4956
		CONN_DEC_REF(econnp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4957
		freemsg(first_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4958
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4959
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4960
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4961
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4962
	 * If we know we have some policy, pass the "IPSEC"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4963
	 * options size TCP uses this adjust the MSS.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4964
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4965
	econnp->conn_tcp->tcp_ipsec_overhead = conn_ipsec_length(econnp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4966
	if (mctl_present) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4967
		freeb(first_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4968
		*mpp = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4969
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4970
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4971
	return (econnp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4972
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4973
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4974
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4975
 * tcp_get_conn/tcp_free_conn
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4976
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4977
 * tcp_get_conn is used to get a clean tcp connection structure.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4978
 * It tries to reuse the connections put on the freelist by the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4979
 * time_wait_collector failing which it goes to kmem_cache. This
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4980
 * way has two benefits compared to just allocating from and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4981
 * freeing to kmem_cache.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4982
 * 1) The time_wait_collector can free (which includes the cleanup)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4983
 * outside the squeue. So when the interrupt comes, we have a clean
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4984
 * connection sitting in the freelist. Obviously, this buys us
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4985
 * performance.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4986
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4987
 * 2) Defence against DOS attack. Allocating a tcp/conn in tcp_conn_request
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4988
 * has multiple disadvantages - tying up the squeue during alloc, and the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4989
 * fact that IPSec policy initialization has to happen here which
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4990
 * requires us sending a M_CTL and checking for it i.e. real ugliness.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4991
 * But allocating the conn/tcp in IP land is also not the best since
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4992
 * we can't check the 'q' and 'q0' which are protected by squeue and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4993
 * blindly allocate memory which might have to be freed here if we are
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4994
 * not allowed to accept the connection. By using the freelist and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4995
 * putting the conn/tcp back in freelist, we don't pay a penalty for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4996
 * allocating memory without checking 'q/q0' and freeing it if we can't
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4997
 * accept the connection.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4998
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4999
 * Care should be taken to put the conn back in the same squeue's freelist
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5000
 * from which it was allocated. Best results are obtained if conn is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5001
 * allocated from listener's squeue and freed to the same. Time wait
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5002
 * collector will free up the freelist is the connection ends up sitting
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5003
 * there for too long.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5004
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5005
void *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5006
tcp_get_conn(void *arg)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5007
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5008
	tcp_t			*tcp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5009
	conn_t			*connp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5010
	squeue_t		*sqp = (squeue_t *)arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5011
	tcp_squeue_priv_t 	*tcp_time_wait;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5012
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5013
	tcp_time_wait =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5014
	    *((tcp_squeue_priv_t **)squeue_getprivate(sqp, SQPRIVATE_TCP));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5015
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5016
	mutex_enter(&tcp_time_wait->tcp_time_wait_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5017
	tcp = tcp_time_wait->tcp_free_list;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5018
	if (tcp != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5019
		tcp_time_wait->tcp_free_list = tcp->tcp_time_wait_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5020
		mutex_exit(&tcp_time_wait->tcp_time_wait_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5021
		tcp->tcp_time_wait_next = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5022
		connp = tcp->tcp_connp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5023
		connp->conn_flags |= IPCL_REUSED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5024
		return ((void *)connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5025
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5026
	mutex_exit(&tcp_time_wait->tcp_time_wait_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5027
	if ((connp = ipcl_conn_create(IPCL_TCPCONN, KM_NOSLEEP)) == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5028
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5029
	return ((void *)connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5030
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5031
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5032
/* BEGIN CSTYLED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5033
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5034
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5035
 * The sockfs ACCEPT path:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5036
 * =======================
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5037
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5038
 * The eager is now established in its own perimeter as soon as SYN is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5039
 * received in tcp_conn_request(). When sockfs receives conn_ind, it
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5040
 * completes the accept processing on the acceptor STREAM. The sending
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5041
 * of conn_ind part is common for both sockfs listener and a TLI/XTI
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5042
 * listener but a TLI/XTI listener completes the accept processing
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5043
 * on the listener perimeter.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5044
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5045
 * Common control flow for 3 way handshake:
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
 * incoming SYN (listener perimeter) 	-> tcp_rput_data()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5049
 *					-> tcp_conn_request()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5050
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5051
 * incoming SYN-ACK-ACK (eager perim) 	-> tcp_rput_data()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5052
 * send T_CONN_IND (listener perim)	-> tcp_send_conn_ind()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5053
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5054
 * Sockfs ACCEPT Path:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5055
 * -------------------
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5056
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5057
 * open acceptor stream (ip_tcpopen allocates tcp_wput_accept()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5058
 * as STREAM entry point)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5059
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5060
 * soaccept() sends T_CONN_RES on the acceptor STREAM to tcp_wput_accept()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5061
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5062
 * tcp_wput_accept() extracts the eager and makes the q->q_ptr <-> eager
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5063
 * association (we are not behind eager's squeue but sockfs is protecting us
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5064
 * and no one knows about this stream yet. The STREAMS entry point q->q_info
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5065
 * is changed to point at tcp_wput().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5066
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5067
 * tcp_wput_accept() sends any deferred eagers via tcp_send_pending() to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5068
 * listener (done on listener's perimeter).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5069
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5070
 * tcp_wput_accept() calls tcp_accept_finish() on eagers perimeter to finish
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5071
 * accept.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5072
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5073
 * TLI/XTI client ACCEPT path:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5074
 * ---------------------------
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5075
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5076
 * soaccept() sends T_CONN_RES on the listener STREAM.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5077
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5078
 * tcp_accept() -> tcp_accept_swap() complete the processing and send
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5079
 * the bind_mp to eager perimeter to finish accept (tcp_rput_other()).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5080
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5081
 * Locks:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5082
 * ======
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5083
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5084
 * listener->tcp_eager_lock protects the listeners->tcp_eager_next_q0 and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5085
 * and listeners->tcp_eager_next_q.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5086
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5087
 * Referencing:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5088
 * ============
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5089
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5090
 * 1) We start out in tcp_conn_request by eager placing a ref on
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5091
 * listener and listener adding eager to listeners->tcp_eager_next_q0.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5092
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5093
 * 2) When a SYN-ACK-ACK arrives, we send the conn_ind to listener. Before
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5094
 * 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
  5095
 * end of tcp_accept_finish() while unwinding from the squeue, i.e. the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5096
 * reference is dropped by the squeue framework.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5097
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5098
 * 3) The ref on listener placed in 1 above is dropped in tcp_accept_finish
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5099
 * 
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5100
 * The reference must be released by the same entity that added the reference
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5101
 * In the above scheme, the eager is the entity that adds and releases the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5102
 * references. Note that tcp_accept_finish executes in the squeue of the eager
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5103
 * (albeit after it is attached to the acceptor stream). Though 1. executes
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5104
 * in the listener's squeue, the eager is nascent at this point and the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5105
 * reference can be considered to have been added on behalf of the eager.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5106
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5107
 * Eager getting a Reset or listener closing:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5108
 * ==========================================
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5109
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5110
 * Once the listener and eager are linked, the listener never does the unlink.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5111
 * If the listener needs to close, tcp_eager_cleanup() is called which queues
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5112
 * a message on all eager perimeter. The eager then does the unlink, clears
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5113
 * any pointers to the listener's queue and drops the reference to the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5114
 * listener. The listener waits in tcp_close outside the squeue until its
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5115
 * refcount has dropped to 1. This ensures that the listener has waited for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5116
 * all eagers to clear their association with the listener.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5117
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5118
 * Similarly, if eager decides to go away, it can unlink itself and close.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5119
 * When the T_CONN_RES comes down, we check if eager has closed. Note that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5120
 * the reference to eager is still valid because of the extra ref we put
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5121
 * in tcp_send_conn_ind.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5122
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5123
 * Listener can always locate the eager under the protection
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5124
 * of the listener->tcp_eager_lock, and then do a refhold
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5125
 * on the eager during the accept processing.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5126
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5127
 * The acceptor stream accesses the eager in the accept processing
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5128
 * based on the ref placed on eager before sending T_conn_ind.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5129
 * The only entity that can negate this refhold is a listener close
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5130
 * which is mutually exclusive with an active acceptor stream.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5131
 * 
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5132
 * Eager's reference on the listener
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5133
 * ===================================
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5134
 * 
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5135
 * If the accept happens (even on a closed eager) the eager drops its
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5136
 * reference on the listener at the start of tcp_accept_finish. If the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5137
 * 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
  5138
 * the reference is dropped in tcp_closei_local. If the listener closes,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5139
 * the reference is dropped in tcp_eager_kill. In all cases the reference
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5140
 * is dropped while executing in the eager's context (squeue).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5141
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5142
/* END CSTYLED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5143
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5144
/* Process the SYN packet, mp, directed at the listener 'tcp' */
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
 * THIS FUNCTION IS DIRECTLY CALLED BY IP VIA SQUEUE FOR SYN.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5148
 * tcp_rput_data will not see any SYN packets.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5149
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5150
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5151
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5152
tcp_conn_request(void *arg, mblk_t *mp, void *arg2)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5153
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5154
	tcph_t		*tcph;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5155
	uint32_t	seg_seq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5156
	tcp_t		*eager;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5157
	uint_t		ipvers;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5158
	ipha_t		*ipha;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5159
	ip6_t		*ip6h;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5160
	int		err;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5161
	conn_t		*econnp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5162
	squeue_t	*new_sqp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5163
	mblk_t		*mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5164
	uint_t 		ip_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5165
	conn_t		*connp = (conn_t *)arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5166
	tcp_t		*tcp = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5167
	ire_t		*ire;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5168
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5169
	if (tcp->tcp_state != TCPS_LISTEN)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5170
		goto error2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5171
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5172
	ASSERT((tcp->tcp_connp->conn_flags & IPCL_BOUND) != 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5173
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5174
	mutex_enter(&tcp->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5175
	if (tcp->tcp_conn_req_cnt_q >= tcp->tcp_conn_req_max) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5176
		mutex_exit(&tcp->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5177
		TCP_STAT(tcp_listendrop);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5178
		BUMP_MIB(&tcp_mib, tcpListenDrop);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5179
		if (tcp->tcp_debug) {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  5180
			(void) strlog(TCP_MOD_ID, 0, 1, SL_TRACE|SL_ERROR,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5181
			    "tcp_conn_request: listen backlog (max=%d) "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5182
			    "overflow (%d pending) on %s",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5183
			    tcp->tcp_conn_req_max, tcp->tcp_conn_req_cnt_q,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5184
			    tcp_display(tcp, NULL, DISP_PORT_ONLY));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5185
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5186
		goto error2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5187
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5188
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5189
	if (tcp->tcp_conn_req_cnt_q0 >=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5190
	    tcp->tcp_conn_req_max + tcp_conn_req_max_q0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5191
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5192
		 * Q0 is full. Drop a pending half-open req from the queue
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5193
		 * to make room for the new SYN req. Also mark the time we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5194
		 * drop a SYN.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5195
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5196
		 * A more aggressive defense against SYN attack will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5197
		 * be to set the "tcp_syn_defense" flag now.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5198
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5199
		TCP_STAT(tcp_listendropq0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5200
		tcp->tcp_last_rcv_lbolt = lbolt64;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5201
		if (!tcp_drop_q0(tcp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5202
			mutex_exit(&tcp->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5203
			BUMP_MIB(&tcp_mib, tcpListenDropQ0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5204
			if (tcp->tcp_debug) {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  5205
				(void) strlog(TCP_MOD_ID, 0, 3, SL_TRACE,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5206
				    "tcp_conn_request: listen half-open queue "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5207
				    "(max=%d) full (%d pending) on %s",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5208
				    tcp_conn_req_max_q0,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5209
				    tcp->tcp_conn_req_cnt_q0,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5210
				    tcp_display(tcp, NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5211
				    DISP_PORT_ONLY));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5212
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5213
			goto error2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5214
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5215
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5216
	mutex_exit(&tcp->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5217
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5218
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5219
	 * IP adds STRUIO_EAGER and ensures that the received packet is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5220
	 * M_DATA even if conn_ipv6_recvpktinfo is enabled or for ip6
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5221
	 * link local address.  If IPSec is enabled, db_struioflag has
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5222
	 * STRUIO_POLICY set (mutually exclusive from STRUIO_EAGER);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5223
	 * otherwise an error case if neither of them is set.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5224
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5225
	if ((mp->b_datap->db_struioflag & STRUIO_EAGER) != 0) {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  5226
		new_sqp = (squeue_t *)DB_CKSUMSTART(mp);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  5227
		DB_CKSUMSTART(mp) = 0;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5228
		mp->b_datap->db_struioflag &= ~STRUIO_EAGER;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5229
		econnp = (conn_t *)tcp_get_conn(arg2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5230
		if (econnp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5231
			goto error2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5232
		econnp->conn_sqp = new_sqp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5233
	} else if ((mp->b_datap->db_struioflag & STRUIO_POLICY) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5234
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5235
		 * mp is updated in tcp_get_ipsec_conn().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5236
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5237
		econnp = tcp_get_ipsec_conn(tcp, arg2, &mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5238
		if (econnp == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5239
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5240
			 * mp freed by tcp_get_ipsec_conn.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5241
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5242
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5243
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5244
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5245
		goto error2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5246
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5247
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5248
	ASSERT(DB_TYPE(mp) == M_DATA);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5249
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5250
	ipvers = IPH_HDR_VERSION(mp->b_rptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5251
	ASSERT(ipvers == IPV6_VERSION || ipvers == IPV4_VERSION);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5252
	ASSERT(OK_32PTR(mp->b_rptr));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5253
	if (ipvers == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5254
		ipha = (ipha_t *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5255
		ip_hdr_len = IPH_HDR_LENGTH(ipha);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5256
		tcph = (tcph_t *)&mp->b_rptr[ip_hdr_len];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5257
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5258
		ip6h = (ip6_t *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5259
		ip_hdr_len = ip_hdr_length_v6(mp, ip6h);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5260
		tcph = (tcph_t *)&mp->b_rptr[ip_hdr_len];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5261
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5262
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5263
	if (tcp->tcp_family == AF_INET) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5264
		ASSERT(ipvers == IPV4_VERSION);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5265
		err = tcp_conn_create_v4(connp, econnp, ipha, tcph, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5266
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5267
		err = tcp_conn_create_v6(connp, econnp, mp, tcph, ipvers, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5268
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5269
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5270
	if (err)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5271
		goto error3;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5272
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5273
	eager = econnp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5274
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5275
	/* Inherit various TCP parameters from the listener */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5276
	eager->tcp_naglim = tcp->tcp_naglim;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5277
	eager->tcp_first_timer_threshold =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5278
	    tcp->tcp_first_timer_threshold;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5279
	eager->tcp_second_timer_threshold =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5280
	    tcp->tcp_second_timer_threshold;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5281
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5282
	eager->tcp_first_ctimer_threshold =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5283
	    tcp->tcp_first_ctimer_threshold;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5284
	eager->tcp_second_ctimer_threshold =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5285
	    tcp->tcp_second_ctimer_threshold;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5286
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5287
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5288
	 * Zones: tcp_adapt_ire() and tcp_send_data() both need the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5289
	 * zone id before the accept is completed in tcp_wput_accept().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5290
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5291
	econnp->conn_zoneid = connp->conn_zoneid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5292
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5293
	eager->tcp_hard_binding = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5294
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5295
	tcp_bind_hash_insert(&tcp_bind_fanout[
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5296
	    TCP_BIND_HASH(eager->tcp_lport)], eager, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5297
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5298
	CL_INET_CONNECT(eager);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5299
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5300
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5301
	 * No need to check for multicast destination since ip will only pass
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5302
	 * up multicasts to those that have expressed interest
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5303
	 * TODO: what about rejecting broadcasts?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5304
	 * Also check that source is not a multicast or broadcast address.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5305
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5306
	eager->tcp_state = TCPS_SYN_RCVD;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5307
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5308
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5309
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5310
	 * There should be no ire in the mp as we are being called after
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5311
	 * receiving the SYN.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5312
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5313
	ASSERT(tcp_ire_mp(mp) == NULL);
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
	 * Adapt our mss, ttl, ... according to information provided in IRE.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5317
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5318
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5319
	if (tcp_adapt_ire(eager, NULL) == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5320
		/* Undo the bind_hash_insert */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5321
		tcp_bind_hash_remove(eager);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5322
		goto error3;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5323
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5324
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5325
	/* Process all TCP options. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5326
	tcp_process_options(eager, tcph);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5327
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5328
	/* Is the other end ECN capable? */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5329
	if (tcp_ecn_permitted >= 1 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5330
	    (tcph->th_flags[0] & (TH_ECE|TH_CWR)) == (TH_ECE|TH_CWR)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5331
		eager->tcp_ecn_ok = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5332
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5333
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5334
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5335
	 * listener->tcp_rq->q_hiwat should be the default window size or a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5336
	 * window size changed via SO_RCVBUF option.  First round up the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5337
	 * eager's tcp_rwnd to the nearest MSS.  Then find out the window
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5338
	 * scale option value if needed.  Call tcp_rwnd_set() to finish the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5339
	 * setting.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5340
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5341
	 * Note if there is a rpipe metric associated with the remote host,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5342
	 * we should not inherit receive window size from listener.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5343
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5344
	eager->tcp_rwnd = MSS_ROUNDUP(
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5345
	    (eager->tcp_rwnd == 0 ? tcp->tcp_rq->q_hiwat :
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5346
	    eager->tcp_rwnd), eager->tcp_mss);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5347
	if (eager->tcp_snd_ws_ok)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5348
		tcp_set_ws_value(eager);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5349
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5350
	 * Note that this is the only place tcp_rwnd_set() is called for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5351
	 * accepting a connection.  We need to call it here instead of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5352
	 * after the 3-way handshake because we need to tell the other
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5353
	 * side our rwnd in the SYN-ACK segment.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5354
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5355
	(void) tcp_rwnd_set(eager, eager->tcp_rwnd);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5356
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5357
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5358
	 * We eliminate the need for sockfs to send down a T_SVR4_OPTMGMT_REQ
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5359
	 * via soaccept()->soinheritoptions() which essentially applies
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5360
	 * all the listener options to the new STREAM. The options that we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5361
	 * need to take care of are:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5362
	 * SO_DEBUG, SO_REUSEADDR, SO_KEEPALIVE, SO_DONTROUTE, SO_BROADCAST,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5363
	 * SO_USELOOPBACK, SO_OOBINLINE, SO_DGRAM_ERRIND, SO_LINGER,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5364
	 * SO_SNDBUF, SO_RCVBUF.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5365
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5366
	 * SO_RCVBUF:	tcp_rwnd_set() above takes care of it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5367
	 * SO_SNDBUF:	Set the tcp_xmit_hiwater for the eager. When
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5368
	 *		tcp_maxpsz_set() gets called later from
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5369
	 *		tcp_accept_finish(), the option takes effect.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5370
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5371
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5372
	/* Set the TCP options */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5373
	eager->tcp_xmit_hiwater = tcp->tcp_xmit_hiwater;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5374
	eager->tcp_dgram_errind = tcp->tcp_dgram_errind;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5375
	eager->tcp_oobinline = tcp->tcp_oobinline;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5376
	eager->tcp_reuseaddr = tcp->tcp_reuseaddr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5377
	eager->tcp_broadcast = tcp->tcp_broadcast;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5378
	eager->tcp_useloopback = tcp->tcp_useloopback;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5379
	eager->tcp_dontroute = tcp->tcp_dontroute;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5380
	eager->tcp_linger = tcp->tcp_linger;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5381
	eager->tcp_lingertime = tcp->tcp_lingertime;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5382
	if (tcp->tcp_ka_enabled)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5383
		eager->tcp_ka_enabled = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5384
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5385
	/* Set the IP options */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5386
	econnp->conn_broadcast = connp->conn_broadcast;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5387
	econnp->conn_loopback = connp->conn_loopback;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5388
	econnp->conn_dontroute = connp->conn_dontroute;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5389
	econnp->conn_reuseaddr = connp->conn_reuseaddr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5390
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5391
	/* Put a ref on the listener for the eager. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5392
	CONN_INC_REF(connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5393
	mutex_enter(&tcp->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5394
	tcp->tcp_eager_next_q0->tcp_eager_prev_q0 = eager;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5395
	eager->tcp_eager_next_q0 = tcp->tcp_eager_next_q0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5396
	tcp->tcp_eager_next_q0 = eager;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5397
	eager->tcp_eager_prev_q0 = tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5398
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5399
	/* Set tcp_listener before adding it to tcp_conn_fanout */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5400
	eager->tcp_listener = tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5401
	eager->tcp_saved_listener = tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5402
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5403
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5404
	 * Tag this detached tcp vector for later retrieval
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5405
	 * by our listener client in tcp_accept().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5406
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5407
	eager->tcp_conn_req_seqnum = tcp->tcp_conn_req_seqnum;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5408
	tcp->tcp_conn_req_cnt_q0++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5409
	if (++tcp->tcp_conn_req_seqnum == -1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5410
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5411
		 * -1 is "special" and defined in TPI as something
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5412
		 * that should never be used in T_CONN_IND
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5413
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5414
		++tcp->tcp_conn_req_seqnum;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5415
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5416
	mutex_exit(&tcp->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5417
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5418
	if (tcp->tcp_syn_defense) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5419
		/* Don't drop the SYN that comes from a good IP source */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5420
		ipaddr_t *addr_cache = (ipaddr_t *)(tcp->tcp_ip_addr_cache);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5421
		if (addr_cache != NULL && eager->tcp_remote ==
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5422
		    addr_cache[IP_ADDR_CACHE_HASH(eager->tcp_remote)]) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5423
			eager->tcp_dontdrop = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5424
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5425
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5426
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5427
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5428
	 * We need to insert the eager in its own perimeter but as soon
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5429
	 * as we do that, we expose the eager to the classifier and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5430
	 * should not touch any field outside the eager's perimeter.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5431
	 * So do all the work necessary before inserting the eager
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5432
	 * in its own perimeter. Be optimistic that ipcl_conn_insert()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5433
	 * will succeed but undo everything if it fails.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5434
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5435
	seg_seq = ABE32_TO_U32(tcph->th_seq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5436
	eager->tcp_irs = seg_seq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5437
	eager->tcp_rack = seg_seq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5438
	eager->tcp_rnxt = seg_seq + 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5439
	U32_TO_ABE32(eager->tcp_rnxt, eager->tcp_tcph->th_ack);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5440
	BUMP_MIB(&tcp_mib, tcpPassiveOpens);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5441
	eager->tcp_state = TCPS_SYN_RCVD;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5442
	mp1 = tcp_xmit_mp(eager, eager->tcp_xmit_head, eager->tcp_mss,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5443
	    NULL, NULL, eager->tcp_iss, B_FALSE, NULL, B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5444
	if (mp1 == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5445
		goto error1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5446
	mblk_setcred(mp1, tcp->tcp_cred);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5447
	DB_CPID(mp1) = tcp->tcp_cpid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5448
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5449
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5450
	 * We need to start the rto timer. In normal case, we start
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5451
	 * the timer after sending the packet on the wire (or at
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5452
	 * least believing that packet was sent by waiting for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5453
	 * CALL_IP_WPUT() to return). Since this is the first packet
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5454
	 * being sent on the wire for the eager, our initial tcp_rto
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5455
	 * is at least tcp_rexmit_interval_min which is a fairly
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5456
	 * large value to allow the algorithm to adjust slowly to large
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5457
	 * fluctuations of RTT during first few transmissions.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5458
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5459
	 * Starting the timer first and then sending the packet in this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5460
	 * case shouldn't make much difference since tcp_rexmit_interval_min
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5461
	 * is of the order of several 100ms and starting the timer
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5462
	 * first and then sending the packet will result in difference
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5463
	 * of few micro seconds.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5464
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5465
	 * Without this optimization, we are forced to hold the fanout
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5466
	 * lock across the ipcl_bind_insert() and sending the packet
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5467
	 * so that we don't race against an incoming packet (maybe RST)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5468
	 * for this eager.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5469
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5470
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5471
	TCP_RECORD_TRACE(eager, mp1, TCP_TRACE_SEND_PKT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5472
	TCP_TIMER_RESTART(eager, eager->tcp_rto);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5473
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5474
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5475
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5476
	 * Insert the eager in its own perimeter now. We are ready to deal
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5477
	 * with any packets on eager.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5478
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5479
	if (eager->tcp_ipversion == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5480
		if (ipcl_conn_insert(econnp, IPPROTO_TCP, 0, 0, 0) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5481
			goto error;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5482
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5483
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5484
		if (ipcl_conn_insert_v6(econnp, IPPROTO_TCP, 0, 0, 0, 0) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5485
			goto error;
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
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5489
	/* mark conn as fully-bound */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5490
	econnp->conn_fully_bound = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5491
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5492
	/* Send the SYN-ACK */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5493
	tcp_send_data(eager, eager->tcp_wq, mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5494
	freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5495
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5496
	return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5497
error:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5498
	(void) TCP_TIMER_CANCEL(eager, eager->tcp_timer_tid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5499
	freemsg(mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5500
error1:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5501
	/* Undo what we did above */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5502
	mutex_enter(&tcp->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5503
	tcp_eager_unlink(eager);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5504
	mutex_exit(&tcp->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5505
	/* Drop eager's reference on the listener */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5506
	CONN_DEC_REF(connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5507
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5508
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5509
	 * Delete the cached ire in conn_ire_cache and also mark
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5510
	 * the conn as CONDEMNED
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5511
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5512
	mutex_enter(&econnp->conn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5513
	econnp->conn_state_flags |= CONN_CONDEMNED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5514
	ire = econnp->conn_ire_cache;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5515
	econnp->conn_ire_cache = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5516
	mutex_exit(&econnp->conn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5517
	if (ire != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5518
		IRE_REFRELE_NOTR(ire);
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
	 * tcp_accept_comm inserts the eager to the bind_hash
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5522
	 * we need to remove it from the hash if ipcl_conn_insert
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5523
	 * fails.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5524
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5525
	tcp_bind_hash_remove(eager);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5526
	/* Drop the eager ref placed in tcp_open_detached */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5527
	CONN_DEC_REF(econnp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5528
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5529
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5530
	 * If a connection already exists, send the mp to that connections so
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5531
	 * that it can be appropriately dealt with.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5532
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5533
	if ((econnp = ipcl_classify(mp, connp->conn_zoneid)) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5534
		if (!IPCL_IS_CONNECTED(econnp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5535
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5536
			 * Something bad happened. ipcl_conn_insert()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5537
			 * failed because a connection already existed
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5538
			 * in connected hash but we can't find it
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5539
			 * anymore (someone blew it away). Just
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5540
			 * free this message and hopefully remote
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5541
			 * will retransmit at which time the SYN can be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5542
			 * treated as a new connection or dealth with
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5543
			 * a TH_RST if a connection already exists.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5544
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5545
			freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5546
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5547
			squeue_fill(econnp->conn_sqp, mp, tcp_input,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5548
			    econnp, SQTAG_TCP_CONN_REQ);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5549
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5550
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5551
		/* Nobody wants this packet */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5552
		freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5553
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5554
	return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5555
error2:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5556
	freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5557
	return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5558
error3:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5559
	CONN_DEC_REF(econnp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5560
	freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5561
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5562
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5563
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5564
 * In an ideal case of vertical partition in NUMA architecture, its
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5565
 * beneficial to have the listener and all the incoming connections
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5566
 * tied to the same squeue. The other constraint is that incoming
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5567
 * connections should be tied to the squeue attached to interrupted
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5568
 * CPU for obvious locality reason so this leaves the listener to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5569
 * be tied to the same squeue. Our only problem is that when listener
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5570
 * is binding, the CPU that will get interrupted by the NIC whose
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5571
 * IP address the listener is binding to is not even known. So
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5572
 * the code below allows us to change that binding at the time the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5573
 * CPU is interrupted by virtue of incoming connection's squeue.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5574
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5575
 * This is usefull only in case of a listener bound to a specific IP
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5576
 * address. For other kind of listeners, they get bound the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5577
 * very first time and there is no attempt to rebind them.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5578
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5579
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5580
tcp_conn_request_unbound(void *arg, mblk_t *mp, void *arg2)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5581
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5582
	conn_t		*connp = (conn_t *)arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5583
	squeue_t	*sqp = (squeue_t *)arg2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5584
	squeue_t	*new_sqp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5585
	uint32_t	conn_flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5586
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5587
	if ((mp->b_datap->db_struioflag & STRUIO_EAGER) != 0) {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  5588
		new_sqp = (squeue_t *)DB_CKSUMSTART(mp);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5589
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5590
		goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5591
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5592
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5593
	if (connp->conn_fanout == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5594
		goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5595
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5596
	if (!(connp->conn_flags & IPCL_FULLY_BOUND)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5597
		mutex_enter(&connp->conn_fanout->connf_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5598
		mutex_enter(&connp->conn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5599
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5600
		 * No one from read or write side can access us now
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5601
		 * except for already queued packets on this squeue.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5602
		 * But since we haven't changed the squeue yet, they
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5603
		 * can't execute. If they are processed after we have
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5604
		 * changed the squeue, they are sent back to the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5605
		 * correct squeue down below.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5606
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5607
		if (connp->conn_sqp != new_sqp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5608
			while (connp->conn_sqp != new_sqp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5609
				(void) casptr(&connp->conn_sqp, sqp, new_sqp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5610
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5611
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5612
		do {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5613
			conn_flags = connp->conn_flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5614
			conn_flags |= IPCL_FULLY_BOUND;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5615
			(void) cas32(&connp->conn_flags, connp->conn_flags,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5616
			    conn_flags);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5617
		} while (!(connp->conn_flags & IPCL_FULLY_BOUND));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5618
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5619
		mutex_exit(&connp->conn_fanout->connf_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5620
		mutex_exit(&connp->conn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5621
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5622
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5623
done:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5624
	if (connp->conn_sqp != sqp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5625
		CONN_INC_REF(connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5626
		squeue_fill(connp->conn_sqp, mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5627
		    connp->conn_recv, connp, SQTAG_TCP_CONN_REQ_UNBOUND);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5628
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5629
		tcp_conn_request(connp, mp, sqp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5630
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5631
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5632
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5633
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5634
 * Successful connect request processing begins when our client passes
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5635
 * a T_CONN_REQ message into tcp_wput() and ends when tcp_rput() passes
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5636
 * our T_OK_ACK reply message upstream.  The control flow looks like this:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5637
 *   upstream -> tcp_wput() -> tcp_wput_proto() -> tcp_connect() -> IP
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5638
 *   upstream <- tcp_rput()                <- IP
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5639
 * After various error checks are completed, tcp_connect() lays
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5640
 * the target address and port into the composite header template,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5641
 * preallocates the T_OK_ACK reply message, construct a full 12 byte bind
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5642
 * request followed by an IRE request, and passes the three mblk message
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5643
 * down to IP looking like this:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5644
 *   O_T_BIND_REQ for IP  --> IRE req --> T_OK_ACK for our client
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5645
 * Processing continues in tcp_rput() when we receive the following message:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5646
 *   T_BIND_ACK from IP --> IRE ack --> T_OK_ACK for our client
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5647
 * After consuming the first two mblks, tcp_rput() calls tcp_timer(),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5648
 * to fire off the connection request, and then passes the T_OK_ACK mblk
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5649
 * upstream that we filled in below.  There are, of course, numerous
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5650
 * error conditions along the way which truncate the processing described
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5651
 * above.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5652
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5653
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5654
tcp_connect(tcp_t *tcp, mblk_t *mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5655
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5656
	sin_t		*sin;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5657
	sin6_t		*sin6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5658
	queue_t		*q = tcp->tcp_wq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5659
	struct T_conn_req	*tcr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5660
	ipaddr_t	*dstaddrp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5661
	in_port_t	dstport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5662
	uint_t		srcid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5663
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5664
	tcr = (struct T_conn_req *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5665
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5666
	ASSERT((uintptr_t)(mp->b_wptr - mp->b_rptr) <= (uintptr_t)INT_MAX);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5667
	if ((mp->b_wptr - mp->b_rptr) < sizeof (*tcr)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5668
		tcp_err_ack(tcp, mp, TPROTO, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5669
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5670
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5671
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5672
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5673
	 * Determine packet type based on type of address passed in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5674
	 * the request should contain an IPv4 or IPv6 address.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5675
	 * Make sure that address family matches the type of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5676
	 * family of the the address passed down
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5677
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5678
	switch (tcr->DEST_length) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5679
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5680
		tcp_err_ack(tcp, mp, TBADADDR, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5681
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5682
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5683
	case (sizeof (sin_t) - sizeof (sin->sin_zero)): {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5684
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5685
		 * XXX: The check for valid DEST_length was not there
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5686
		 * in earlier releases and some buggy
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5687
		 * TLI apps (e.g Sybase) got away with not feeding
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5688
		 * in sin_zero part of address.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5689
		 * We allow that bug to keep those buggy apps humming.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5690
		 * Test suites require the check on DEST_length.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5691
		 * We construct a new mblk with valid DEST_length
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5692
		 * free the original so the rest of the code does
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5693
		 * not have to keep track of this special shorter
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5694
		 * length address case.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5695
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5696
		mblk_t *nmp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5697
		struct T_conn_req *ntcr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5698
		sin_t *nsin;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5699
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5700
		nmp = allocb(sizeof (struct T_conn_req) + sizeof (sin_t) +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5701
		    tcr->OPT_length, BPRI_HI);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5702
		if (nmp == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5703
			tcp_err_ack(tcp, mp, TSYSERR, ENOMEM);
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
		ntcr = (struct T_conn_req *)nmp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5707
		bzero(ntcr, sizeof (struct T_conn_req)); /* zero fill */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5708
		ntcr->PRIM_type = T_CONN_REQ;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5709
		ntcr->DEST_length = sizeof (sin_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5710
		ntcr->DEST_offset = sizeof (struct T_conn_req);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5711
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5712
		nsin = (sin_t *)((uchar_t *)ntcr + ntcr->DEST_offset);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5713
		*nsin = sin_null;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5714
		/* Get pointer to shorter address to copy from original mp */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5715
		sin = (sin_t *)mi_offset_param(mp, tcr->DEST_offset,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5716
		    tcr->DEST_length); /* extract DEST_length worth of sin_t */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5717
		if (sin == NULL || !OK_32PTR((char *)sin)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5718
			freemsg(nmp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5719
			tcp_err_ack(tcp, mp, TSYSERR, EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5720
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5721
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5722
		nsin->sin_family = sin->sin_family;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5723
		nsin->sin_port = sin->sin_port;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5724
		nsin->sin_addr = sin->sin_addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5725
		/* Note:nsin->sin_zero zero-fill with sin_null assign above */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5726
		nmp->b_wptr = (uchar_t *)&nsin[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5727
		if (tcr->OPT_length != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5728
			ntcr->OPT_length = tcr->OPT_length;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5729
			ntcr->OPT_offset = nmp->b_wptr - nmp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5730
			bcopy((uchar_t *)tcr + tcr->OPT_offset,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5731
			    (uchar_t *)ntcr + ntcr->OPT_offset,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5732
			    tcr->OPT_length);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5733
			nmp->b_wptr += tcr->OPT_length;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5734
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5735
		freemsg(mp);	/* original mp freed */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5736
		mp = nmp;	/* re-initialize original variables */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5737
		tcr = ntcr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5738
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5739
	/* FALLTHRU */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5740
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5741
	case sizeof (sin_t):
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5742
		sin = (sin_t *)mi_offset_param(mp, tcr->DEST_offset,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5743
		    sizeof (sin_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5744
		if (sin == NULL || !OK_32PTR((char *)sin)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5745
			tcp_err_ack(tcp, mp, TSYSERR, EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5746
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5747
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5748
		if (tcp->tcp_family != AF_INET ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5749
		    sin->sin_family != AF_INET) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5750
			tcp_err_ack(tcp, mp, TSYSERR, EAFNOSUPPORT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5751
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5752
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5753
		if (sin->sin_port == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5754
			tcp_err_ack(tcp, mp, TBADADDR, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5755
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5756
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5757
		if (tcp->tcp_connp && tcp->tcp_connp->conn_ipv6_v6only) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5758
			tcp_err_ack(tcp, mp, TSYSERR, EAFNOSUPPORT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5759
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5760
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5761
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5762
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5763
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5764
	case sizeof (sin6_t):
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5765
		sin6 = (sin6_t *)mi_offset_param(mp, tcr->DEST_offset,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5766
		    sizeof (sin6_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5767
		if (sin6 == NULL || !OK_32PTR((char *)sin6)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5768
			tcp_err_ack(tcp, mp, TSYSERR, EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5769
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5770
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5771
		if (tcp->tcp_family != AF_INET6 ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5772
		    sin6->sin6_family != AF_INET6) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5773
			tcp_err_ack(tcp, mp, TSYSERR, EAFNOSUPPORT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5774
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5775
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5776
		if (sin6->sin6_port == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5777
			tcp_err_ack(tcp, mp, TBADADDR, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5778
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5779
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5780
		break;
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
	 * TODO: If someone in TCPS_TIME_WAIT has this dst/port we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5784
	 * should key on their sequence number and cut them loose.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5785
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5786
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5787
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5788
	 * If options passed in, feed it for verification and handling
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5789
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5790
	if (tcr->OPT_length != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5791
		mblk_t	*ok_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5792
		mblk_t	*discon_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5793
		mblk_t  *conn_opts_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5794
		int t_error, sys_error, do_disconnect;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5795
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5796
		conn_opts_mp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5797
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5798
		if (tcp_conprim_opt_process(tcp, mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5799
			&do_disconnect, &t_error, &sys_error) < 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5800
			if (do_disconnect) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5801
				ASSERT(t_error == 0 && sys_error == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5802
				discon_mp = mi_tpi_discon_ind(NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5803
				    ECONNREFUSED, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5804
				if (!discon_mp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5805
					tcp_err_ack_prim(tcp, mp, T_CONN_REQ,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5806
					    TSYSERR, ENOMEM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5807
					return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5808
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5809
				ok_mp = mi_tpi_ok_ack_alloc(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5810
				if (!ok_mp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5811
					tcp_err_ack_prim(tcp, NULL, T_CONN_REQ,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5812
					    TSYSERR, ENOMEM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5813
					return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5814
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5815
				qreply(q, ok_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5816
				qreply(q, discon_mp); /* no flush! */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5817
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5818
				ASSERT(t_error != 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5819
				tcp_err_ack_prim(tcp, mp, T_CONN_REQ, t_error,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5820
				    sys_error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5821
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5822
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5823
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5824
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5825
		 * Success in setting options, the mp option buffer represented
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5826
		 * by OPT_length/offset has been potentially modified and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5827
		 * contains results of option processing. We copy it in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5828
		 * another mp to save it for potentially influencing returning
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5829
		 * it in T_CONN_CONN.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5830
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5831
		if (tcr->OPT_length != 0) { /* there are resulting options */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5832
			conn_opts_mp = copyb(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5833
			if (!conn_opts_mp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5834
				tcp_err_ack_prim(tcp, mp, T_CONN_REQ,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5835
				    TSYSERR, ENOMEM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5836
				return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5837
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5838
			ASSERT(tcp->tcp_conn.tcp_opts_conn_req == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5839
			tcp->tcp_conn.tcp_opts_conn_req = conn_opts_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5840
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5841
			 * Note:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5842
			 * These resulting option negotiation can include any
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5843
			 * end-to-end negotiation options but there no such
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5844
			 * thing (yet?) in our TCP/IP.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5845
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5846
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5847
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5848
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5849
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5850
	 * If we're connecting to an IPv4-mapped IPv6 address, we need to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5851
	 * make sure that the template IP header in the tcp structure is an
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5852
	 * IPv4 header, and that the tcp_ipversion is IPV4_VERSION.  We
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5853
	 * need to this before we call tcp_bindi() so that the port lookup
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5854
	 * code will look for ports in the correct port space (IPv4 and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5855
	 * IPv6 have separate port spaces).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5856
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5857
	if (tcp->tcp_family == AF_INET6 && tcp->tcp_ipversion == IPV6_VERSION &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5858
	    IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5859
		int err = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5860
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5861
		err = tcp_header_init_ipv4(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5862
		if (err != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5863
			mp = mi_tpi_err_ack_alloc(mp, TSYSERR, ENOMEM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5864
			goto connect_failed;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5865
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5866
		if (tcp->tcp_lport != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5867
			*(uint16_t *)tcp->tcp_tcph->th_lport = tcp->tcp_lport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5868
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5869
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5870
	switch (tcp->tcp_state) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5871
	case TCPS_IDLE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5872
		/*
646
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  5873
		 * We support quick connect, refer to comments in
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  5874
		 * tcp_connect_*()
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  5875
		 */
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5876
		/* FALLTHRU */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5877
	case TCPS_BOUND:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5878
	case TCPS_LISTEN:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5879
		if (tcp->tcp_family == AF_INET6) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5880
			if (!IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5881
				tcp_connect_ipv6(tcp, mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5882
				    &sin6->sin6_addr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5883
				    sin6->sin6_port, sin6->sin6_flowinfo,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5884
				    sin6->__sin6_src_id, sin6->sin6_scope_id);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5885
				return;
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
			 * Destination adress is mapped IPv6 address.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5889
			 * Source bound address should be unspecified or
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5890
			 * IPv6 mapped address as well.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5891
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5892
			if (!IN6_IS_ADDR_UNSPECIFIED(
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5893
			    &tcp->tcp_bound_source_v6) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5894
			    !IN6_IS_ADDR_V4MAPPED(&tcp->tcp_bound_source_v6)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5895
				mp = mi_tpi_err_ack_alloc(mp, TSYSERR,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5896
				    EADDRNOTAVAIL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5897
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5898
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5899
			dstaddrp = &V4_PART_OF_V6((sin6->sin6_addr));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5900
			dstport = sin6->sin6_port;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5901
			srcid = sin6->__sin6_src_id;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5902
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5903
			dstaddrp = &sin->sin_addr.s_addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5904
			dstport = sin->sin_port;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5905
			srcid = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5906
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5907
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5908
		tcp_connect_ipv4(tcp, mp, dstaddrp, dstport, srcid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5909
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5910
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5911
		mp = mi_tpi_err_ack_alloc(mp, TOUTSTATE, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5912
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5913
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5914
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5915
	 * Note: Code below is the "failure" case
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5916
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5917
	/* return error ack and blow away saved option results if any */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5918
connect_failed:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5919
	if (mp != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5920
		putnext(tcp->tcp_rq, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5921
	else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5922
		tcp_err_ack_prim(tcp, NULL, T_CONN_REQ,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5923
		    TSYSERR, ENOMEM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5924
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5925
	if (tcp->tcp_conn.tcp_opts_conn_req != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5926
		tcp_close_mpp(&tcp->tcp_conn.tcp_opts_conn_req);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5927
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5928
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5929
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5930
 * Handle connect to IPv4 destinations, including connections for AF_INET6
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5931
 * sockets connecting to IPv4 mapped IPv6 destinations.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5932
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5933
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5934
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
  5935
    uint_t srcid)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5936
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5937
	tcph_t	*tcph;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5938
	mblk_t	*mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5939
	ipaddr_t dstaddr = *dstaddrp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5940
	int32_t	oldstate;
646
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  5941
	uint16_t lport;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5942
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5943
	ASSERT(tcp->tcp_ipversion == IPV4_VERSION);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5944
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5945
	/* Check for attempt to connect to INADDR_ANY */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5946
	if (dstaddr == INADDR_ANY)  {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5947
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5948
		 * SunOS 4.x and 4.3 BSD allow an application
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5949
		 * to connect a TCP socket to INADDR_ANY.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5950
		 * When they do this, the kernel picks the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5951
		 * address of one interface and uses it
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5952
		 * instead.  The kernel usually ends up
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5953
		 * picking the address of the loopback
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5954
		 * interface.  This is an undocumented feature.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5955
		 * However, we provide the same thing here
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5956
		 * in order to have source and binary
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5957
		 * compatibility with SunOS 4.x.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5958
		 * Update the T_CONN_REQ (sin/sin6) since it is used to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5959
		 * generate the T_CONN_CON.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5960
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5961
		dstaddr = htonl(INADDR_LOOPBACK);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5962
		*dstaddrp = dstaddr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5963
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5964
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5965
	/* Handle __sin6_src_id if socket not bound to an IP address */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5966
	if (srcid != 0 && tcp->tcp_ipha->ipha_src == INADDR_ANY) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5967
		ip_srcid_find_id(srcid, &tcp->tcp_ip_src_v6,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5968
		    tcp->tcp_connp->conn_zoneid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5969
		IN6_V4MAPPED_TO_IPADDR(&tcp->tcp_ip_src_v6,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5970
		    tcp->tcp_ipha->ipha_src);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5971
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5972
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5973
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5974
	 * Don't let an endpoint connect to itself.  Note that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5975
	 * the test here does not catch the case where the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5976
	 * source IP addr was left unspecified by the user. In
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5977
	 * this case, the source addr is set in tcp_adapt_ire()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5978
	 * using the reply to the T_BIND message that we send
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5979
	 * down to IP here and the check is repeated in tcp_rput_other.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5980
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5981
	if (dstaddr == tcp->tcp_ipha->ipha_src &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5982
	    dstport == tcp->tcp_lport) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5983
		mp = mi_tpi_err_ack_alloc(mp, TBADADDR, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5984
		goto failed;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5985
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5986
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5987
	tcp->tcp_ipha->ipha_dst = dstaddr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5988
	IN6_IPADDR_TO_V4MAPPED(dstaddr, &tcp->tcp_remote_v6);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5989
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5990
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5991
	 * Massage a source route if any putting the first hop
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5992
	 * in iph_dst. Compute a starting value for the checksum which
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5993
	 * takes into account that the original iph_dst should be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5994
	 * included in the checksum but that ip will include the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5995
	 * first hop in the source route in the tcp checksum.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5996
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5997
	tcp->tcp_sum = ip_massage_options(tcp->tcp_ipha);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5998
	tcp->tcp_sum = (tcp->tcp_sum & 0xFFFF) + (tcp->tcp_sum >> 16);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5999
	tcp->tcp_sum -= ((tcp->tcp_ipha->ipha_dst >> 16) +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6000
	    (tcp->tcp_ipha->ipha_dst & 0xffff));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6001
	if ((int)tcp->tcp_sum < 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6002
		tcp->tcp_sum--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6003
	tcp->tcp_sum = (tcp->tcp_sum & 0xFFFF) + (tcp->tcp_sum >> 16);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6004
	tcp->tcp_sum = ntohs((tcp->tcp_sum & 0xFFFF) +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6005
	    (tcp->tcp_sum >> 16));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6006
	tcph = tcp->tcp_tcph;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6007
	*(uint16_t *)tcph->th_fport = dstport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6008
	tcp->tcp_fport = dstport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6009
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6010
	oldstate = tcp->tcp_state;
646
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  6011
	/*
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  6012
	 * 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
  6013
	 * 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
  6014
	 * 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
  6015
	 */
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  6016
	if (oldstate == TCPS_IDLE) {
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  6017
		/*
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  6018
		 * We support a quick connect capability here, allowing
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  6019
		 * clients to transition directly from IDLE to SYN_SENT
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  6020
		 * 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
  6021
		 * in the bind hash and transition to BOUND state.
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  6022
		 */
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  6023
		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
  6024
		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
  6025
		    B_FALSE, B_FALSE);
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  6026
		if (lport == 0) {
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  6027
			mp = mi_tpi_err_ack_alloc(mp, TNOADDR, 0);
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  6028
			goto failed;
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  6029
		}
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  6030
	}
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6031
	tcp->tcp_state = TCPS_SYN_SENT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6032
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6033
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6034
	 * TODO: allow data with connect requests
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6035
	 * by unlinking M_DATA trailers here and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6036
	 * linking them in behind the T_OK_ACK mblk.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6037
	 * The tcp_rput() bind ack handler would then
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6038
	 * feed them to tcp_wput_data() rather than call
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6039
	 * tcp_timer().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6040
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6041
	mp = mi_tpi_ok_ack_alloc(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6042
	if (!mp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6043
		tcp->tcp_state = oldstate;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6044
		goto failed;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6045
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6046
	if (tcp->tcp_family == AF_INET) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6047
		mp1 = tcp_ip_bind_mp(tcp, O_T_BIND_REQ,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6048
		    sizeof (ipa_conn_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6049
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6050
		mp1 = tcp_ip_bind_mp(tcp, O_T_BIND_REQ,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6051
		    sizeof (ipa6_conn_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6052
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6053
	if (mp1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6054
		/* Hang onto the T_OK_ACK for later. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6055
		linkb(mp1, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6056
		if (tcp->tcp_family == AF_INET)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6057
			mp1 = ip_bind_v4(tcp->tcp_wq, mp1, tcp->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6058
		else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6059
			mp1 = ip_bind_v6(tcp->tcp_wq, mp1, tcp->tcp_connp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6060
			    &tcp->tcp_sticky_ipp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6061
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6062
		BUMP_MIB(&tcp_mib, tcpActiveOpens);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6063
		tcp->tcp_active_open = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6064
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6065
		 * If the bind cannot complete immediately
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6066
		 * IP will arrange to call tcp_rput_other
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6067
		 * when the bind completes.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6068
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6069
		if (mp1 != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6070
			tcp_rput_other(tcp, mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6071
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6072
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6073
	/* Error case */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6074
	tcp->tcp_state = oldstate;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6075
	mp = mi_tpi_err_ack_alloc(mp, TSYSERR, ENOMEM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6076
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6077
failed:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6078
	/* return error ack and blow away saved option results if any */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6079
	if (mp != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6080
		putnext(tcp->tcp_rq, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6081
	else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6082
		tcp_err_ack_prim(tcp, NULL, T_CONN_REQ,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6083
		    TSYSERR, ENOMEM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6084
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6085
	if (tcp->tcp_conn.tcp_opts_conn_req != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6086
		tcp_close_mpp(&tcp->tcp_conn.tcp_opts_conn_req);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6087
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
 * Handle connect to IPv6 destinations.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6092
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6093
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6094
tcp_connect_ipv6(tcp_t *tcp, mblk_t *mp, in6_addr_t *dstaddrp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6095
    in_port_t dstport, uint32_t flowinfo, uint_t srcid, uint32_t scope_id)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6096
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6097
	tcph_t	*tcph;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6098
	mblk_t	*mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6099
	ip6_rthdr_t *rth;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6100
	int32_t  oldstate;
646
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  6101
	uint16_t lport;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6102
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6103
	ASSERT(tcp->tcp_family == AF_INET6);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6104
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6105
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6106
	 * If we're here, it means that the destination address is a native
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6107
	 * IPv6 address.  Return an error if tcp_ipversion is not IPv6.  A
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6108
	 * reason why it might not be IPv6 is if the socket was bound to an
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6109
	 * IPv4-mapped IPv6 address.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6110
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6111
	if (tcp->tcp_ipversion != IPV6_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6112
		mp = mi_tpi_err_ack_alloc(mp, TBADADDR, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6113
		goto failed;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6114
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6115
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6116
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6117
	 * Interpret a zero destination to mean loopback.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6118
	 * Update the T_CONN_REQ (sin/sin6) since it is used to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6119
	 * generate the T_CONN_CON.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6120
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6121
	if (IN6_IS_ADDR_UNSPECIFIED(dstaddrp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6122
		*dstaddrp = ipv6_loopback;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6123
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6124
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6125
	/* Handle __sin6_src_id if socket not bound to an IP address */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6126
	if (srcid != 0 && IN6_IS_ADDR_UNSPECIFIED(&tcp->tcp_ip6h->ip6_src)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6127
		ip_srcid_find_id(srcid, &tcp->tcp_ip6h->ip6_src,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6128
		    tcp->tcp_connp->conn_zoneid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6129
		tcp->tcp_ip_src_v6 = tcp->tcp_ip6h->ip6_src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6130
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6131
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6132
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6133
	 * Take care of the scope_id now and add ip6i_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6134
	 * if ip6i_t is not already allocated through TCP
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6135
	 * sticky options. At this point tcp_ip6h does not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6136
	 * have dst info, thus use dstaddrp.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6137
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6138
	if (scope_id != 0 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6139
	    IN6_IS_ADDR_LINKSCOPE(dstaddrp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6140
		ip6_pkt_t *ipp = &tcp->tcp_sticky_ipp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6141
		ip6i_t  *ip6i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6142
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6143
		ipp->ipp_ifindex = scope_id;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6144
		ip6i = (ip6i_t *)tcp->tcp_iphc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6145
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6146
		if ((ipp->ipp_fields & IPPF_HAS_IP6I) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6147
		    ip6i != NULL && (ip6i->ip6i_nxt == IPPROTO_RAW)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6148
			/* Already allocated */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6149
			ip6i->ip6i_flags |= IP6I_IFINDEX;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6150
			ip6i->ip6i_ifindex = ipp->ipp_ifindex;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6151
			ipp->ipp_fields |= IPPF_SCOPE_ID;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6152
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6153
			int reterr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6154
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6155
			ipp->ipp_fields |= IPPF_SCOPE_ID;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6156
			if (ipp->ipp_fields & IPPF_HAS_IP6I)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6157
				ip2dbg(("tcp_connect_v6: SCOPE_ID set\n"));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6158
			reterr = tcp_build_hdrs(tcp->tcp_rq, tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6159
			if (reterr != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6160
				goto failed;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6161
			ip1dbg(("tcp_connect_ipv6: tcp_bld_hdrs returned\n"));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6162
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6163
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6164
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6165
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6166
	 * Don't let an endpoint connect to itself.  Note that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6167
	 * the test here does not catch the case where the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6168
	 * source IP addr was left unspecified by the user. In
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6169
	 * this case, the source addr is set in tcp_adapt_ire()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6170
	 * using the reply to the T_BIND message that we send
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6171
	 * down to IP here and the check is repeated in tcp_rput_other.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6172
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6173
	if (IN6_ARE_ADDR_EQUAL(dstaddrp, &tcp->tcp_ip6h->ip6_src) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6174
	    (dstport == tcp->tcp_lport)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6175
		mp = mi_tpi_err_ack_alloc(mp, TBADADDR, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6176
		goto failed;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6177
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6178
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6179
	tcp->tcp_ip6h->ip6_dst = *dstaddrp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6180
	tcp->tcp_remote_v6 = *dstaddrp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6181
	tcp->tcp_ip6h->ip6_vcf =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6182
	    (IPV6_DEFAULT_VERS_AND_FLOW & IPV6_VERS_AND_FLOW_MASK) |
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6183
	    (flowinfo & ~IPV6_VERS_AND_FLOW_MASK);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6184
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6185
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6186
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6187
	 * Massage a routing header (if present) putting the first hop
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6188
	 * in ip6_dst. Compute a starting value for the checksum which
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6189
	 * takes into account that the original ip6_dst should be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6190
	 * included in the checksum but that ip will include the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6191
	 * first hop in the source route in the tcp checksum.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6192
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6193
	rth = ip_find_rthdr_v6(tcp->tcp_ip6h, (uint8_t *)tcp->tcp_tcph);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6194
	if (rth != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6195
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6196
		tcp->tcp_sum = ip_massage_options_v6(tcp->tcp_ip6h, rth);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6197
		tcp->tcp_sum = ntohs((tcp->tcp_sum & 0xFFFF) +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6198
		    (tcp->tcp_sum >> 16));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6199
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6200
		tcp->tcp_sum = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6201
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6202
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6203
	tcph = tcp->tcp_tcph;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6204
	*(uint16_t *)tcph->th_fport = dstport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6205
	tcp->tcp_fport = dstport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6206
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6207
	oldstate = tcp->tcp_state;
646
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  6208
	/*
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  6209
	 * 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
  6210
	 * 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
  6211
	 * 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
  6212
	 */
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  6213
	if (oldstate == TCPS_IDLE) {
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  6214
		/*
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  6215
		 * We support a quick connect capability here, allowing
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  6216
		 * clients to transition directly from IDLE to SYN_SENT
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  6217
		 * 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
  6218
		 * in the bind hash and transition to BOUND state.
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  6219
		 */
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  6220
		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
  6221
		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
  6222
		    B_FALSE, B_FALSE);
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  6223
		if (lport == 0) {
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  6224
			mp = mi_tpi_err_ack_alloc(mp, TNOADDR, 0);
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  6225
			goto failed;
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  6226
		}
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  6227
	}
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6228
	tcp->tcp_state = TCPS_SYN_SENT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6229
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6230
	 * TODO: allow data with connect requests
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6231
	 * by unlinking M_DATA trailers here and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6232
	 * linking them in behind the T_OK_ACK mblk.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6233
	 * The tcp_rput() bind ack handler would then
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6234
	 * feed them to tcp_wput_data() rather than call
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6235
	 * tcp_timer().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6236
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6237
	mp = mi_tpi_ok_ack_alloc(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6238
	if (!mp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6239
		tcp->tcp_state = oldstate;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6240
		goto failed;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6241
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6242
	mp1 = tcp_ip_bind_mp(tcp, O_T_BIND_REQ, sizeof (ipa6_conn_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6243
	if (mp1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6244
		/* Hang onto the T_OK_ACK for later. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6245
		linkb(mp1, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6246
		mp1 = ip_bind_v6(tcp->tcp_wq, mp1, tcp->tcp_connp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6247
		    &tcp->tcp_sticky_ipp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6248
		BUMP_MIB(&tcp_mib, tcpActiveOpens);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6249
		tcp->tcp_active_open = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6250
		/* ip_bind_v6() may return ACK or ERROR */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6251
		if (mp1 != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6252
			tcp_rput_other(tcp, mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6253
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6254
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6255
	/* Error case */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6256
	tcp->tcp_state = oldstate;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6257
	mp = mi_tpi_err_ack_alloc(mp, TSYSERR, ENOMEM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6258
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6259
failed:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6260
	/* return error ack and blow away saved option results if any */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6261
	if (mp != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6262
		putnext(tcp->tcp_rq, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6263
	else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6264
		tcp_err_ack_prim(tcp, NULL, T_CONN_REQ,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6265
		    TSYSERR, ENOMEM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6266
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6267
	if (tcp->tcp_conn.tcp_opts_conn_req != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6268
		tcp_close_mpp(&tcp->tcp_conn.tcp_opts_conn_req);
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
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6272
 * We need a stream q for detached closing tcp connections
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6273
 * to use.  Our client hereby indicates that this q is the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6274
 * one to use.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6275
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6276
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6277
tcp_def_q_set(tcp_t *tcp, mblk_t *mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6278
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6279
	struct iocblk *iocp = (struct iocblk *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6280
	queue_t	*q = tcp->tcp_wq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6281
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6282
	mp->b_datap->db_type = M_IOCACK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6283
	iocp->ioc_count = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6284
	mutex_enter(&tcp_g_q_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6285
	if (tcp_g_q != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6286
		mutex_exit(&tcp_g_q_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6287
		iocp->ioc_error = EALREADY;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6288
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6289
		mblk_t *mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6290
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6291
		mp1 = tcp_ip_bind_mp(tcp, O_T_BIND_REQ, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6292
		if (mp1 == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6293
			mutex_exit(&tcp_g_q_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6294
			iocp->ioc_error = ENOMEM;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6295
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6296
			tcp_g_q = tcp->tcp_rq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6297
			mutex_exit(&tcp_g_q_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6298
			iocp->ioc_error = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6299
			iocp->ioc_rval = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6300
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6301
			 * We are passing tcp_sticky_ipp as NULL
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6302
			 * as it is not useful for tcp_default queue
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6303
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6304
			mp1 = ip_bind_v6(q, mp1, tcp->tcp_connp, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6305
			if (mp1 != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6306
				tcp_rput_other(tcp, mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6307
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6308
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6309
	qreply(q, mp);
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
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6313
 * Our client hereby directs us to reject the connection request
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6314
 * that tcp_conn_request() marked with 'seqnum'.  Rejection consists
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6315
 * of sending the appropriate RST, not an ICMP error.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6316
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6317
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6318
tcp_disconnect(tcp_t *tcp, mblk_t *mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6319
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6320
	tcp_t	*ltcp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6321
	t_scalar_t seqnum;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6322
	conn_t	*connp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6323
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6324
	ASSERT((uintptr_t)(mp->b_wptr - mp->b_rptr) <= (uintptr_t)INT_MAX);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6325
	if ((mp->b_wptr - mp->b_rptr) < sizeof (struct T_discon_req)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6326
		tcp_err_ack(tcp, mp, TPROTO, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6327
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6328
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6329
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6330
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6331
	 * Right now, upper modules pass down a T_DISCON_REQ to TCP,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6332
	 * when the stream is in BOUND state. Do not send a reset,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6333
	 * since the destination IP address is not valid, and it can
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6334
	 * be the initialized value of all zeros (broadcast address).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6335
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6336
	 * If TCP has sent down a bind request to IP and has not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6337
	 * received the reply, reject the request.  Otherwise, TCP
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6338
	 * will be confused.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6339
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6340
	if (tcp->tcp_state <= TCPS_BOUND || tcp->tcp_hard_binding) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6341
		if (tcp->tcp_debug) {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  6342
			(void) strlog(TCP_MOD_ID, 0, 1, SL_ERROR|SL_TRACE,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6343
			    "tcp_disconnect: bad state, %d", tcp->tcp_state);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6344
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6345
		tcp_err_ack(tcp, mp, TOUTSTATE, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6346
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6347
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6348
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6349
	seqnum = ((struct T_discon_req *)mp->b_rptr)->SEQ_number;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6350
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6351
	if (seqnum == -1 || tcp->tcp_conn_req_max == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6352
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6353
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6354
		 * According to TPI, for non-listeners, ignore seqnum
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6355
		 * and disconnect.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6356
		 * Following interpretation of -1 seqnum is historical
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6357
		 * and implied TPI ? (TPI only states that for T_CONN_IND,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6358
		 * a valid seqnum should not be -1).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6359
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6360
		 *	-1 means disconnect everything
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6361
		 *	regardless even on a listener.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6362
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6363
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6364
		int old_state = tcp->tcp_state;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6365
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6366
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6367
		 * The connection can't be on the tcp_time_wait_head list
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6368
		 * since it is not detached.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6369
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6370
		ASSERT(tcp->tcp_time_wait_next == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6371
		ASSERT(tcp->tcp_time_wait_prev == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6372
		ASSERT(tcp->tcp_time_wait_expire == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6373
		ltcp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6374
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6375
		 * If it used to be a listener, check to make sure no one else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6376
		 * has taken the port before switching back to LISTEN state.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6377
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6378
		if (tcp->tcp_ipversion == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6379
			connp = ipcl_lookup_listener_v4(tcp->tcp_lport,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6380
			    tcp->tcp_ipha->ipha_src,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6381
			    tcp->tcp_connp->conn_zoneid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6382
			if (connp != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6383
				ltcp = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6384
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6385
			/* Allow tcp_bound_if listeners? */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6386
			connp = ipcl_lookup_listener_v6(tcp->tcp_lport,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6387
			    &tcp->tcp_ip6h->ip6_src, 0,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6388
			    tcp->tcp_connp->conn_zoneid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6389
			if (connp != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6390
				ltcp = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6391
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6392
		if (tcp->tcp_conn_req_max && ltcp == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6393
			tcp->tcp_state = TCPS_LISTEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6394
		} else if (old_state > TCPS_BOUND) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6395
			tcp->tcp_conn_req_max = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6396
			tcp->tcp_state = TCPS_BOUND;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6397
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6398
		if (ltcp != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6399
			CONN_DEC_REF(ltcp->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6400
		if (old_state == TCPS_SYN_SENT || old_state == TCPS_SYN_RCVD) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6401
			BUMP_MIB(&tcp_mib, tcpAttemptFails);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6402
		} else if (old_state == TCPS_ESTABLISHED ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6403
		    old_state == TCPS_CLOSE_WAIT) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6404
			BUMP_MIB(&tcp_mib, tcpEstabResets);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6405
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6406
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6407
		if (tcp->tcp_fused)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6408
			tcp_unfuse(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6409
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6410
		mutex_enter(&tcp->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6411
		if ((tcp->tcp_conn_req_cnt_q0 != 0) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6412
		    (tcp->tcp_conn_req_cnt_q != 0)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6413
			tcp_eager_cleanup(tcp, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6414
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6415
		mutex_exit(&tcp->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6416
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6417
		tcp_xmit_ctl("tcp_disconnect", tcp, tcp->tcp_snxt,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6418
		    tcp->tcp_rnxt, TH_RST | TH_ACK);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6419
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6420
		tcp_reinit(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6421
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6422
		if (old_state >= TCPS_ESTABLISHED) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6423
			/* Send M_FLUSH according to TPI */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6424
			(void) putnextctl1(tcp->tcp_rq, M_FLUSH, FLUSHRW);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6425
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6426
		mp = mi_tpi_ok_ack_alloc(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6427
		if (mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6428
			putnext(tcp->tcp_rq, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6429
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6430
	} else if (!tcp_eager_blowoff(tcp, seqnum)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6431
		tcp_err_ack(tcp, mp, TBADSEQ, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6432
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6433
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6434
	if (tcp->tcp_state >= TCPS_ESTABLISHED) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6435
		/* Send M_FLUSH according to TPI */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6436
		(void) putnextctl1(tcp->tcp_rq, M_FLUSH, FLUSHRW);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6437
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6438
	mp = mi_tpi_ok_ack_alloc(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6439
	if (mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6440
		putnext(tcp->tcp_rq, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6441
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6442
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6443
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6444
 * Diagnostic routine used to return a string associated with the tcp state.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6445
 * Note that if the caller does not supply a buffer, it will use an internal
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6446
 * static string.  This means that if multiple threads call this function at
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6447
 * the same time, output can be corrupted...  Note also that this function
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6448
 * does not check the size of the supplied buffer.  The caller has to make
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6449
 * sure that it is big enough.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6450
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6451
static char *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6452
tcp_display(tcp_t *tcp, char *sup_buf, char format)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6453
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6454
	char		buf1[30];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6455
	static char	priv_buf[INET6_ADDRSTRLEN * 2 + 80];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6456
	char		*buf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6457
	char		*cp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6458
	in6_addr_t	local, remote;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6459
	char		local_addrbuf[INET6_ADDRSTRLEN];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6460
	char		remote_addrbuf[INET6_ADDRSTRLEN];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6461
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6462
	if (sup_buf != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6463
		buf = sup_buf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6464
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6465
		buf = priv_buf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6466
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6467
	if (tcp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6468
		return ("NULL_TCP");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6469
	switch (tcp->tcp_state) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6470
	case TCPS_CLOSED:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6471
		cp = "TCP_CLOSED";
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6472
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6473
	case TCPS_IDLE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6474
		cp = "TCP_IDLE";
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6475
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6476
	case TCPS_BOUND:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6477
		cp = "TCP_BOUND";
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6478
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6479
	case TCPS_LISTEN:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6480
		cp = "TCP_LISTEN";
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6481
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6482
	case TCPS_SYN_SENT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6483
		cp = "TCP_SYN_SENT";
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6484
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6485
	case TCPS_SYN_RCVD:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6486
		cp = "TCP_SYN_RCVD";
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6487
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6488
	case TCPS_ESTABLISHED:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6489
		cp = "TCP_ESTABLISHED";
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6490
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6491
	case TCPS_CLOSE_WAIT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6492
		cp = "TCP_CLOSE_WAIT";
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6493
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6494
	case TCPS_FIN_WAIT_1:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6495
		cp = "TCP_FIN_WAIT_1";
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6496
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6497
	case TCPS_CLOSING:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6498
		cp = "TCP_CLOSING";
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6499
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6500
	case TCPS_LAST_ACK:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6501
		cp = "TCP_LAST_ACK";
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6502
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6503
	case TCPS_FIN_WAIT_2:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6504
		cp = "TCP_FIN_WAIT_2";
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6505
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6506
	case TCPS_TIME_WAIT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6507
		cp = "TCP_TIME_WAIT";
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6508
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6509
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6510
		(void) mi_sprintf(buf1, "TCPUnkState(%d)", tcp->tcp_state);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6511
		cp = buf1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6512
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6513
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6514
	switch (format) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6515
	case DISP_ADDR_AND_PORT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6516
		if (tcp->tcp_ipversion == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6517
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6518
			 * Note that we use the remote address in the tcp_b
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6519
			 * structure.  This means that it will print out
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6520
			 * the real destination address, not the next hop's
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6521
			 * address if source routing is used.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6522
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6523
			IN6_IPADDR_TO_V4MAPPED(tcp->tcp_ip_src, &local);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6524
			IN6_IPADDR_TO_V4MAPPED(tcp->tcp_remote, &remote);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6525
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6526
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6527
			local = tcp->tcp_ip_src_v6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6528
			remote = tcp->tcp_remote_v6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6529
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6530
		(void) inet_ntop(AF_INET6, &local, local_addrbuf,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6531
		    sizeof (local_addrbuf));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6532
		(void) inet_ntop(AF_INET6, &remote, remote_addrbuf,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6533
		    sizeof (remote_addrbuf));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6534
		(void) mi_sprintf(buf, "[%s.%u, %s.%u] %s",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6535
		    local_addrbuf, ntohs(tcp->tcp_lport), remote_addrbuf,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6536
		    ntohs(tcp->tcp_fport), cp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6537
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6538
	case DISP_PORT_ONLY:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6539
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6540
		(void) mi_sprintf(buf, "[%u, %u] %s",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6541
		    ntohs(tcp->tcp_lport), ntohs(tcp->tcp_fport), cp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6542
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6543
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6544
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6545
	return (buf);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6546
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6547
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6548
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6549
 * Called via squeue to get on to eager's perimeter to send a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6550
 * TH_RST. The listener wants the eager to disappear either
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6551
 * by means of tcp_eager_blowoff() or tcp_eager_cleanup()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6552
 * being called.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6553
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6554
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6555
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6556
tcp_eager_kill(void *arg, mblk_t *mp, void *arg2)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6557
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6558
	conn_t	*econnp = (conn_t *)arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6559
	tcp_t	*eager = econnp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6560
	tcp_t	*listener = eager->tcp_listener;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6561
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6562
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6563
	 * We could be called because listener is closing. Since
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6564
	 * the eager is using listener's queue's, its not safe.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6565
	 * Better use the default queue just to send the TH_RST
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6566
	 * out.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6567
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6568
	eager->tcp_rq = tcp_g_q;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6569
	eager->tcp_wq = WR(tcp_g_q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6570
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6571
	if (eager->tcp_state > TCPS_LISTEN) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6572
		tcp_xmit_ctl("tcp_eager_kill, can't wait",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6573
		    eager, eager->tcp_snxt, 0, TH_RST);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6574
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6575
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6576
	/* We are here because listener wants this eager gone */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6577
	if (listener != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6578
		mutex_enter(&listener->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6579
		tcp_eager_unlink(eager);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6580
		if (eager->tcp_conn.tcp_eager_conn_ind == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6581
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6582
			 * The eager has sent a conn_ind up to the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6583
			 * listener but listener decides to close
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6584
			 * instead. We need to drop the extra ref
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6585
			 * placed on eager in tcp_rput_data() before
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6586
			 * sending the conn_ind to listener.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6587
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6588
			CONN_DEC_REF(econnp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6589
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6590
		mutex_exit(&listener->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6591
		CONN_DEC_REF(listener->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6592
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6593
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6594
	if (eager->tcp_state > TCPS_BOUND)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6595
		tcp_close_detached(eager);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6596
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6597
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6598
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6599
 * Reset any eager connection hanging off this listener marked
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6600
 * with 'seqnum' and then reclaim it's resources.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6601
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6602
static boolean_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6603
tcp_eager_blowoff(tcp_t	*listener, t_scalar_t seqnum)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6604
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6605
	tcp_t	*eager;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6606
	mblk_t 	*mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6607
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6608
	TCP_STAT(tcp_eager_blowoff_calls);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6609
	eager = listener;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6610
	mutex_enter(&listener->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6611
	do {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6612
		eager = eager->tcp_eager_next_q;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6613
		if (eager == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6614
			mutex_exit(&listener->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6615
			return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6616
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6617
	} while (eager->tcp_conn_req_seqnum != seqnum);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6618
	CONN_INC_REF(eager->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6619
	mutex_exit(&listener->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6620
	mp = &eager->tcp_closemp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6621
	squeue_fill(eager->tcp_connp->conn_sqp, mp, tcp_eager_kill,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6622
	    eager->tcp_connp, SQTAG_TCP_EAGER_BLOWOFF);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6623
	return (B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6624
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6625
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6626
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6627
 * Reset any eager connection hanging off this listener
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6628
 * and then reclaim it's resources.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6629
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6630
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6631
tcp_eager_cleanup(tcp_t *listener, boolean_t q0_only)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6632
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6633
	tcp_t	*eager;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6634
	mblk_t	*mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6635
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6636
	ASSERT(MUTEX_HELD(&listener->tcp_eager_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6637
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6638
	if (!q0_only) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6639
		/* First cleanup q */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6640
		TCP_STAT(tcp_eager_blowoff_q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6641
		eager = listener->tcp_eager_next_q;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6642
		while (eager != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6643
			CONN_INC_REF(eager->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6644
			mp = &eager->tcp_closemp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6645
			squeue_fill(eager->tcp_connp->conn_sqp, mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6646
			    tcp_eager_kill, eager->tcp_connp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6647
			    SQTAG_TCP_EAGER_CLEANUP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6648
			eager = eager->tcp_eager_next_q;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6649
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6650
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6651
	/* Then cleanup q0 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6652
	TCP_STAT(tcp_eager_blowoff_q0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6653
	eager = listener->tcp_eager_next_q0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6654
	while (eager != listener) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6655
		CONN_INC_REF(eager->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6656
		mp = &eager->tcp_closemp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6657
		squeue_fill(eager->tcp_connp->conn_sqp, mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6658
		    tcp_eager_kill, eager->tcp_connp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6659
		    SQTAG_TCP_EAGER_CLEANUP_Q0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6660
		eager = eager->tcp_eager_next_q0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6661
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6662
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6663
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6664
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6665
 * If we are an eager connection hanging off a listener that hasn't
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6666
 * formally accepted the connection yet, get off his list and blow off
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6667
 * any data that we have accumulated.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6668
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6669
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6670
tcp_eager_unlink(tcp_t *tcp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6671
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6672
	tcp_t	*listener = tcp->tcp_listener;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6673
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6674
	ASSERT(MUTEX_HELD(&listener->tcp_eager_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6675
	ASSERT(listener != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6676
	if (tcp->tcp_eager_next_q0 != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6677
		ASSERT(tcp->tcp_eager_prev_q0 != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6678
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6679
		/* Remove the eager tcp from q0 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6680
		tcp->tcp_eager_next_q0->tcp_eager_prev_q0 =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6681
		    tcp->tcp_eager_prev_q0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6682
		tcp->tcp_eager_prev_q0->tcp_eager_next_q0 =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6683
		    tcp->tcp_eager_next_q0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6684
		ASSERT(listener->tcp_conn_req_cnt_q0 > 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6685
		listener->tcp_conn_req_cnt_q0--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6686
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6687
		tcp->tcp_eager_next_q0 = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6688
		tcp->tcp_eager_prev_q0 = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6689
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6690
		if (tcp->tcp_syn_rcvd_timeout != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6691
			/* we have timed out before */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6692
			ASSERT(listener->tcp_syn_rcvd_timeout > 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6693
			listener->tcp_syn_rcvd_timeout--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6694
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6695
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6696
		tcp_t   **tcpp = &listener->tcp_eager_next_q;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6697
		tcp_t	*prev = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6698
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6699
		for (; tcpp[0]; tcpp = &tcpp[0]->tcp_eager_next_q) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6700
			if (tcpp[0] == tcp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6701
				if (listener->tcp_eager_last_q == tcp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6702
					/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6703
					 * If we are unlinking the last
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6704
					 * element on the list, adjust
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6705
					 * tail pointer. Set tail pointer
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6706
					 * to nil when list is empty.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6707
					 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6708
					ASSERT(tcp->tcp_eager_next_q == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6709
					if (listener->tcp_eager_last_q ==
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6710
					    listener->tcp_eager_next_q) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6711
						listener->tcp_eager_last_q =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6712
						NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6713
					} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6714
						/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6715
						 * We won't get here if there
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6716
						 * is only one eager in the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6717
						 * list.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6718
						 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6719
						ASSERT(prev != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6720
						listener->tcp_eager_last_q =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6721
						    prev;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6722
					}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6723
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6724
				tcpp[0] = tcp->tcp_eager_next_q;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6725
				tcp->tcp_eager_next_q = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6726
				tcp->tcp_eager_last_q = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6727
				ASSERT(listener->tcp_conn_req_cnt_q > 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6728
				listener->tcp_conn_req_cnt_q--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6729
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6730
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6731
			prev = tcpp[0];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6732
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6733
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6734
	tcp->tcp_listener = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6735
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6736
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6737
/* Shorthand to generate and send TPI error acks to our client */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6738
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6739
tcp_err_ack(tcp_t *tcp, mblk_t *mp, int t_error, int sys_error)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6740
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6741
	if ((mp = mi_tpi_err_ack_alloc(mp, t_error, sys_error)) != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6742
		putnext(tcp->tcp_rq, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6743
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6744
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6745
/* Shorthand to generate and send TPI error acks to our client */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6746
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6747
tcp_err_ack_prim(tcp_t *tcp, mblk_t *mp, int primitive,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6748
    int t_error, int sys_error)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6749
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6750
	struct T_error_ack	*teackp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6751
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6752
	if ((mp = tpi_ack_alloc(mp, sizeof (struct T_error_ack),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6753
	    M_PCPROTO, T_ERROR_ACK)) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6754
		teackp = (struct T_error_ack *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6755
		teackp->ERROR_prim = primitive;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6756
		teackp->TLI_error = t_error;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6757
		teackp->UNIX_error = sys_error;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6758
		putnext(tcp->tcp_rq, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6759
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6760
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6761
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6762
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6763
 * Note: No locks are held when inspecting tcp_g_*epriv_ports
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6764
 * but instead the code relies on:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6765
 * - the fact that the address of the array and its size never changes
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6766
 * - the atomic assignment of the elements of the array
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6767
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6768
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6769
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6770
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
  6771
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6772
	int i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6773
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6774
	for (i = 0; i < tcp_g_num_epriv_ports; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6775
		if (tcp_g_epriv_ports[i] != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6776
			(void) mi_mpprintf(mp, "%d ", tcp_g_epriv_ports[i]);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6777
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6778
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6779
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6780
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6781
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6782
 * Hold a lock while changing tcp_g_epriv_ports to prevent multiple
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6783
 * threads from changing it at the same time.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6784
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6785
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6786
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6787
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
  6788
    cred_t *cr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6789
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6790
	long	new_value;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6791
	int	i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6792
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6793
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6794
	 * Fail the request if the new value does not lie within the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6795
	 * port number limits.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6796
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6797
	if (ddi_strtol(value, NULL, 10, &new_value) != 0 ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6798
	    new_value <= 0 || new_value >= 65536) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6799
		return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6800
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6801
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6802
	mutex_enter(&tcp_epriv_port_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6803
	/* Check if the value is already in the list */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6804
	for (i = 0; i < tcp_g_num_epriv_ports; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6805
		if (new_value == tcp_g_epriv_ports[i]) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6806
			mutex_exit(&tcp_epriv_port_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6807
			return (EEXIST);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6808
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6809
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6810
	/* Find an empty slot */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6811
	for (i = 0; i < tcp_g_num_epriv_ports; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6812
		if (tcp_g_epriv_ports[i] == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6813
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6814
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6815
	if (i == tcp_g_num_epriv_ports) {
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 (EOVERFLOW);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6818
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6819
	/* Set the new value */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6820
	tcp_g_epriv_ports[i] = (uint16_t)new_value;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6821
	mutex_exit(&tcp_epriv_port_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6822
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6823
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6824
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6825
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6826
 * Hold a lock while changing tcp_g_epriv_ports to prevent multiple
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6827
 * threads from changing it at the same time.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6828
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6829
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6830
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6831
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
  6832
    cred_t *cr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6833
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6834
	long	new_value;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6835
	int	i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6836
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6837
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6838
	 * Fail the request if the new value does not lie within the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6839
	 * port number limits.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6840
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6841
	if (ddi_strtol(value, NULL, 10, &new_value) != 0 || new_value <= 0 ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6842
	    new_value >= 65536) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6843
		return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6844
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6845
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6846
	mutex_enter(&tcp_epriv_port_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6847
	/* Check that the value is already in the list */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6848
	for (i = 0; i < tcp_g_num_epriv_ports; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6849
		if (tcp_g_epriv_ports[i] == new_value)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6850
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6851
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6852
	if (i == tcp_g_num_epriv_ports) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6853
		mutex_exit(&tcp_epriv_port_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6854
		return (ESRCH);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6855
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6856
	/* Clear the value */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6857
	tcp_g_epriv_ports[i] = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6858
	mutex_exit(&tcp_epriv_port_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6859
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6860
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6861
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6862
/* Return the TPI/TLI equivalent of our current tcp_state */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6863
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6864
tcp_tpistate(tcp_t *tcp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6865
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6866
	switch (tcp->tcp_state) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6867
	case TCPS_IDLE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6868
		return (TS_UNBND);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6869
	case TCPS_LISTEN:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6870
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6871
		 * Return whether there are outstanding T_CONN_IND waiting
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6872
		 * for the matching T_CONN_RES. Therefore don't count q0.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6873
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6874
		if (tcp->tcp_conn_req_cnt_q > 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6875
			return (TS_WRES_CIND);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6876
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6877
			return (TS_IDLE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6878
	case TCPS_BOUND:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6879
		return (TS_IDLE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6880
	case TCPS_SYN_SENT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6881
		return (TS_WCON_CREQ);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6882
	case TCPS_SYN_RCVD:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6883
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6884
		 * Note: assumption: this has to the active open SYN_RCVD.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6885
		 * The passive instance is detached in SYN_RCVD stage of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6886
		 * incoming connection processing so we cannot get request
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6887
		 * for T_info_ack on it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6888
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6889
		return (TS_WACK_CRES);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6890
	case TCPS_ESTABLISHED:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6891
		return (TS_DATA_XFER);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6892
	case TCPS_CLOSE_WAIT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6893
		return (TS_WREQ_ORDREL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6894
	case TCPS_FIN_WAIT_1:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6895
		return (TS_WIND_ORDREL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6896
	case TCPS_FIN_WAIT_2:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6897
		return (TS_WIND_ORDREL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6898
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6899
	case TCPS_CLOSING:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6900
	case TCPS_LAST_ACK:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6901
	case TCPS_TIME_WAIT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6902
	case TCPS_CLOSED:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6903
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6904
		 * Following TS_WACK_DREQ7 is a rendition of "not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6905
		 * yet TS_IDLE" TPI state. There is no best match to any
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6906
		 * TPI state for TCPS_{CLOSING, LAST_ACK, TIME_WAIT} but we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6907
		 * choose a value chosen that will map to TLI/XTI level
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6908
		 * state of TSTATECHNG (state is process of changing) which
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6909
		 * captures what this dummy state represents.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6910
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6911
		return (TS_WACK_DREQ7);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6912
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6913
		cmn_err(CE_WARN, "tcp_tpistate: strange state (%d) %s",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6914
		    tcp->tcp_state, tcp_display(tcp, NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6915
		    DISP_PORT_ONLY));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6916
		return (TS_UNBND);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6917
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6918
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6919
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6920
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6921
tcp_copy_info(struct T_info_ack *tia, tcp_t *tcp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6922
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6923
	if (tcp->tcp_family == AF_INET6)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6924
		*tia = tcp_g_t_info_ack_v6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6925
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6926
		*tia = tcp_g_t_info_ack;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6927
	tia->CURRENT_state = tcp_tpistate(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6928
	tia->OPT_size = tcp_max_optsize;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6929
	if (tcp->tcp_mss == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6930
		/* Not yet set - tcp_open does not set mss */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6931
		if (tcp->tcp_ipversion == IPV4_VERSION)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6932
			tia->TIDU_size = tcp_mss_def_ipv4;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6933
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6934
			tia->TIDU_size = tcp_mss_def_ipv6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6935
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6936
		tia->TIDU_size = tcp->tcp_mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6937
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6938
	/* TODO: Default ETSDU is 1.  Is that correct for tcp? */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6939
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6940
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6941
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6942
 * This routine responds to T_CAPABILITY_REQ messages.  It is called by
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6943
 * tcp_wput.  Much of the T_CAPABILITY_ACK information is copied from
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6944
 * tcp_g_t_info_ack.  The current state of the stream is copied from
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6945
 * tcp_state.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6946
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6947
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6948
tcp_capability_req(tcp_t *tcp, mblk_t *mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6949
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6950
	t_uscalar_t		cap_bits1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6951
	struct T_capability_ack	*tcap;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6952
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6953
	if (MBLKL(mp) < sizeof (struct T_capability_req)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6954
		freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6955
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6956
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6957
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6958
	cap_bits1 = ((struct T_capability_req *)mp->b_rptr)->CAP_bits1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6959
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6960
	mp = tpi_ack_alloc(mp, sizeof (struct T_capability_ack),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6961
	    mp->b_datap->db_type, T_CAPABILITY_ACK);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6962
	if (mp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6963
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6964
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6965
	tcap = (struct T_capability_ack *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6966
	tcap->CAP_bits1 = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6967
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6968
	if (cap_bits1 & TC1_INFO) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6969
		tcp_copy_info(&tcap->INFO_ack, tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6970
		tcap->CAP_bits1 |= TC1_INFO;
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 (cap_bits1 & TC1_ACCEPTOR_ID) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6974
		tcap->ACCEPTOR_id = tcp->tcp_acceptor_id;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6975
		tcap->CAP_bits1 |= TC1_ACCEPTOR_ID;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6976
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6977
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6978
	putnext(tcp->tcp_rq, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6979
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6980
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6981
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6982
 * This routine responds to T_INFO_REQ messages.  It is called by tcp_wput.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6983
 * Most of the T_INFO_ACK information is copied from tcp_g_t_info_ack.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6984
 * The current state of the stream is copied from tcp_state.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6985
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6986
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6987
tcp_info_req(tcp_t *tcp, mblk_t *mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6988
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6989
	mp = tpi_ack_alloc(mp, sizeof (struct T_info_ack), M_PCPROTO,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6990
	    T_INFO_ACK);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6991
	if (!mp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6992
		tcp_err_ack(tcp, mp, TSYSERR, ENOMEM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6993
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6994
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6995
	tcp_copy_info((struct T_info_ack *)mp->b_rptr, tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6996
	putnext(tcp->tcp_rq, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6997
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6998
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6999
/* Respond to the TPI addr request */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7000
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7001
tcp_addr_req(tcp_t *tcp, mblk_t *mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7002
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7003
	sin_t	*sin;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7004
	mblk_t	*ackmp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7005
	struct T_addr_ack *taa;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7006
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7007
	/* Make it large enough for worst case */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7008
	ackmp = reallocb(mp, sizeof (struct T_addr_ack) +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7009
	    2 * sizeof (sin6_t), 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7010
	if (ackmp == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7011
		tcp_err_ack(tcp, mp, TSYSERR, ENOMEM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7012
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7013
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7014
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7015
	if (tcp->tcp_ipversion == IPV6_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7016
		tcp_addr_req_ipv6(tcp, ackmp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7017
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7018
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7019
	taa = (struct T_addr_ack *)ackmp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7020
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7021
	bzero(taa, sizeof (struct T_addr_ack));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7022
	ackmp->b_wptr = (uchar_t *)&taa[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7023
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7024
	taa->PRIM_type = T_ADDR_ACK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7025
	ackmp->b_datap->db_type = M_PCPROTO;
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
	 * Note: Following code assumes 32 bit alignment of basic
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7029
	 * data structures like sin_t and struct T_addr_ack.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7030
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7031
	if (tcp->tcp_state >= TCPS_BOUND) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7032
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7033
		 * Fill in local address
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7034
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7035
		taa->LOCADDR_length = sizeof (sin_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7036
		taa->LOCADDR_offset = sizeof (*taa);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7037
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7038
		sin = (sin_t *)&taa[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7039
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7040
		/* Fill zeroes and then intialize non-zero fields */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7041
		*sin = sin_null;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7042
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7043
		sin->sin_family = AF_INET;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7044
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7045
		sin->sin_addr.s_addr = tcp->tcp_ipha->ipha_src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7046
		sin->sin_port = *(uint16_t *)tcp->tcp_tcph->th_lport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7047
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7048
		ackmp->b_wptr = (uchar_t *)&sin[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7049
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7050
		if (tcp->tcp_state >= TCPS_SYN_RCVD) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7051
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7052
			 * Fill in Remote address
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7053
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7054
			taa->REMADDR_length = sizeof (sin_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7055
			taa->REMADDR_offset = ROUNDUP32(taa->LOCADDR_offset +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7056
						taa->LOCADDR_length);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7057
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7058
			sin = (sin_t *)(ackmp->b_rptr + taa->REMADDR_offset);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7059
			*sin = sin_null;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7060
			sin->sin_family = AF_INET;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7061
			sin->sin_addr.s_addr = tcp->tcp_remote;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7062
			sin->sin_port = tcp->tcp_fport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7063
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7064
			ackmp->b_wptr = (uchar_t *)&sin[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7065
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7066
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7067
	putnext(tcp->tcp_rq, ackmp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7068
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7069
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7070
/* Assumes that tcp_addr_req gets enough space and alignment */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7071
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7072
tcp_addr_req_ipv6(tcp_t *tcp, mblk_t *ackmp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7073
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7074
	sin6_t	*sin6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7075
	struct T_addr_ack *taa;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7076
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7077
	ASSERT(tcp->tcp_ipversion == IPV6_VERSION);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7078
	ASSERT(OK_32PTR(ackmp->b_rptr));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7079
	ASSERT(ackmp->b_wptr - ackmp->b_rptr >= sizeof (struct T_addr_ack) +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7080
	    2 * sizeof (sin6_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7081
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7082
	taa = (struct T_addr_ack *)ackmp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7083
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7084
	bzero(taa, sizeof (struct T_addr_ack));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7085
	ackmp->b_wptr = (uchar_t *)&taa[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7086
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7087
	taa->PRIM_type = T_ADDR_ACK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7088
	ackmp->b_datap->db_type = M_PCPROTO;
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
	 * Note: Following code assumes 32 bit alignment of basic
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7092
	 * data structures like sin6_t and struct T_addr_ack.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7093
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7094
	if (tcp->tcp_state >= TCPS_BOUND) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7095
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7096
		 * Fill in local address
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7097
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7098
		taa->LOCADDR_length = sizeof (sin6_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7099
		taa->LOCADDR_offset = sizeof (*taa);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7100
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7101
		sin6 = (sin6_t *)&taa[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7102
		*sin6 = sin6_null;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7103
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7104
		sin6->sin6_family = AF_INET6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7105
		sin6->sin6_addr = tcp->tcp_ip6h->ip6_src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7106
		sin6->sin6_port = tcp->tcp_lport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7107
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7108
		ackmp->b_wptr = (uchar_t *)&sin6[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7109
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7110
		if (tcp->tcp_state >= TCPS_SYN_RCVD) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7111
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7112
			 * Fill in Remote address
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7113
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7114
			taa->REMADDR_length = sizeof (sin6_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7115
			taa->REMADDR_offset = ROUNDUP32(taa->LOCADDR_offset +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7116
						taa->LOCADDR_length);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7117
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7118
			sin6 = (sin6_t *)(ackmp->b_rptr + taa->REMADDR_offset);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7119
			*sin6 = sin6_null;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7120
			sin6->sin6_family = AF_INET6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7121
			sin6->sin6_flowinfo =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7122
			    tcp->tcp_ip6h->ip6_vcf &
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7123
			    ~IPV6_VERS_AND_FLOW_MASK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7124
			sin6->sin6_addr = tcp->tcp_remote_v6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7125
			sin6->sin6_port = tcp->tcp_fport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7126
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7127
			ackmp->b_wptr = (uchar_t *)&sin6[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7128
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7129
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7130
	putnext(tcp->tcp_rq, ackmp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7131
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7132
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7133
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7134
 * Handle reinitialization of a tcp structure.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7135
 * Maintain "binding state" resetting the state to BOUND, LISTEN, or IDLE.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7136
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7137
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7138
tcp_reinit(tcp_t *tcp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7139
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7140
	mblk_t	*mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7141
	int 	err;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7142
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7143
	TCP_STAT(tcp_reinit_calls);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7144
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7145
	/* tcp_reinit should never be called for detached tcp_t's */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7146
	ASSERT(tcp->tcp_listener == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7147
	ASSERT((tcp->tcp_family == AF_INET &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7148
	    tcp->tcp_ipversion == IPV4_VERSION) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7149
	    (tcp->tcp_family == AF_INET6 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7150
	    (tcp->tcp_ipversion == IPV4_VERSION ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7151
	    tcp->tcp_ipversion == IPV6_VERSION)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7152
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7153
	/* Cancel outstanding timers */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7154
	tcp_timers_stop(tcp);
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
	 * Reset everything in the state vector, after updating global
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7158
	 * MIB data from instance counters.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7159
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7160
	UPDATE_MIB(&tcp_mib, tcpInSegs, tcp->tcp_ibsegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7161
	tcp->tcp_ibsegs = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7162
	UPDATE_MIB(&tcp_mib, tcpOutSegs, tcp->tcp_obsegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7163
	tcp->tcp_obsegs = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7164
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7165
	tcp_close_mpp(&tcp->tcp_xmit_head);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7166
	if (tcp->tcp_snd_zcopy_aware)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7167
		tcp_zcopy_notify(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7168
	tcp->tcp_xmit_last = tcp->tcp_xmit_tail = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7169
	tcp->tcp_unsent = tcp->tcp_xmit_tail_unsent = 0;
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  7170
	if (tcp->tcp_flow_stopped &&
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  7171
	    TCP_UNSENT_BYTES(tcp) <= tcp->tcp_xmit_lowater) {
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  7172
		tcp_clrqfull(tcp);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  7173
	}
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7174
	tcp_close_mpp(&tcp->tcp_reass_head);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7175
	tcp->tcp_reass_tail = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7176
	if (tcp->tcp_rcv_list != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7177
		/* Free b_next chain */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7178
		tcp_close_mpp(&tcp->tcp_rcv_list);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7179
		tcp->tcp_rcv_last_head = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7180
		tcp->tcp_rcv_last_tail = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7181
		tcp->tcp_rcv_cnt = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7182
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7183
	tcp->tcp_rcv_last_tail = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7184
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7185
	if ((mp = tcp->tcp_urp_mp) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7186
		freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7187
		tcp->tcp_urp_mp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7188
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7189
	if ((mp = tcp->tcp_urp_mark_mp) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7190
		freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7191
		tcp->tcp_urp_mark_mp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7192
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7193
	if (tcp->tcp_fused_sigurg_mp != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7194
		freeb(tcp->tcp_fused_sigurg_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7195
		tcp->tcp_fused_sigurg_mp = NULL;
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
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7199
	 * Following is a union with two members which are
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7200
	 * identical types and size so the following cleanup
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7201
	 * is enough.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7202
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7203
	tcp_close_mpp(&tcp->tcp_conn.tcp_eager_conn_ind);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7204
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7205
	CL_INET_DISCONNECT(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7206
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7207
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7208
	 * The connection can't be on the tcp_time_wait_head list
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7209
	 * since it is not detached.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7210
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7211
	ASSERT(tcp->tcp_time_wait_next == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7212
	ASSERT(tcp->tcp_time_wait_prev == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7213
	ASSERT(tcp->tcp_time_wait_expire == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7214
898
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
  7215
	if (tcp->tcp_kssl_pending) {
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
  7216
		tcp->tcp_kssl_pending = B_FALSE;
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
  7217
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
  7218
		/* Don't reset if the initialized by bind. */
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
  7219
		if (tcp->tcp_kssl_ent != NULL) {
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
  7220
			kssl_release_ent(tcp->tcp_kssl_ent, NULL,
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
  7221
			    KSSL_NO_PROXY);
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
  7222
		}
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
  7223
	}
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
  7224
	if (tcp->tcp_kssl_ctx != NULL) {
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
  7225
		kssl_release_ctx(tcp->tcp_kssl_ctx);
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
  7226
		tcp->tcp_kssl_ctx = NULL;
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
  7227
	}
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
  7228
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7229
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7230
	 * Reset/preserve other values
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7231
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7232
	tcp_reinit_values(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7233
	ipcl_hash_remove(tcp->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7234
	conn_delete_ire(tcp->tcp_connp, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7235
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7236
	if (tcp->tcp_conn_req_max != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7237
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7238
		 * This is the case when a TLI program uses the same
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7239
		 * transport end point to accept a connection.  This
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7240
		 * makes the TCP both a listener and acceptor.  When
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7241
		 * this connection is closed, we need to set the state
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7242
		 * back to TCPS_LISTEN.  Make sure that the eager list
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7243
		 * is reinitialized.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7244
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7245
		 * Note that this stream is still bound to the four
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7246
		 * tuples of the previous connection in IP.  If a new
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7247
		 * SYN with different foreign address comes in, IP will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7248
		 * not find it and will send it to the global queue.  In
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7249
		 * the global queue, TCP will do a tcp_lookup_listener()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7250
		 * to find this stream.  This works because this stream
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7251
		 * is only removed from connected hash.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7252
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7253
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7254
		tcp->tcp_state = TCPS_LISTEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7255
		tcp->tcp_eager_next_q0 = tcp->tcp_eager_prev_q0 = tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7256
		tcp->tcp_connp->conn_recv = tcp_conn_request;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7257
		if (tcp->tcp_family == AF_INET6) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7258
			ASSERT(tcp->tcp_connp->conn_af_isv6);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7259
			(void) ipcl_bind_insert_v6(tcp->tcp_connp, IPPROTO_TCP,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7260
			    &tcp->tcp_ip6h->ip6_src, tcp->tcp_lport);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7261
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7262
			ASSERT(!tcp->tcp_connp->conn_af_isv6);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7263
			(void) ipcl_bind_insert(tcp->tcp_connp, IPPROTO_TCP,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7264
			    tcp->tcp_ipha->ipha_src, tcp->tcp_lport);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7265
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7266
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7267
		tcp->tcp_state = TCPS_BOUND;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7268
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7269
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7270
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7271
	 * Initialize to default values
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7272
	 * Can't fail since enough header template space already allocated
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7273
	 * at open().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7274
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7275
	err = tcp_init_values(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7276
	ASSERT(err == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7277
	/* Restore state in tcp_tcph */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7278
	bcopy(&tcp->tcp_lport, tcp->tcp_tcph->th_lport, TCP_PORT_LEN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7279
	if (tcp->tcp_ipversion == IPV4_VERSION)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7280
		tcp->tcp_ipha->ipha_src = tcp->tcp_bound_source;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7281
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7282
		tcp->tcp_ip6h->ip6_src = tcp->tcp_bound_source_v6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7283
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7284
	 * Copy of the src addr. in tcp_t is needed in tcp_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7285
	 * since the lookup funcs can only lookup on tcp_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7286
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7287
	tcp->tcp_ip_src_v6 = tcp->tcp_bound_source_v6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7288
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7289
	ASSERT(tcp->tcp_ptpbhn != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7290
	tcp->tcp_rq->q_hiwat = tcp_recv_hiwat;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7291
	tcp->tcp_rwnd = tcp_recv_hiwat;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7292
	tcp->tcp_mss = tcp->tcp_ipversion != IPV4_VERSION ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7293
	    tcp_mss_def_ipv6 : tcp_mss_def_ipv4;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7294
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7295
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7296
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7297
 * Force values to zero that need be zero.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7298
 * Do not touch values asociated with the BOUND or LISTEN state
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7299
 * since the connection will end up in that state after the reinit.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7300
 * NOTE: tcp_reinit_values MUST have a line for each field in the tcp_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7301
 * structure!
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7302
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7303
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7304
tcp_reinit_values(tcp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7305
	tcp_t *tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7306
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7307
#ifndef	lint
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7308
#define	DONTCARE(x)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7309
#define	PRESERVE(x)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7310
#else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7311
#define	DONTCARE(x)	((x) = (x))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7312
#define	PRESERVE(x)	((x) = (x))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7313
#endif	/* lint */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7314
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7315
	PRESERVE(tcp->tcp_bind_hash);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7316
	PRESERVE(tcp->tcp_ptpbhn);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7317
	PRESERVE(tcp->tcp_acceptor_hash);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7318
	PRESERVE(tcp->tcp_ptpahn);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7319
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7320
	/* Should be ASSERT NULL on these with new code! */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7321
	ASSERT(tcp->tcp_time_wait_next == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7322
	ASSERT(tcp->tcp_time_wait_prev == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7323
	ASSERT(tcp->tcp_time_wait_expire == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7324
	PRESERVE(tcp->tcp_state);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7325
	PRESERVE(tcp->tcp_rq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7326
	PRESERVE(tcp->tcp_wq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7327
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7328
	ASSERT(tcp->tcp_xmit_head == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7329
	ASSERT(tcp->tcp_xmit_last == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7330
	ASSERT(tcp->tcp_unsent == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7331
	ASSERT(tcp->tcp_xmit_tail == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7332
	ASSERT(tcp->tcp_xmit_tail_unsent == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7333
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7334
	tcp->tcp_snxt = 0;			/* Displayed in mib */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7335
	tcp->tcp_suna = 0;			/* Displayed in mib */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7336
	tcp->tcp_swnd = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7337
	DONTCARE(tcp->tcp_cwnd);		/* Init in tcp_mss_set */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7338
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7339
	ASSERT(tcp->tcp_ibsegs == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7340
	ASSERT(tcp->tcp_obsegs == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7341
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7342
	if (tcp->tcp_iphc != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7343
		ASSERT(tcp->tcp_iphc_len >= TCP_MAX_COMBINED_HEADER_LENGTH);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7344
		bzero(tcp->tcp_iphc, tcp->tcp_iphc_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7345
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7346
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7347
	DONTCARE(tcp->tcp_naglim);		/* Init in tcp_init_values */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7348
	DONTCARE(tcp->tcp_hdr_len);		/* Init in tcp_init_values */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7349
	DONTCARE(tcp->tcp_ipha);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7350
	DONTCARE(tcp->tcp_ip6h);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7351
	DONTCARE(tcp->tcp_ip_hdr_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7352
	DONTCARE(tcp->tcp_tcph);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7353
	DONTCARE(tcp->tcp_tcp_hdr_len);		/* Init in tcp_init_values */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7354
	tcp->tcp_valid_bits = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7355
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7356
	DONTCARE(tcp->tcp_xmit_hiwater);	/* Init in tcp_init_values */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7357
	DONTCARE(tcp->tcp_timer_backoff);	/* Init in tcp_init_values */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7358
	DONTCARE(tcp->tcp_last_recv_time);	/* Init in tcp_init_values */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7359
	tcp->tcp_last_rcv_lbolt = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7360
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7361
	tcp->tcp_init_cwnd = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7362
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7363
	tcp->tcp_urp_last_valid = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7364
	tcp->tcp_hard_binding = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7365
	tcp->tcp_hard_bound = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7366
	PRESERVE(tcp->tcp_cred);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7367
	PRESERVE(tcp->tcp_cpid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7368
	PRESERVE(tcp->tcp_exclbind);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7369
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7370
	tcp->tcp_fin_acked = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7371
	tcp->tcp_fin_rcvd = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7372
	tcp->tcp_fin_sent = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7373
	tcp->tcp_ordrel_done = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7374
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7375
	tcp->tcp_debug = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7376
	tcp->tcp_dontroute = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7377
	tcp->tcp_broadcast = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7378
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7379
	tcp->tcp_useloopback = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7380
	tcp->tcp_reuseaddr = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7381
	tcp->tcp_oobinline = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7382
	tcp->tcp_dgram_errind = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7383
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7384
	tcp->tcp_detached = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7385
	tcp->tcp_bind_pending = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7386
	tcp->tcp_unbind_pending = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7387
	tcp->tcp_deferred_clean_death = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7388
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7389
	tcp->tcp_snd_ws_ok = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7390
	tcp->tcp_snd_ts_ok = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7391
	tcp->tcp_linger = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7392
	tcp->tcp_ka_enabled = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7393
	tcp->tcp_zero_win_probe = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7394
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7395
	tcp->tcp_loopback = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7396
	tcp->tcp_localnet = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7397
	tcp->tcp_syn_defense = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7398
	tcp->tcp_set_timer = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7399
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7400
	tcp->tcp_active_open = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7401
	ASSERT(tcp->tcp_timeout == B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7402
	tcp->tcp_rexmit = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7403
	tcp->tcp_xmit_zc_clean = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7404
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7405
	tcp->tcp_snd_sack_ok = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7406
	PRESERVE(tcp->tcp_recvdstaddr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7407
	tcp->tcp_hwcksum = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7408
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7409
	tcp->tcp_ire_ill_check_done = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7410
	DONTCARE(tcp->tcp_maxpsz);		/* Init in tcp_init_values */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7411
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7412
	tcp->tcp_mdt = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7413
	tcp->tcp_mdt_hdr_head = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7414
	tcp->tcp_mdt_hdr_tail = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7415
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7416
	tcp->tcp_conn_def_q0 = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7417
	tcp->tcp_ip_forward_progress = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7418
	tcp->tcp_anon_priv_bind = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7419
	tcp->tcp_ecn_ok = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7420
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7421
	tcp->tcp_cwr = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7422
	tcp->tcp_ecn_echo_on = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7423
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7424
	if (tcp->tcp_sack_info != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7425
		if (tcp->tcp_notsack_list != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7426
			TCP_NOTSACK_REMOVE_ALL(tcp->tcp_notsack_list);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7427
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7428
		kmem_cache_free(tcp_sack_info_cache, tcp->tcp_sack_info);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7429
		tcp->tcp_sack_info = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7430
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7431
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7432
	tcp->tcp_rcv_ws = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7433
	tcp->tcp_snd_ws = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7434
	tcp->tcp_ts_recent = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7435
	tcp->tcp_rnxt = 0;			/* Displayed in mib */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7436
	DONTCARE(tcp->tcp_rwnd);		/* Set in tcp_reinit() */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7437
	tcp->tcp_if_mtu = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7438
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7439
	ASSERT(tcp->tcp_reass_head == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7440
	ASSERT(tcp->tcp_reass_tail == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7441
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7442
	tcp->tcp_cwnd_cnt = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7443
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7444
	ASSERT(tcp->tcp_rcv_list == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7445
	ASSERT(tcp->tcp_rcv_last_head == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7446
	ASSERT(tcp->tcp_rcv_last_tail == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7447
	ASSERT(tcp->tcp_rcv_cnt == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7448
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7449
	DONTCARE(tcp->tcp_cwnd_ssthresh);	/* Init in tcp_adapt_ire */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7450
	DONTCARE(tcp->tcp_cwnd_max);		/* Init in tcp_init_values */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7451
	tcp->tcp_csuna = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7452
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7453
	tcp->tcp_rto = 0;			/* Displayed in MIB */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7454
	DONTCARE(tcp->tcp_rtt_sa);		/* Init in tcp_init_values */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7455
	DONTCARE(tcp->tcp_rtt_sd);		/* Init in tcp_init_values */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7456
	tcp->tcp_rtt_update = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7457
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7458
	DONTCARE(tcp->tcp_swl1); /* Init in case TCPS_LISTEN/TCPS_SYN_SENT */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7459
	DONTCARE(tcp->tcp_swl2); /* Init in case TCPS_LISTEN/TCPS_SYN_SENT */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7460
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7461
	tcp->tcp_rack = 0;			/* Displayed in mib */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7462
	tcp->tcp_rack_cnt = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7463
	tcp->tcp_rack_cur_max = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7464
	tcp->tcp_rack_abs_max = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7465
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7466
	tcp->tcp_max_swnd = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7467
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7468
	ASSERT(tcp->tcp_listener == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7469
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7470
	DONTCARE(tcp->tcp_xmit_lowater);	/* Init in tcp_init_values */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7471
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7472
	DONTCARE(tcp->tcp_irs);			/* tcp_valid_bits cleared */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7473
	DONTCARE(tcp->tcp_iss);			/* tcp_valid_bits cleared */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7474
	DONTCARE(tcp->tcp_fss);			/* tcp_valid_bits cleared */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7475
	DONTCARE(tcp->tcp_urg);			/* tcp_valid_bits cleared */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7476
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7477
	ASSERT(tcp->tcp_conn_req_cnt_q == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7478
	ASSERT(tcp->tcp_conn_req_cnt_q0 == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7479
	PRESERVE(tcp->tcp_conn_req_max);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7480
	PRESERVE(tcp->tcp_conn_req_seqnum);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7481
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7482
	DONTCARE(tcp->tcp_ip_hdr_len);		/* Init in tcp_init_values */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7483
	DONTCARE(tcp->tcp_first_timer_threshold); /* Init in tcp_init_values */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7484
	DONTCARE(tcp->tcp_second_timer_threshold); /* Init in tcp_init_values */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7485
	DONTCARE(tcp->tcp_first_ctimer_threshold); /* Init in tcp_init_values */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7486
	DONTCARE(tcp->tcp_second_ctimer_threshold); /* in tcp_init_values */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7487
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7488
	tcp->tcp_lingertime = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7489
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7490
	DONTCARE(tcp->tcp_urp_last);	/* tcp_urp_last_valid is cleared */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7491
	ASSERT(tcp->tcp_urp_mp == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7492
	ASSERT(tcp->tcp_urp_mark_mp == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7493
	ASSERT(tcp->tcp_fused_sigurg_mp == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7494
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7495
	ASSERT(tcp->tcp_eager_next_q == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7496
	ASSERT(tcp->tcp_eager_last_q == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7497
	ASSERT((tcp->tcp_eager_next_q0 == NULL &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7498
	    tcp->tcp_eager_prev_q0 == NULL) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7499
	    tcp->tcp_eager_next_q0 == tcp->tcp_eager_prev_q0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7500
	ASSERT(tcp->tcp_conn.tcp_eager_conn_ind == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7501
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7502
	tcp->tcp_client_errno = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7503
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7504
	DONTCARE(tcp->tcp_sum);			/* Init in tcp_init_values */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7505
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7506
	tcp->tcp_remote_v6 = ipv6_all_zeros;	/* Displayed in MIB */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7507
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7508
	PRESERVE(tcp->tcp_bound_source_v6);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7509
	tcp->tcp_last_sent_len = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7510
	tcp->tcp_dupack_cnt = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7511
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7512
	tcp->tcp_fport = 0;			/* Displayed in MIB */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7513
	PRESERVE(tcp->tcp_lport);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7514
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7515
	PRESERVE(tcp->tcp_acceptor_lockp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7516
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7517
	ASSERT(tcp->tcp_ordrelid == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7518
	PRESERVE(tcp->tcp_acceptor_id);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7519
	DONTCARE(tcp->tcp_ipsec_overhead);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7520
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7521
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7522
	 * If tcp_tracing flag is ON (i.e. We have a trace buffer
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7523
	 * in tcp structure and now tracing), Re-initialize all
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7524
	 * members of tcp_traceinfo.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7525
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7526
	if (tcp->tcp_tracebuf != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7527
		bzero(tcp->tcp_tracebuf, sizeof (tcptrch_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7528
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7529
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7530
	PRESERVE(tcp->tcp_family);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7531
	if (tcp->tcp_family == AF_INET6) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7532
		tcp->tcp_ipversion = IPV6_VERSION;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7533
		tcp->tcp_mss = tcp_mss_def_ipv6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7534
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7535
		tcp->tcp_ipversion = IPV4_VERSION;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7536
		tcp->tcp_mss = tcp_mss_def_ipv4;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7537
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7538
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7539
	tcp->tcp_bound_if = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7540
	tcp->tcp_ipv6_recvancillary = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7541
	tcp->tcp_recvifindex = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7542
	tcp->tcp_recvhops = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7543
	tcp->tcp_closed = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7544
	tcp->tcp_cleandeathtag = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7545
	if (tcp->tcp_hopopts != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7546
		mi_free(tcp->tcp_hopopts);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7547
		tcp->tcp_hopopts = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7548
		tcp->tcp_hopoptslen = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7549
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7550
	ASSERT(tcp->tcp_hopoptslen == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7551
	if (tcp->tcp_dstopts != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7552
		mi_free(tcp->tcp_dstopts);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7553
		tcp->tcp_dstopts = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7554
		tcp->tcp_dstoptslen = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7555
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7556
	ASSERT(tcp->tcp_dstoptslen == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7557
	if (tcp->tcp_rtdstopts != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7558
		mi_free(tcp->tcp_rtdstopts);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7559
		tcp->tcp_rtdstopts = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7560
		tcp->tcp_rtdstoptslen = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7561
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7562
	ASSERT(tcp->tcp_rtdstoptslen == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7563
	if (tcp->tcp_rthdr != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7564
		mi_free(tcp->tcp_rthdr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7565
		tcp->tcp_rthdr = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7566
		tcp->tcp_rthdrlen = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7567
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7568
	ASSERT(tcp->tcp_rthdrlen == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7569
	PRESERVE(tcp->tcp_drop_opt_ack_cnt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7570
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  7571
	/* Reset fusion-related fields */
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7572
	tcp->tcp_fused = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7573
	tcp->tcp_unfusable = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7574
	tcp->tcp_fused_sigurg = B_FALSE;
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  7575
	tcp->tcp_direct_sockfs = B_FALSE;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  7576
	tcp->tcp_fuse_syncstr_stopped = B_FALSE;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7577
	tcp->tcp_loopback_peer = NULL;
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  7578
	tcp->tcp_fuse_rcv_hiwater = 0;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  7579
	tcp->tcp_fuse_rcv_unread_hiwater = 0;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  7580
	tcp->tcp_fuse_rcv_unread_cnt = 0;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7581
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7582
	tcp->tcp_in_ack_unsent = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7583
	tcp->tcp_cork = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7584
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  7585
	PRESERVE(tcp->tcp_squeue_bytes);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  7586
898
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
  7587
	ASSERT(tcp->tcp_kssl_ctx == NULL);
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
  7588
	ASSERT(!tcp->tcp_kssl_pending);
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
  7589
	PRESERVE(tcp->tcp_kssl_ent);
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
  7590
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7591
#undef	DONTCARE
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7592
#undef	PRESERVE
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7593
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7594
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7595
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7596
 * Allocate necessary resources and initialize state vector.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7597
 * Guaranteed not to fail so that when an error is returned,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7598
 * the caller doesn't need to do any additional cleanup.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7599
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7600
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7601
tcp_init(tcp_t *tcp, queue_t *q)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7602
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7603
	int	err;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7604
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7605
	tcp->tcp_rq = q;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7606
	tcp->tcp_wq = WR(q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7607
	tcp->tcp_state = TCPS_IDLE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7608
	if ((err = tcp_init_values(tcp)) != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7609
		tcp_timers_stop(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7610
	return (err);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7611
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7612
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7613
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7614
tcp_init_values(tcp_t *tcp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7615
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7616
	int	err;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7617
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7618
	ASSERT((tcp->tcp_family == AF_INET &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7619
	    tcp->tcp_ipversion == IPV4_VERSION) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7620
	    (tcp->tcp_family == AF_INET6 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7621
	    (tcp->tcp_ipversion == IPV4_VERSION ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7622
	    tcp->tcp_ipversion == IPV6_VERSION)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7623
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7624
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7625
	 * Initialize tcp_rtt_sa and tcp_rtt_sd so that the calculated RTO
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7626
	 * will be close to tcp_rexmit_interval_initial.  By doing this, we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7627
	 * allow the algorithm to adjust slowly to large fluctuations of RTT
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7628
	 * during first few transmissions of a connection as seen in slow
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7629
	 * links.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7630
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7631
	tcp->tcp_rtt_sa = tcp_rexmit_interval_initial << 2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7632
	tcp->tcp_rtt_sd = tcp_rexmit_interval_initial >> 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7633
	tcp->tcp_rto = (tcp->tcp_rtt_sa >> 3) + tcp->tcp_rtt_sd +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7634
	    tcp_rexmit_interval_extra + (tcp->tcp_rtt_sa >> 5) +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7635
	    tcp_conn_grace_period;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7636
	if (tcp->tcp_rto < tcp_rexmit_interval_min)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7637
		tcp->tcp_rto = tcp_rexmit_interval_min;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7638
	tcp->tcp_timer_backoff = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7639
	tcp->tcp_ms_we_have_waited = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7640
	tcp->tcp_last_recv_time = lbolt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7641
	tcp->tcp_cwnd_max = tcp_cwnd_max_;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7642
	tcp->tcp_snd_burst = TCP_CWND_INFINITE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7643
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7644
	tcp->tcp_maxpsz = tcp_maxpsz_multiplier;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7645
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7646
	tcp->tcp_first_timer_threshold = tcp_ip_notify_interval;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7647
	tcp->tcp_first_ctimer_threshold = tcp_ip_notify_cinterval;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7648
	tcp->tcp_second_timer_threshold = tcp_ip_abort_interval;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7649
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7650
	 * Fix it to tcp_ip_abort_linterval later if it turns out to be a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7651
	 * passive open.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7652
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7653
	tcp->tcp_second_ctimer_threshold = tcp_ip_abort_cinterval;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7654
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7655
	tcp->tcp_naglim = tcp_naglim_def;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7656
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7657
	/* NOTE:  ISS is now set in tcp_adapt_ire(). */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7658
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7659
	tcp->tcp_mdt_hdr_head = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7660
	tcp->tcp_mdt_hdr_tail = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7661
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  7662
	/* Reset fusion-related fields */
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7663
	tcp->tcp_fused = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7664
	tcp->tcp_unfusable = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7665
	tcp->tcp_fused_sigurg = B_FALSE;
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  7666
	tcp->tcp_direct_sockfs = B_FALSE;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  7667
	tcp->tcp_fuse_syncstr_stopped = B_FALSE;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7668
	tcp->tcp_loopback_peer = NULL;
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  7669
	tcp->tcp_fuse_rcv_hiwater = 0;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  7670
	tcp->tcp_fuse_rcv_unread_hiwater = 0;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  7671
	tcp->tcp_fuse_rcv_unread_cnt = 0;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7672
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7673
	/* Initialize the header template */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7674
	if (tcp->tcp_ipversion == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7675
		err = tcp_header_init_ipv4(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7676
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7677
		err = tcp_header_init_ipv6(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7678
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7679
	if (err)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7680
		return (err);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7681
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7682
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7683
	 * Init the window scale to the max so tcp_rwnd_set() won't pare
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7684
	 * down tcp_rwnd. tcp_adapt_ire() will set the right value later.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7685
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7686
	tcp->tcp_rcv_ws = TCP_MAX_WINSHIFT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7687
	tcp->tcp_xmit_lowater = tcp_xmit_lowat;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7688
	tcp->tcp_xmit_hiwater = tcp_xmit_hiwat;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7689
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7690
	tcp->tcp_cork = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7691
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7692
	 * Init the tcp_debug option.  This value determines whether TCP
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7693
	 * calls strlog() to print out debug messages.  Doing this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7694
	 * initialization here means that this value is not inherited thru
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7695
	 * tcp_reinit().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7696
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7697
	tcp->tcp_debug = tcp_dbg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7698
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7699
	tcp->tcp_ka_interval = tcp_keepalive_interval;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7700
	tcp->tcp_ka_abort_thres = tcp_keepalive_abort_interval;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7701
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7702
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7703
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7704
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7705
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7706
 * Initialize the IPv4 header. Loses any record of any IP options.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7707
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7708
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7709
tcp_header_init_ipv4(tcp_t *tcp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7710
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7711
	tcph_t		*tcph;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7712
	uint32_t	sum;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7713
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7714
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7715
	 * This is a simple initialization. If there's
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7716
	 * already a template, it should never be too small,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7717
	 * so reuse it.  Otherwise, allocate space for the new one.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7718
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7719
	if (tcp->tcp_iphc == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7720
		ASSERT(tcp->tcp_iphc_len == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7721
		tcp->tcp_iphc_len = TCP_MAX_COMBINED_HEADER_LENGTH;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7722
		tcp->tcp_iphc = kmem_cache_alloc(tcp_iphc_cache, KM_NOSLEEP);
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
			tcp->tcp_iphc_len = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7725
			return (ENOMEM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7726
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7727
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7728
	ASSERT(tcp->tcp_iphc_len >= TCP_MAX_COMBINED_HEADER_LENGTH);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7729
	tcp->tcp_ipha = (ipha_t *)tcp->tcp_iphc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7730
	tcp->tcp_ip6h = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7731
	tcp->tcp_ipversion = IPV4_VERSION;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7732
	tcp->tcp_hdr_len = sizeof (ipha_t) + sizeof (tcph_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7733
	tcp->tcp_tcp_hdr_len = sizeof (tcph_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7734
	tcp->tcp_ip_hdr_len = sizeof (ipha_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7735
	tcp->tcp_ipha->ipha_length = htons(sizeof (ipha_t) + sizeof (tcph_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7736
	tcp->tcp_ipha->ipha_version_and_hdr_length
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7737
		= (IP_VERSION << 4) | IP_SIMPLE_HDR_LENGTH_IN_WORDS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7738
	tcp->tcp_ipha->ipha_ident = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7739
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7740
	tcp->tcp_ttl = (uchar_t)tcp_ipv4_ttl;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7741
	tcp->tcp_tos = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7742
	tcp->tcp_ipha->ipha_fragment_offset_and_flags = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7743
	tcp->tcp_ipha->ipha_ttl = (uchar_t)tcp_ipv4_ttl;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7744
	tcp->tcp_ipha->ipha_protocol = IPPROTO_TCP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7745
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7746
	tcph = (tcph_t *)(tcp->tcp_iphc + sizeof (ipha_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7747
	tcp->tcp_tcph = tcph;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7748
	tcph->th_offset_and_rsrvd[0] = (5 << 4);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7749
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7750
	 * IP wants our header length in the checksum field to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7751
	 * allow it to perform a single pseudo-header+checksum
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7752
	 * calculation on behalf of TCP.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7753
	 * Include the adjustment for a source route once IP_OPTIONS is set.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7754
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7755
	sum = sizeof (tcph_t) + tcp->tcp_sum;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7756
	sum = (sum >> 16) + (sum & 0xFFFF);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7757
	U16_TO_ABE16(sum, tcph->th_sum);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7758
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7759
}
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
 * Initialize the IPv6 header. Loses any record of any IPv6 extension headers.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7763
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7764
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7765
tcp_header_init_ipv6(tcp_t *tcp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7766
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7767
	tcph_t	*tcph;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7768
	uint32_t	sum;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7769
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7770
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7771
	 * This is a simple initialization. If there's
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7772
	 * already a template, it should never be too small,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7773
	 * so reuse it. Otherwise, allocate space for the new one.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7774
	 * Ensure that there is enough space to "downgrade" the tcp_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7775
	 * to an IPv4 tcp_t. This requires having space for a full load
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7776
	 * of IPv4 options, as well as a full load of TCP options
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7777
	 * (TCP_MAX_COMBINED_HEADER_LENGTH, 120 bytes); this is more space
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7778
	 * than a v6 header and a TCP header with a full load of TCP options
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7779
	 * (IPV6_HDR_LEN is 40 bytes; TCP_MAX_HDR_LENGTH is 60 bytes).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7780
	 * We want to avoid reallocation in the "downgraded" case when
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7781
	 * processing outbound IPv4 options.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7782
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7783
	if (tcp->tcp_iphc == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7784
		ASSERT(tcp->tcp_iphc_len == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7785
		tcp->tcp_iphc_len = TCP_MAX_COMBINED_HEADER_LENGTH;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7786
		tcp->tcp_iphc = kmem_cache_alloc(tcp_iphc_cache, KM_NOSLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7787
		if (tcp->tcp_iphc == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7788
			tcp->tcp_iphc_len = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7789
			return (ENOMEM);
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
	ASSERT(tcp->tcp_iphc_len >= TCP_MAX_COMBINED_HEADER_LENGTH);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7793
	tcp->tcp_ipversion = IPV6_VERSION;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7794
	tcp->tcp_hdr_len = IPV6_HDR_LEN + sizeof (tcph_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7795
	tcp->tcp_tcp_hdr_len = sizeof (tcph_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7796
	tcp->tcp_ip_hdr_len = IPV6_HDR_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7797
	tcp->tcp_ip6h = (ip6_t *)tcp->tcp_iphc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7798
	tcp->tcp_ipha = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7799
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7800
	/* Initialize the header template */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7801
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7802
	tcp->tcp_ip6h->ip6_vcf = IPV6_DEFAULT_VERS_AND_FLOW;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7803
	tcp->tcp_ip6h->ip6_plen = ntohs(sizeof (tcph_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7804
	tcp->tcp_ip6h->ip6_nxt = IPPROTO_TCP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7805
	tcp->tcp_ip6h->ip6_hops = (uint8_t)tcp_ipv6_hoplimit;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7806
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7807
	tcph = (tcph_t *)(tcp->tcp_iphc + IPV6_HDR_LEN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7808
	tcp->tcp_tcph = tcph;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7809
	tcph->th_offset_and_rsrvd[0] = (5 << 4);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7810
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7811
	 * IP wants our header length in the checksum field to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7812
	 * allow it to perform a single psuedo-header+checksum
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7813
	 * calculation on behalf of TCP.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7814
	 * Include the adjustment for a source route when IPV6_RTHDR is set.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7815
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7816
	sum = sizeof (tcph_t) + tcp->tcp_sum;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7817
	sum = (sum >> 16) + (sum & 0xFFFF);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7818
	U16_TO_ABE16(sum, tcph->th_sum);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7819
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7820
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7821
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7822
/* At minimum we need 4 bytes in the TCP header for the lookup */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7823
#define	ICMP_MIN_TCP_HDR	4
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7824
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7825
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7826
 * tcp_icmp_error is called by tcp_rput_other to process ICMP error messages
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7827
 * passed up by IP. The message is always received on the correct tcp_t.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7828
 * Assumes that IP has pulled up everything up to and including the ICMP header.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7829
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7830
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7831
tcp_icmp_error(tcp_t *tcp, mblk_t *mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7832
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7833
	icmph_t *icmph;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7834
	ipha_t	*ipha;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7835
	int	iph_hdr_length;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7836
	tcph_t	*tcph;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7837
	boolean_t ipsec_mctl = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7838
	boolean_t secure;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7839
	mblk_t *first_mp = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7840
	uint32_t new_mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7841
	uint32_t ratio;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7842
	size_t mp_size = MBLKL(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7843
	uint32_t seg_ack;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7844
	uint32_t seg_seq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7845
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7846
	/* Assume IP provides aligned packets - otherwise toss */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7847
	if (!OK_32PTR(mp->b_rptr)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7848
		freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7849
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7850
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7851
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7852
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7853
	 * Since ICMP errors are normal data marked with M_CTL when sent
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7854
	 * to TCP or UDP, we have to look for a IPSEC_IN value to identify
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7855
	 * packets starting with an ipsec_info_t, see ipsec_info.h.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7856
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7857
	if ((mp_size == sizeof (ipsec_info_t)) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7858
	    (((ipsec_info_t *)mp->b_rptr)->ipsec_info_type == IPSEC_IN)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7859
		ASSERT(mp->b_cont != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7860
		mp = mp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7861
		/* IP should have done this */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7862
		ASSERT(OK_32PTR(mp->b_rptr));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7863
		mp_size = MBLKL(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7864
		ipsec_mctl = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7865
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7866
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7867
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7868
	 * Verify that we have a complete outer IP header. If not, drop it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7869
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7870
	if (mp_size < sizeof (ipha_t)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7871
noticmpv4:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7872
		freemsg(first_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7873
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7874
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7875
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7876
	ipha = (ipha_t *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7877
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7878
	 * Verify IP version. Anything other than IPv4 or IPv6 packet is sent
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7879
	 * upstream. ICMPv6 is handled in tcp_icmp_error_ipv6.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7880
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7881
	switch (IPH_HDR_VERSION(ipha)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7882
	case IPV6_VERSION:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7883
		tcp_icmp_error_ipv6(tcp, first_mp, ipsec_mctl);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7884
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7885
	case IPV4_VERSION:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7886
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7887
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7888
		goto noticmpv4;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7889
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7890
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7891
	/* Skip past the outer IP and ICMP headers */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7892
	iph_hdr_length = IPH_HDR_LENGTH(ipha);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7893
	icmph = (icmph_t *)&mp->b_rptr[iph_hdr_length];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7894
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7895
	 * If we don't have the correct outer IP header length or if the ULP
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7896
	 * is not IPPROTO_ICMP or if we don't have a complete inner IP header
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7897
	 * send it upstream.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7898
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7899
	if (iph_hdr_length < sizeof (ipha_t) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7900
	    ipha->ipha_protocol != IPPROTO_ICMP ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7901
	    (ipha_t *)&icmph[1] + 1 > (ipha_t *)mp->b_wptr) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7902
		goto noticmpv4;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7903
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7904
	ipha = (ipha_t *)&icmph[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7905
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7906
	/* Skip past the inner IP and find the ULP header */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7907
	iph_hdr_length = IPH_HDR_LENGTH(ipha);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7908
	tcph = (tcph_t *)((char *)ipha + iph_hdr_length);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7909
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7910
	 * If we don't have the correct inner IP header length or if the ULP
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7911
	 * 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
  7912
	 * bytes of TCP header, drop it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7913
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7914
	if (iph_hdr_length < sizeof (ipha_t) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7915
	    ipha->ipha_protocol != IPPROTO_TCP ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7916
	    (uchar_t *)tcph + ICMP_MIN_TCP_HDR > mp->b_wptr) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7917
		goto noticmpv4;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7918
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7919
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7920
	if (TCP_IS_DETACHED_NONEAGER(tcp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7921
		if (ipsec_mctl) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7922
			secure = ipsec_in_is_secure(first_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7923
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7924
			secure = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7925
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7926
		if (secure) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7927
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7928
			 * If we are willing to accept this in clear
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7929
			 * we don't have to verify policy.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7930
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7931
			if (!ipsec_inbound_accept_clear(mp, ipha, NULL)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7932
				if (!tcp_check_policy(tcp, first_mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7933
				    ipha, NULL, secure, ipsec_mctl)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7934
					/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7935
					 * tcp_check_policy called
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7936
					 * ip_drop_packet() on failure.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7937
					 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7938
					return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7939
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7940
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7941
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7942
	} else if (ipsec_mctl) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7943
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7944
		 * This is a hard_bound connection. IP has already
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7945
		 * verified policy. We don't have to do it again.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7946
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7947
		freeb(first_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7948
		first_mp = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7949
		ipsec_mctl = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7950
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7951
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7952
	seg_ack = ABE32_TO_U32(tcph->th_ack);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7953
	seg_seq = ABE32_TO_U32(tcph->th_seq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7954
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7955
	 * TCP SHOULD check that the TCP sequence number contained in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7956
	 * payload of the ICMP error message is within the range
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7957
	 * SND.UNA <= SEG.SEQ < SND.NXT. and also SEG.ACK <= RECV.NXT
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7958
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7959
	if (SEQ_LT(seg_seq, tcp->tcp_suna) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7960
		SEQ_GEQ(seg_seq, tcp->tcp_snxt) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7961
		SEQ_GT(seg_ack, tcp->tcp_rnxt)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7962
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7963
		 * If the ICMP message is bogus, should we kill the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7964
		 * connection, or should we just drop the bogus ICMP
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7965
		 * message? It would probably make more sense to just
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7966
		 * drop the message so that if this one managed to get
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7967
		 * in, the real connection should not suffer.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7968
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7969
		goto noticmpv4;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7970
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7971
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7972
	switch (icmph->icmph_type) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7973
	case ICMP_DEST_UNREACHABLE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7974
		switch (icmph->icmph_code) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7975
		case ICMP_FRAGMENTATION_NEEDED:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7976
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7977
			 * Reduce the MSS based on the new MTU.  This will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7978
			 * eliminate any fragmentation locally.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7979
			 * N.B.  There may well be some funny side-effects on
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7980
			 * the local send policy and the remote receive policy.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7981
			 * Pending further research, we provide
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7982
			 * tcp_ignore_path_mtu just in case this proves
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7983
			 * disastrous somewhere.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7984
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7985
			 * After updating the MSS, retransmit part of the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7986
			 * dropped segment using the new mss by calling
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7987
			 * tcp_wput_data().  Need to adjust all those
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7988
			 * params to make sure tcp_wput_data() work properly.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7989
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7990
			if (tcp_ignore_path_mtu)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7991
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7992
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7993
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7994
			 * Decrease the MSS by time stamp options
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7995
			 * IP options and IPSEC options. tcp_hdr_len
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7996
			 * includes time stamp option and IP option
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7997
			 * length.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7998
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7999
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8000
			new_mss = ntohs(icmph->icmph_du_mtu) -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8001
			    tcp->tcp_hdr_len - tcp->tcp_ipsec_overhead;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8002
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8003
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8004
			 * Only update the MSS if the new one is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8005
			 * smaller than the previous one.  This is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8006
			 * to avoid problems when getting multiple
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8007
			 * ICMP errors for the same MTU.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8008
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8009
			if (new_mss >= tcp->tcp_mss)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8010
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8011
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8012
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8013
			 * Stop doing PMTU if new_mss is less than 68
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8014
			 * or less than tcp_mss_min.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8015
			 * The value 68 comes from rfc 1191.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8016
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8017
			if (new_mss < MAX(68, tcp_mss_min))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8018
				tcp->tcp_ipha->ipha_fragment_offset_and_flags =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8019
				    0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8020
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8021
			ratio = tcp->tcp_cwnd / tcp->tcp_mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8022
			ASSERT(ratio >= 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8023
			tcp_mss_set(tcp, new_mss);
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
			 * Make sure we have something to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8027
			 * send.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8028
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8029
			if (SEQ_LT(tcp->tcp_suna, tcp->tcp_snxt) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8030
			    (tcp->tcp_xmit_head != NULL)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8031
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8032
				 * Shrink tcp_cwnd in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8033
				 * proportion to the old MSS/new MSS.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8034
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8035
				tcp->tcp_cwnd = ratio * tcp->tcp_mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8036
				if ((tcp->tcp_valid_bits & TCP_FSS_VALID) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8037
				    (tcp->tcp_unsent == 0)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8038
					tcp->tcp_rexmit_max = tcp->tcp_fss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8039
				} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8040
					tcp->tcp_rexmit_max = tcp->tcp_snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8041
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8042
				tcp->tcp_rexmit_nxt = tcp->tcp_suna;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8043
				tcp->tcp_rexmit = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8044
				tcp->tcp_dupack_cnt = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8045
				tcp->tcp_snd_burst = TCP_CWND_SS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8046
				tcp_ss_rexmit(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8047
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8048
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8049
		case ICMP_PORT_UNREACHABLE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8050
		case ICMP_PROTOCOL_UNREACHABLE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8051
			switch (tcp->tcp_state) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8052
			case TCPS_SYN_SENT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8053
			case TCPS_SYN_RCVD:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8054
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8055
				 * ICMP can snipe away incipient
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8056
				 * TCP connections as long as
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8057
				 * seq number is same as initial
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8058
				 * send seq number.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8059
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8060
				if (seg_seq == tcp->tcp_iss) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8061
					(void) tcp_clean_death(tcp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8062
					    ECONNREFUSED, 6);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8063
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8064
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8065
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8066
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8067
		case ICMP_HOST_UNREACHABLE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8068
		case ICMP_NET_UNREACHABLE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8069
			/* Record the error in case we finally time out. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8070
			if (icmph->icmph_code == ICMP_HOST_UNREACHABLE)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8071
				tcp->tcp_client_errno = EHOSTUNREACH;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8072
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8073
				tcp->tcp_client_errno = ENETUNREACH;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8074
			if (tcp->tcp_state == TCPS_SYN_RCVD) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8075
				if (tcp->tcp_listener != NULL &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8076
				    tcp->tcp_listener->tcp_syn_defense) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8077
					/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8078
					 * Ditch the half-open connection if we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8079
					 * suspect a SYN attack is under way.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8080
					 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8081
					tcp_ip_ire_mark_advice(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8082
					(void) tcp_clean_death(tcp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8083
					    tcp->tcp_client_errno, 7);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8084
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8085
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8086
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8087
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8088
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8089
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8090
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8091
	case ICMP_SOURCE_QUENCH: {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8092
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8093
		 * use a global boolean to control
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8094
		 * whether TCP should respond to ICMP_SOURCE_QUENCH.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8095
		 * The default is false.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8096
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8097
		if (tcp_icmp_source_quench) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8098
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8099
			 * Reduce the sending rate as if we got a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8100
			 * retransmit timeout
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8101
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8102
			uint32_t npkt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8103
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8104
			npkt = ((tcp->tcp_snxt - tcp->tcp_suna) >> 1) /
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8105
			    tcp->tcp_mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8106
			tcp->tcp_cwnd_ssthresh = MAX(npkt, 2) * tcp->tcp_mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8107
			tcp->tcp_cwnd = tcp->tcp_mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8108
			tcp->tcp_cwnd_cnt = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8109
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8110
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8111
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8112
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8113
	freemsg(first_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8114
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8115
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8116
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8117
 * tcp_icmp_error_ipv6 is called by tcp_rput_other to process ICMPv6
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8118
 * error messages passed up by IP.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8119
 * Assumes that IP has pulled up all the extension headers as well
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8120
 * as the ICMPv6 header.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8121
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8122
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8123
tcp_icmp_error_ipv6(tcp_t *tcp, mblk_t *mp, boolean_t ipsec_mctl)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8124
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8125
	icmp6_t *icmp6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8126
	ip6_t	*ip6h;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8127
	uint16_t	iph_hdr_length;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8128
	tcpha_t	*tcpha;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8129
	uint8_t	*nexthdrp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8130
	uint32_t new_mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8131
	uint32_t ratio;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8132
	boolean_t secure;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8133
	mblk_t *first_mp = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8134
	size_t mp_size;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8135
	uint32_t seg_ack;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8136
	uint32_t seg_seq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8137
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8138
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8139
	 * The caller has determined if this is an IPSEC_IN packet and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8140
	 * set ipsec_mctl appropriately (see tcp_icmp_error).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8141
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8142
	if (ipsec_mctl)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8143
		mp = mp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8144
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8145
	mp_size = MBLKL(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8146
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8147
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8148
	 * Verify that we have a complete IP header. If not, send it upstream.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8149
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8150
	if (mp_size < sizeof (ip6_t)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8151
noticmpv6:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8152
		freemsg(first_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8153
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8154
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8155
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8156
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8157
	 * Verify this is an ICMPV6 packet, else send it upstream.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8158
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8159
	ip6h = (ip6_t *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8160
	if (ip6h->ip6_nxt == IPPROTO_ICMPV6) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8161
		iph_hdr_length = IPV6_HDR_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8162
	} else if (!ip_hdr_length_nexthdr_v6(mp, ip6h, &iph_hdr_length,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8163
	    &nexthdrp) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8164
	    *nexthdrp != IPPROTO_ICMPV6) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8165
		goto noticmpv6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8166
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8167
	icmp6 = (icmp6_t *)&mp->b_rptr[iph_hdr_length];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8168
	ip6h = (ip6_t *)&icmp6[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8169
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8170
	 * Verify if we have a complete ICMP and inner IP header.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8171
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8172
	if ((uchar_t *)&ip6h[1] > mp->b_wptr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8173
		goto noticmpv6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8174
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8175
	if (!ip_hdr_length_nexthdr_v6(mp, ip6h, &iph_hdr_length, &nexthdrp))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8176
		goto noticmpv6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8177
	tcpha = (tcpha_t *)((char *)ip6h + iph_hdr_length);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8178
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8179
	 * Validate inner header. If the ULP is not IPPROTO_TCP or if we don't
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8180
	 * have at least ICMP_MIN_TCP_HDR bytes of  TCP header drop the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8181
	 * packet.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8182
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8183
	if ((*nexthdrp != IPPROTO_TCP) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8184
	    ((uchar_t *)tcpha + ICMP_MIN_TCP_HDR) > mp->b_wptr) {
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
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8189
	 * ICMP errors come on the right queue or come on
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8190
	 * listener/global queue for detached connections and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8191
	 * get switched to the right queue. If it comes on the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8192
	 * right queue, policy check has already been done by IP
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8193
	 * and thus free the first_mp without verifying the policy.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8194
	 * If it has come for a non-hard bound connection, we need
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8195
	 * to verify policy as IP may not have done it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8196
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8197
	if (!tcp->tcp_hard_bound) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8198
		if (ipsec_mctl) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8199
			secure = ipsec_in_is_secure(first_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8200
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8201
			secure = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8202
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8203
		if (secure) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8204
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8205
			 * If we are willing to accept this in clear
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8206
			 * we don't have to verify policy.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8207
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8208
			if (!ipsec_inbound_accept_clear(mp, NULL, ip6h)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8209
				if (!tcp_check_policy(tcp, first_mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8210
				    NULL, ip6h, secure, ipsec_mctl)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8211
					/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8212
					 * tcp_check_policy called
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8213
					 * ip_drop_packet() on failure.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8214
					 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8215
					return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8216
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8217
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8218
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8219
	} else if (ipsec_mctl) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8220
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8221
		 * This is a hard_bound connection. IP has already
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8222
		 * verified policy. We don't have to do it again.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8223
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8224
		freeb(first_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8225
		first_mp = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8226
		ipsec_mctl = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8227
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8228
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8229
	seg_ack = ntohl(tcpha->tha_ack);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8230
	seg_seq = ntohl(tcpha->tha_seq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8231
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8232
	 * TCP SHOULD check that the TCP sequence number contained in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8233
	 * payload of the ICMP error message is within the range
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8234
	 * SND.UNA <= SEG.SEQ < SND.NXT. and also SEG.ACK <= RECV.NXT
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8235
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8236
	if (SEQ_LT(seg_seq, tcp->tcp_suna) || SEQ_GEQ(seg_seq, tcp->tcp_snxt) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8237
	    SEQ_GT(seg_ack, tcp->tcp_rnxt)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8238
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8239
		 * If the ICMP message is bogus, should we kill the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8240
		 * connection, or should we just drop the bogus ICMP
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8241
		 * message? It would probably make more sense to just
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8242
		 * drop the message so that if this one managed to get
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8243
		 * in, the real connection should not suffer.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8244
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8245
		goto noticmpv6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8246
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8247
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8248
	switch (icmp6->icmp6_type) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8249
	case ICMP6_PACKET_TOO_BIG:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8250
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8251
		 * Reduce the MSS based on the new MTU.  This will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8252
		 * eliminate any fragmentation locally.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8253
		 * N.B.  There may well be some funny side-effects on
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8254
		 * the local send policy and the remote receive policy.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8255
		 * Pending further research, we provide
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8256
		 * tcp_ignore_path_mtu just in case this proves
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8257
		 * disastrous somewhere.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8258
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8259
		 * After updating the MSS, retransmit part of the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8260
		 * dropped segment using the new mss by calling
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8261
		 * tcp_wput_data().  Need to adjust all those
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8262
		 * params to make sure tcp_wput_data() work properly.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8263
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8264
		if (tcp_ignore_path_mtu)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8265
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8266
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8267
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8268
		 * Decrease the MSS by time stamp options
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8269
		 * IP options and IPSEC options. tcp_hdr_len
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8270
		 * includes time stamp option and IP option
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8271
		 * length.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8272
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8273
		new_mss = ntohs(icmp6->icmp6_mtu) - tcp->tcp_hdr_len -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8274
			    tcp->tcp_ipsec_overhead;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8275
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8276
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8277
		 * Only update the MSS if the new one is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8278
		 * smaller than the previous one.  This is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8279
		 * to avoid problems when getting multiple
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8280
		 * ICMP errors for the same MTU.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8281
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8282
		if (new_mss >= tcp->tcp_mss)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8283
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8284
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8285
		ratio = tcp->tcp_cwnd / tcp->tcp_mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8286
		ASSERT(ratio >= 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8287
		tcp_mss_set(tcp, new_mss);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8288
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8289
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8290
		 * Make sure we have something to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8291
		 * send.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8292
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8293
		if (SEQ_LT(tcp->tcp_suna, tcp->tcp_snxt) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8294
		    (tcp->tcp_xmit_head != NULL)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8295
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8296
			 * Shrink tcp_cwnd in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8297
			 * proportion to the old MSS/new MSS.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8298
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8299
			tcp->tcp_cwnd = ratio * tcp->tcp_mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8300
			if ((tcp->tcp_valid_bits & TCP_FSS_VALID) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8301
			    (tcp->tcp_unsent == 0)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8302
				tcp->tcp_rexmit_max = tcp->tcp_fss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8303
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8304
				tcp->tcp_rexmit_max = tcp->tcp_snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8305
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8306
			tcp->tcp_rexmit_nxt = tcp->tcp_suna;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8307
			tcp->tcp_rexmit = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8308
			tcp->tcp_dupack_cnt = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8309
			tcp->tcp_snd_burst = TCP_CWND_SS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8310
			tcp_ss_rexmit(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8311
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8312
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8313
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8314
	case ICMP6_DST_UNREACH:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8315
		switch (icmp6->icmp6_code) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8316
		case ICMP6_DST_UNREACH_NOPORT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8317
			if (((tcp->tcp_state == TCPS_SYN_SENT) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8318
			    (tcp->tcp_state == TCPS_SYN_RCVD)) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8319
			    (tcpha->tha_seq == tcp->tcp_iss)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8320
				(void) tcp_clean_death(tcp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8321
				    ECONNREFUSED, 8);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8322
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8323
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8324
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8325
		case ICMP6_DST_UNREACH_ADMIN:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8326
		case ICMP6_DST_UNREACH_NOROUTE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8327
		case ICMP6_DST_UNREACH_BEYONDSCOPE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8328
		case ICMP6_DST_UNREACH_ADDR:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8329
			/* Record the error in case we finally time out. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8330
			tcp->tcp_client_errno = EHOSTUNREACH;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8331
			if (((tcp->tcp_state == TCPS_SYN_SENT) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8332
			    (tcp->tcp_state == TCPS_SYN_RCVD)) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8333
			    (tcpha->tha_seq == tcp->tcp_iss)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8334
				if (tcp->tcp_listener != NULL &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8335
				    tcp->tcp_listener->tcp_syn_defense) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8336
					/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8337
					 * Ditch the half-open connection if we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8338
					 * suspect a SYN attack is under way.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8339
					 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8340
					tcp_ip_ire_mark_advice(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8341
					(void) tcp_clean_death(tcp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8342
					    tcp->tcp_client_errno, 9);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8343
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8344
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8345
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8346
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8347
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8348
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8349
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8350
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8351
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8352
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8353
	case ICMP6_PARAM_PROB:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8354
		/* If this corresponds to an ICMP_PROTOCOL_UNREACHABLE */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8355
		if (icmp6->icmp6_code == ICMP6_PARAMPROB_NEXTHEADER &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8356
		    (uchar_t *)ip6h + icmp6->icmp6_pptr ==
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8357
		    (uchar_t *)nexthdrp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8358
			if (tcp->tcp_state == TCPS_SYN_SENT ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8359
			    tcp->tcp_state == TCPS_SYN_RCVD) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8360
				(void) tcp_clean_death(tcp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8361
				    ECONNREFUSED, 10);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8362
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8363
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8364
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8365
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8366
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8367
	case ICMP6_TIME_EXCEEDED:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8368
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8369
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8370
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8371
	freemsg(first_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8372
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8373
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8374
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8375
 * IP recognizes seven kinds of bind requests:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8376
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8377
 * - A zero-length address binds only to the protocol number.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8378
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8379
 * - A 4-byte address is treated as a request to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8380
 * validate that the address is a valid local IPv4
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8381
 * address, appropriate for an application to bind to.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8382
 * IP does the verification, but does not make any note
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8383
 * of the address at this time.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8384
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8385
 * - A 16-byte address contains is treated as a request
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8386
 * to validate a local IPv6 address, as the 4-byte
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8387
 * address case above.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8388
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8389
 * - A 16-byte sockaddr_in to validate the local IPv4 address and also
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8390
 * use it for the inbound fanout of packets.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8391
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8392
 * - A 24-byte sockaddr_in6 to validate the local IPv6 address and also
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8393
 * use it for the inbound fanout of packets.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8394
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8395
 * - A 12-byte address (ipa_conn_t) containing complete IPv4 fanout
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8396
 * information consisting of local and remote addresses
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8397
 * and ports.  In this case, the addresses are both
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8398
 * validated as appropriate for this operation, and, if
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8399
 * so, the information is retained for use in the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8400
 * inbound fanout.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8401
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8402
 * - A 36-byte address address (ipa6_conn_t) containing complete IPv6
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8403
 * fanout information, like the 12-byte case above.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8404
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8405
 * IP will also fill in the IRE request mblk with information
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8406
 * regarding our peer.  In all cases, we notify IP of our protocol
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8407
 * type by appending a single protocol byte to the bind request.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8408
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8409
static mblk_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8410
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
  8411
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8412
	char	*cp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8413
	mblk_t	*mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8414
	struct T_bind_req *tbr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8415
	ipa_conn_t	*ac;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8416
	ipa6_conn_t	*ac6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8417
	sin_t		*sin;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8418
	sin6_t		*sin6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8419
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8420
	ASSERT(bind_prim == O_T_BIND_REQ || bind_prim == T_BIND_REQ);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8421
	ASSERT((tcp->tcp_family == AF_INET &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8422
	    tcp->tcp_ipversion == IPV4_VERSION) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8423
	    (tcp->tcp_family == AF_INET6 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8424
	    (tcp->tcp_ipversion == IPV4_VERSION ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8425
	    tcp->tcp_ipversion == IPV6_VERSION)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8426
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8427
	mp = allocb(sizeof (*tbr) + addr_length + 1, BPRI_HI);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8428
	if (!mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8429
		return (mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8430
	mp->b_datap->db_type = M_PROTO;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8431
	tbr = (struct T_bind_req *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8432
	tbr->PRIM_type = bind_prim;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8433
	tbr->ADDR_offset = sizeof (*tbr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8434
	tbr->CONIND_number = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8435
	tbr->ADDR_length = addr_length;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8436
	cp = (char *)&tbr[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8437
	switch (addr_length) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8438
	case sizeof (ipa_conn_t):
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8439
		ASSERT(tcp->tcp_family == AF_INET);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8440
		ASSERT(tcp->tcp_ipversion == IPV4_VERSION);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8441
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8442
		mp->b_cont = allocb(sizeof (ire_t), BPRI_HI);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8443
		if (mp->b_cont == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8444
			freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8445
			return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8446
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8447
		mp->b_cont->b_wptr += sizeof (ire_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8448
		mp->b_cont->b_datap->db_type = IRE_DB_REQ_TYPE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8449
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8450
		/* cp known to be 32 bit aligned */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8451
		ac = (ipa_conn_t *)cp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8452
		ac->ac_laddr = tcp->tcp_ipha->ipha_src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8453
		ac->ac_faddr = tcp->tcp_remote;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8454
		ac->ac_fport = tcp->tcp_fport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8455
		ac->ac_lport = tcp->tcp_lport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8456
		tcp->tcp_hard_binding = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8457
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8458
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8459
	case sizeof (ipa6_conn_t):
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8460
		ASSERT(tcp->tcp_family == AF_INET6);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8461
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8462
		mp->b_cont = allocb(sizeof (ire_t), BPRI_HI);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8463
		if (mp->b_cont == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8464
			freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8465
			return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8466
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8467
		mp->b_cont->b_wptr += sizeof (ire_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8468
		mp->b_cont->b_datap->db_type = IRE_DB_REQ_TYPE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8469
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8470
		/* cp known to be 32 bit aligned */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8471
		ac6 = (ipa6_conn_t *)cp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8472
		if (tcp->tcp_ipversion == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8473
			IN6_IPADDR_TO_V4MAPPED(tcp->tcp_ipha->ipha_src,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8474
			    &ac6->ac6_laddr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8475
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8476
			ac6->ac6_laddr = tcp->tcp_ip6h->ip6_src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8477
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8478
		ac6->ac6_faddr = tcp->tcp_remote_v6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8479
		ac6->ac6_fport = tcp->tcp_fport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8480
		ac6->ac6_lport = tcp->tcp_lport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8481
		tcp->tcp_hard_binding = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8482
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8483
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8484
	case sizeof (sin_t):
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8485
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8486
		 * NOTE: IPV6_ADDR_LEN also has same size.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8487
		 * Use family to discriminate.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8488
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8489
		if (tcp->tcp_family == AF_INET) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8490
			sin = (sin_t *)cp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8491
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8492
			*sin = sin_null;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8493
			sin->sin_family = AF_INET;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8494
			sin->sin_addr.s_addr = tcp->tcp_bound_source;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8495
			sin->sin_port = tcp->tcp_lport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8496
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8497
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8498
			*(in6_addr_t *)cp = tcp->tcp_bound_source_v6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8499
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8500
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8501
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8502
	case sizeof (sin6_t):
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8503
		ASSERT(tcp->tcp_family == AF_INET6);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8504
		sin6 = (sin6_t *)cp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8505
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8506
		*sin6 = sin6_null;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8507
		sin6->sin6_family = AF_INET6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8508
		sin6->sin6_addr = tcp->tcp_bound_source_v6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8509
		sin6->sin6_port = tcp->tcp_lport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8510
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8511
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8512
	case IP_ADDR_LEN:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8513
		ASSERT(tcp->tcp_ipversion == IPV4_VERSION);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8514
		*(uint32_t *)cp = tcp->tcp_ipha->ipha_src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8515
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8516
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8517
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8518
	/* Add protocol number to end */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8519
	cp[addr_length] = (char)IPPROTO_TCP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8520
	mp->b_wptr = (uchar_t *)&cp[addr_length + 1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8521
	return (mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8522
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8523
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8524
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8525
 * Notify IP that we are having trouble with this connection.  IP should
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8526
 * blow the IRE away and start over.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8527
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8528
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8529
tcp_ip_notify(tcp_t *tcp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8530
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8531
	struct iocblk	*iocp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8532
	ipid_t	*ipid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8533
	mblk_t	*mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8534
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8535
	/* IPv6 has NUD thus notification to delete the IRE is not needed */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8536
	if (tcp->tcp_ipversion == IPV6_VERSION)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8537
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8538
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8539
	mp = mkiocb(IP_IOCTL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8540
	if (mp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8541
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8542
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8543
	iocp = (struct iocblk *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8544
	iocp->ioc_count = sizeof (ipid_t) + sizeof (tcp->tcp_ipha->ipha_dst);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8545
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8546
	mp->b_cont = allocb(iocp->ioc_count, BPRI_HI);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8547
	if (!mp->b_cont) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8548
		freeb(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8549
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8550
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8551
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8552
	ipid = (ipid_t *)mp->b_cont->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8553
	mp->b_cont->b_wptr += iocp->ioc_count;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8554
	bzero(ipid, sizeof (*ipid));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8555
	ipid->ipid_cmd = IP_IOC_IRE_DELETE_NO_REPLY;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8556
	ipid->ipid_ire_type = IRE_CACHE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8557
	ipid->ipid_addr_offset = sizeof (ipid_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8558
	ipid->ipid_addr_length = sizeof (tcp->tcp_ipha->ipha_dst);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8559
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8560
	 * Note: in the case of source routing we want to blow away the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8561
	 * route to the first source route hop.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8562
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8563
	bcopy(&tcp->tcp_ipha->ipha_dst, &ipid[1],
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8564
	    sizeof (tcp->tcp_ipha->ipha_dst));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8565
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8566
	CALL_IP_WPUT(tcp->tcp_connp, tcp->tcp_wq, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8567
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8568
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8569
/* Unlink and return any mblk that looks like it contains an ire */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8570
static mblk_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8571
tcp_ire_mp(mblk_t *mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8572
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8573
	mblk_t	*prev_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8574
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8575
	for (;;) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8576
		prev_mp = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8577
		mp = mp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8578
		if (mp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8579
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8580
		switch (DB_TYPE(mp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8581
		case IRE_DB_TYPE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8582
		case IRE_DB_REQ_TYPE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8583
			if (prev_mp != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8584
				prev_mp->b_cont = mp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8585
			mp->b_cont = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8586
			return (mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8587
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8588
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8589
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8590
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8591
	return (mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8592
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8593
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8594
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8595
 * Timer callback routine for keepalive probe.  We do a fake resend of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8596
 * last ACKed byte.  Then set a timer using RTO.  When the timer expires,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8597
 * check to see if we have heard anything from the other end for the last
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8598
 * RTO period.  If we have, set the timer to expire for another
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8599
 * tcp_keepalive_intrvl and check again.  If we have not, set a timer using
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8600
 * RTO << 1 and check again when it expires.  Keep exponentially increasing
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8601
 * the timeout if we have not heard from the other side.  If for more than
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8602
 * (tcp_ka_interval + tcp_ka_abort_thres) we have not heard anything,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8603
 * kill the connection unless the keepalive abort threshold is 0.  In
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8604
 * that case, we will probe "forever."
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8605
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8606
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8607
tcp_keepalive_killer(void *arg)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8608
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8609
	mblk_t	*mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8610
	conn_t	*connp = (conn_t *)arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8611
	tcp_t  	*tcp = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8612
	int32_t	firetime;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8613
	int32_t	idletime;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8614
	int32_t	ka_intrvl;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8615
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8616
	tcp->tcp_ka_tid = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8617
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8618
	if (tcp->tcp_fused)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8619
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8620
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8621
	BUMP_MIB(&tcp_mib, tcpTimKeepalive);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8622
	ka_intrvl = tcp->tcp_ka_interval;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8623
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8624
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8625
	 * Keepalive probe should only be sent if the application has not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8626
	 * done a close on the connection.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8627
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8628
	if (tcp->tcp_state > TCPS_CLOSE_WAIT) {
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
	/* Timer fired too early, restart it. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8632
	if (tcp->tcp_state < TCPS_ESTABLISHED) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8633
		tcp->tcp_ka_tid = TCP_TIMER(tcp, tcp_keepalive_killer,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8634
		    MSEC_TO_TICK(ka_intrvl));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8635
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8636
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8637
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8638
	idletime = TICK_TO_MSEC(lbolt - tcp->tcp_last_recv_time);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8639
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8640
	 * If we have not heard from the other side for a long
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8641
	 * time, kill the connection unless the keepalive abort
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8642
	 * threshold is 0.  In that case, we will probe "forever."
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8643
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8644
	if (tcp->tcp_ka_abort_thres != 0 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8645
	    idletime > (ka_intrvl + tcp->tcp_ka_abort_thres)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8646
		BUMP_MIB(&tcp_mib, tcpTimKeepaliveDrop);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8647
		(void) tcp_clean_death(tcp, tcp->tcp_client_errno ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8648
		    tcp->tcp_client_errno : ETIMEDOUT, 11);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8649
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8650
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8651
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8652
	if (tcp->tcp_snxt == tcp->tcp_suna &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8653
	    idletime >= ka_intrvl) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8654
		/* Fake resend of last ACKed byte. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8655
		mblk_t	*mp1 = allocb(1, BPRI_LO);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8656
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8657
		if (mp1 != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8658
			*mp1->b_wptr++ = '\0';
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8659
			mp = tcp_xmit_mp(tcp, mp1, 1, NULL, NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8660
			    tcp->tcp_suna - 1, B_FALSE, NULL, B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8661
			freeb(mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8662
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8663
			 * if allocation failed, fall through to start the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8664
			 * timer back.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8665
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8666
			if (mp != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8667
				TCP_RECORD_TRACE(tcp, mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8668
				    TCP_TRACE_SEND_PKT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8669
				tcp_send_data(tcp, tcp->tcp_wq, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8670
				BUMP_MIB(&tcp_mib, tcpTimKeepaliveProbe);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8671
				if (tcp->tcp_ka_last_intrvl != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8672
					/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8673
					 * We should probe again at least
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8674
					 * in ka_intrvl, but not more than
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8675
					 * tcp_rexmit_interval_max.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8676
					 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8677
					firetime = MIN(ka_intrvl - 1,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8678
					    tcp->tcp_ka_last_intrvl << 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8679
					if (firetime > tcp_rexmit_interval_max)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8680
						firetime =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8681
						    tcp_rexmit_interval_max;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8682
				} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8683
					firetime = tcp->tcp_rto;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8684
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8685
				tcp->tcp_ka_tid = TCP_TIMER(tcp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8686
				    tcp_keepalive_killer,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8687
				    MSEC_TO_TICK(firetime));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8688
				tcp->tcp_ka_last_intrvl = firetime;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8689
				return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8690
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8691
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8692
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8693
		tcp->tcp_ka_last_intrvl = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8694
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8695
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8696
	/* firetime can be negative if (mp1 == NULL || mp == NULL) */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8697
	if ((firetime = ka_intrvl - idletime) < 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8698
		firetime = ka_intrvl;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8699
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8700
	tcp->tcp_ka_tid = TCP_TIMER(tcp, tcp_keepalive_killer,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8701
	    MSEC_TO_TICK(firetime));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8702
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8703
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  8704
int
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8705
tcp_maxpsz_set(tcp_t *tcp, boolean_t set_maxblk)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8706
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8707
	queue_t	*q = tcp->tcp_rq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8708
	int32_t	mss = tcp->tcp_mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8709
	int	maxpsz;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8710
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8711
	if (TCP_IS_DETACHED(tcp))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8712
		return (mss);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8713
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  8714
	if (tcp->tcp_fused) {
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  8715
		maxpsz = tcp_fuse_maxpsz_set(tcp);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  8716
		mss = INFPSZ;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  8717
	} else if (tcp->tcp_mdt || tcp->tcp_maxpsz == 0) {
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8718
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8719
		 * Set the sd_qn_maxpsz according to the socket send buffer
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8720
		 * size, and sd_maxblk to INFPSZ (-1).  This will essentially
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8721
		 * instruct the stream head to copyin user data into contiguous
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8722
		 * kernel-allocated buffers without breaking it up into smaller
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8723
		 * chunks.  We round up the buffer size to the nearest SMSS.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8724
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8725
		maxpsz = MSS_ROUNDUP(tcp->tcp_xmit_hiwater, mss);
898
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
  8726
		if (tcp->tcp_kssl_ctx == NULL)
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
  8727
			mss = INFPSZ;
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
  8728
		else
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
  8729
			mss = SSL3_MAX_RECORD_LEN;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8730
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8731
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8732
		 * Set sd_qn_maxpsz to approx half the (receivers) buffer
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8733
		 * (and a multiple of the mss).  This instructs the stream
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8734
		 * head to break down larger than SMSS writes into SMSS-
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8735
		 * size mblks, up to tcp_maxpsz_multiplier mblks at a time.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8736
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8737
		maxpsz = tcp->tcp_maxpsz * mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8738
		if (maxpsz > tcp->tcp_xmit_hiwater/2) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8739
			maxpsz = tcp->tcp_xmit_hiwater/2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8740
			/* Round up to nearest mss */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8741
			maxpsz = MSS_ROUNDUP(maxpsz, mss);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8742
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8743
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8744
	(void) setmaxps(q, maxpsz);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8745
	tcp->tcp_wq->q_maxpsz = maxpsz;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8746
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8747
	if (set_maxblk)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8748
		(void) mi_set_sth_maxblk(q, mss);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8749
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8750
	return (mss);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8751
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8752
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8753
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8754
 * Extract option values from a tcp header.  We put any found values into the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8755
 * tcpopt struct and return a bitmask saying which options were found.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8756
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8757
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8758
tcp_parse_options(tcph_t *tcph, tcp_opt_t *tcpopt)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8759
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8760
	uchar_t		*endp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8761
	int		len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8762
	uint32_t	mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8763
	uchar_t		*up = (uchar_t *)tcph;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8764
	int		found = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8765
	int32_t		sack_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8766
	tcp_seq		sack_begin, sack_end;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8767
	tcp_t		*tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8768
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8769
	endp = up + TCP_HDR_LENGTH(tcph);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8770
	up += TCP_MIN_HEADER_LENGTH;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8771
	while (up < endp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8772
		len = endp - up;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8773
		switch (*up) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8774
		case TCPOPT_EOL:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8775
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8776
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8777
		case TCPOPT_NOP:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8778
			up++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8779
			continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8780
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8781
		case TCPOPT_MAXSEG:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8782
			if (len < TCPOPT_MAXSEG_LEN ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8783
			    up[1] != TCPOPT_MAXSEG_LEN)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8784
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8785
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8786
			mss = BE16_TO_U16(up+2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8787
			/* Caller must handle tcp_mss_min and tcp_mss_max_* */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8788
			tcpopt->tcp_opt_mss = mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8789
			found |= TCP_OPT_MSS_PRESENT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8790
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8791
			up += TCPOPT_MAXSEG_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8792
			continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8793
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8794
		case TCPOPT_WSCALE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8795
			if (len < TCPOPT_WS_LEN || up[1] != TCPOPT_WS_LEN)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8796
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8797
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8798
			if (up[2] > TCP_MAX_WINSHIFT)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8799
				tcpopt->tcp_opt_wscale = TCP_MAX_WINSHIFT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8800
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8801
				tcpopt->tcp_opt_wscale = up[2];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8802
			found |= TCP_OPT_WSCALE_PRESENT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8803
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8804
			up += TCPOPT_WS_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8805
			continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8806
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8807
		case TCPOPT_SACK_PERMITTED:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8808
			if (len < TCPOPT_SACK_OK_LEN ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8809
			    up[1] != TCPOPT_SACK_OK_LEN)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8810
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8811
			found |= TCP_OPT_SACK_OK_PRESENT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8812
			up += TCPOPT_SACK_OK_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8813
			continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8814
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8815
		case TCPOPT_SACK:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8816
			if (len <= 2 || up[1] <= 2 || len < up[1])
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8817
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8818
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8819
			/* If TCP is not interested in SACK blks... */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8820
			if ((tcp = tcpopt->tcp) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8821
				up += up[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8822
				continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8823
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8824
			sack_len = up[1] - TCPOPT_HEADER_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8825
			up += TCPOPT_HEADER_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8826
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8827
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8828
			 * If the list is empty, allocate one and assume
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8829
			 * nothing is sack'ed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8830
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8831
			ASSERT(tcp->tcp_sack_info != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8832
			if (tcp->tcp_notsack_list == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8833
				tcp_notsack_update(&(tcp->tcp_notsack_list),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8834
				    tcp->tcp_suna, tcp->tcp_snxt,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8835
				    &(tcp->tcp_num_notsack_blk),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8836
				    &(tcp->tcp_cnt_notsack_list));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8837
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8838
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8839
				 * Make sure tcp_notsack_list is not NULL.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8840
				 * This happens when kmem_alloc(KM_NOSLEEP)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8841
				 * returns NULL.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8842
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8843
				if (tcp->tcp_notsack_list == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8844
					up += sack_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8845
					continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8846
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8847
				tcp->tcp_fack = tcp->tcp_suna;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8848
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8849
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8850
			while (sack_len > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8851
				if (up + 8 > endp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8852
					up = endp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8853
					break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8854
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8855
				sack_begin = BE32_TO_U32(up);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8856
				up += 4;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8857
				sack_end = BE32_TO_U32(up);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8858
				up += 4;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8859
				sack_len -= 8;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8860
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8861
				 * Bounds checking.  Make sure the SACK
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8862
				 * info is within tcp_suna and tcp_snxt.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8863
				 * If this SACK blk is out of bound, ignore
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8864
				 * it but continue to parse the following
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8865
				 * blks.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8866
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8867
				if (SEQ_LEQ(sack_end, sack_begin) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8868
				    SEQ_LT(sack_begin, tcp->tcp_suna) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8869
				    SEQ_GT(sack_end, tcp->tcp_snxt)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8870
					continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8871
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8872
				tcp_notsack_insert(&(tcp->tcp_notsack_list),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8873
				    sack_begin, sack_end,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8874
				    &(tcp->tcp_num_notsack_blk),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8875
				    &(tcp->tcp_cnt_notsack_list));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8876
				if (SEQ_GT(sack_end, tcp->tcp_fack)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8877
					tcp->tcp_fack = sack_end;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8878
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8879
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8880
			found |= TCP_OPT_SACK_PRESENT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8881
			continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8882
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8883
		case TCPOPT_TSTAMP:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8884
			if (len < TCPOPT_TSTAMP_LEN ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8885
			    up[1] != TCPOPT_TSTAMP_LEN)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8886
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8887
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8888
			tcpopt->tcp_opt_ts_val = BE32_TO_U32(up+2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8889
			tcpopt->tcp_opt_ts_ecr = BE32_TO_U32(up+6);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8890
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8891
			found |= TCP_OPT_TSTAMP_PRESENT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8892
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8893
			up += TCPOPT_TSTAMP_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8894
			continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8895
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8896
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8897
			if (len <= 1 || len < (int)up[1] || up[1] == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8898
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8899
			up += up[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8900
			continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8901
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8902
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8903
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8904
	return (found);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8905
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8906
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8907
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8908
 * Set the mss associated with a particular tcp based on its current value,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8909
 * and a new one passed in. Observe minimums and maximums, and reset
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8910
 * other state variables that we want to view as multiples of mss.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8911
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8912
 * This function is called in various places mainly because
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8913
 * 1) Various stuffs, tcp_mss, tcp_cwnd, ... need to be adjusted when the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8914
 *    other side's SYN/SYN-ACK packet arrives.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8915
 * 2) PMTUd may get us a new MSS.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8916
 * 3) If the other side stops sending us timestamp option, we need to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8917
 *    increase the MSS size to use the extra bytes available.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8918
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8919
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8920
tcp_mss_set(tcp_t *tcp, uint32_t mss)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8921
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8922
	uint32_t	mss_max;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8923
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8924
	if (tcp->tcp_ipversion == IPV4_VERSION)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8925
		mss_max = tcp_mss_max_ipv4;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8926
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8927
		mss_max = tcp_mss_max_ipv6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8928
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8929
	if (mss < tcp_mss_min)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8930
		mss = tcp_mss_min;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8931
	if (mss > mss_max)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8932
		mss = mss_max;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8933
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8934
	 * Unless naglim has been set by our client to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8935
	 * a non-mss value, force naglim to track mss.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8936
	 * This can help to aggregate small writes.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8937
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8938
	if (mss < tcp->tcp_naglim || tcp->tcp_mss == tcp->tcp_naglim)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8939
		tcp->tcp_naglim = mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8940
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8941
	 * TCP should be able to buffer at least 4 MSS data for obvious
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8942
	 * performance reason.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8943
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8944
	if ((mss << 2) > tcp->tcp_xmit_hiwater)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8945
		tcp->tcp_xmit_hiwater = mss << 2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8946
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8947
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8948
	 * Check if we need to apply the tcp_init_cwnd here.  If
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8949
	 * it is set and the MSS gets bigger (should not happen
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8950
	 * normally), we need to adjust the resulting tcp_cwnd properly.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8951
	 * The new tcp_cwnd should not get bigger.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8952
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8953
	if (tcp->tcp_init_cwnd == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8954
		tcp->tcp_cwnd = MIN(tcp_slow_start_initial * mss,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8955
		    MIN(4 * mss, MAX(2 * mss, 4380 / mss * mss)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8956
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8957
		if (tcp->tcp_mss < mss) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8958
			tcp->tcp_cwnd = MAX(1,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8959
			    (tcp->tcp_init_cwnd * tcp->tcp_mss / mss)) * mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8960
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8961
			tcp->tcp_cwnd = tcp->tcp_init_cwnd * mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8962
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8963
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8964
	tcp->tcp_mss = mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8965
	tcp->tcp_cwnd_cnt = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8966
	(void) tcp_maxpsz_set(tcp, B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8967
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8968
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8969
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8970
tcp_open(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *credp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8971
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8972
	tcp_t		*tcp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8973
	conn_t		*connp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8974
	int		err;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8975
	dev_t		conn_dev;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8976
	zoneid_t	zoneid = getzoneid();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8977
766
c521de78a32f PSARC 2005/474 Zones Upgrade (Ashanti and Zulu)
carlsonj
parents: 741
diff changeset
  8978
	/*
c521de78a32f PSARC 2005/474 Zones Upgrade (Ashanti and Zulu)
carlsonj
parents: 741
diff changeset
  8979
	 * Special case for install: miniroot needs to be able to access files
c521de78a32f PSARC 2005/474 Zones Upgrade (Ashanti and Zulu)
carlsonj
parents: 741
diff changeset
  8980
	 * via NFS as though it were always in the global zone.
c521de78a32f PSARC 2005/474 Zones Upgrade (Ashanti and Zulu)
carlsonj
parents: 741
diff changeset
  8981
	 */
c521de78a32f PSARC 2005/474 Zones Upgrade (Ashanti and Zulu)
carlsonj
parents: 741
diff changeset
  8982
	if (credp == kcred && nfs_global_client_only != 0)
c521de78a32f PSARC 2005/474 Zones Upgrade (Ashanti and Zulu)
carlsonj
parents: 741
diff changeset
  8983
		zoneid = GLOBAL_ZONEID;
c521de78a32f PSARC 2005/474 Zones Upgrade (Ashanti and Zulu)
carlsonj
parents: 741
diff changeset
  8984
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8985
	if (q->q_ptr != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8986
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8987
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8988
	if (sflag == MODOPEN) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8989
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8990
		 * This is a special case. The purpose of a modopen
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8991
		 * is to allow just the T_SVR4_OPTMGMT_REQ to pass
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8992
		 * through for MIB browsers. Everything else is failed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8993
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8994
		connp = (conn_t *)tcp_get_conn(IP_SQUEUE_GET(lbolt));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8995
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8996
		if (connp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8997
			return (ENOMEM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8998
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8999
		connp->conn_flags |= IPCL_TCPMOD;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9000
		connp->conn_cred = credp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9001
		connp->conn_zoneid = zoneid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9002
		q->q_ptr = WR(q)->q_ptr = connp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9003
		crhold(credp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9004
		q->q_qinfo = &tcp_mod_rinit;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9005
		WR(q)->q_qinfo = &tcp_mod_winit;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9006
		qprocson(q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9007
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9008
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9009
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9010
	if ((conn_dev = inet_minor_alloc(ip_minor_arena)) == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9011
		return (EBUSY);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9012
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9013
	*devp = makedevice(getemajor(*devp), (minor_t)conn_dev);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9014
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9015
	if (flag & SO_ACCEPTOR) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9016
		q->q_qinfo = &tcp_acceptor_rinit;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9017
		q->q_ptr = (void *)conn_dev;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9018
		WR(q)->q_qinfo = &tcp_acceptor_winit;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9019
		WR(q)->q_ptr = (void *)conn_dev;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9020
		qprocson(q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9021
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9022
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9023
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9024
	connp = (conn_t *)tcp_get_conn(IP_SQUEUE_GET(lbolt));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9025
	if (connp == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9026
		inet_minor_free(ip_minor_arena, conn_dev);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9027
		q->q_ptr = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9028
		return (ENOSR);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9029
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9030
	connp->conn_sqp = IP_SQUEUE_GET(lbolt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9031
	tcp = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9032
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9033
	q->q_ptr = WR(q)->q_ptr = connp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9034
	if (getmajor(*devp) == TCP6_MAJ) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9035
		connp->conn_flags |= (IPCL_TCP6|IPCL_ISV6);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9036
		connp->conn_send = ip_output_v6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9037
		connp->conn_af_isv6 = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9038
		connp->conn_pkt_isv6 = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9039
		connp->conn_src_preferences = IPV6_PREFER_SRC_DEFAULT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9040
		tcp->tcp_ipversion = IPV6_VERSION;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9041
		tcp->tcp_family = AF_INET6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9042
		tcp->tcp_mss = tcp_mss_def_ipv6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9043
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9044
		connp->conn_flags |= IPCL_TCP4;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9045
		connp->conn_send = ip_output;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9046
		connp->conn_af_isv6 = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9047
		connp->conn_pkt_isv6 = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9048
		tcp->tcp_ipversion = IPV4_VERSION;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9049
		tcp->tcp_family = AF_INET;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9050
		tcp->tcp_mss = tcp_mss_def_ipv4;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9051
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9052
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9053
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9054
	 * TCP keeps a copy of cred for cache locality reasons but
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9055
	 * we put a reference only once. If connp->conn_cred
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9056
	 * becomes invalid, tcp_cred should also be set to NULL.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9057
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9058
	tcp->tcp_cred = connp->conn_cred = credp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9059
	crhold(connp->conn_cred);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9060
	tcp->tcp_cpid = curproc->p_pid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9061
	connp->conn_zoneid = zoneid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9062
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9063
	connp->conn_dev = conn_dev;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9064
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9065
	ASSERT(q->q_qinfo == &tcp_rinit);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9066
	ASSERT(WR(q)->q_qinfo == &tcp_winit);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9067
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9068
	if (flag & SO_SOCKSTR) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9069
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9070
		 * No need to insert a socket in tcp acceptor hash.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9071
		 * If it was a socket acceptor stream, we dealt with
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9072
		 * it above. A socket listener can never accept a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9073
		 * connection and doesn't need acceptor_id.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9074
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9075
		connp->conn_flags |= IPCL_SOCKET;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9076
		tcp->tcp_issocket = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9077
		WR(q)->q_qinfo = &tcp_sock_winit;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9078
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9079
#ifdef	_ILP32
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9080
		tcp->tcp_acceptor_id = (t_uscalar_t)RD(q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9081
#else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9082
		tcp->tcp_acceptor_id = conn_dev;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9083
#endif	/* _ILP32 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9084
		tcp_acceptor_hash_insert(tcp->tcp_acceptor_id, tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9085
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9086
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9087
	if (tcp_trace)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9088
		tcp->tcp_tracebuf = kmem_zalloc(sizeof (tcptrch_t), KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9089
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9090
	err = tcp_init(tcp, q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9091
	if (err != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9092
		inet_minor_free(ip_minor_arena, connp->conn_dev);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9093
		tcp_acceptor_hash_remove(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9094
		CONN_DEC_REF(connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9095
		q->q_ptr = WR(q)->q_ptr = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9096
		return (err);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9097
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9098
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9099
	RD(q)->q_hiwat = tcp_recv_hiwat;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9100
	tcp->tcp_rwnd = tcp_recv_hiwat;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9101
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9102
	/* Non-zero default values */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9103
	connp->conn_multicast_loop = IP_DEFAULT_MULTICAST_LOOP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9104
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9105
	 * Put the ref for TCP. Ref for IP was already put
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9106
	 * by ipcl_conn_create. Also Make the conn_t globally
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9107
	 * visible to walkers
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9108
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9109
	mutex_enter(&connp->conn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9110
	CONN_INC_REF_LOCKED(connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9111
	ASSERT(connp->conn_ref == 2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9112
	connp->conn_state_flags &= ~CONN_INCIPIENT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9113
	mutex_exit(&connp->conn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9114
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9115
	qprocson(q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9116
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9117
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9118
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9119
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9120
 * Some TCP options can be "set" by requesting them in the option
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9121
 * buffer. This is needed for XTI feature test though we do not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9122
 * allow it in general. We interpret that this mechanism is more
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9123
 * applicable to OSI protocols and need not be allowed in general.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9124
 * This routine filters out options for which it is not allowed (most)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9125
 * and lets through those (few) for which it is. [ The XTI interface
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9126
 * test suite specifics will imply that any XTI_GENERIC level XTI_* if
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9127
 * ever implemented will have to be allowed here ].
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9128
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9129
static boolean_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9130
tcp_allow_connopt_set(int level, int name)
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
	switch (level) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9134
	case IPPROTO_TCP:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9135
		switch (name) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9136
		case TCP_NODELAY:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9137
			return (B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9138
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9139
			return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9140
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9141
		/*NOTREACHED*/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9142
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9143
		return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9144
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9145
	/*NOTREACHED*/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9146
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9147
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9148
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9149
 * This routine gets default values of certain options whose default
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9150
 * values are maintained by protocol specific code
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9151
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9152
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9153
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9154
tcp_opt_default(queue_t *q, int level, int name, uchar_t *ptr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9155
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9156
	int32_t	*i1 = (int32_t *)ptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9157
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9158
	switch (level) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9159
	case IPPROTO_TCP:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9160
		switch (name) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9161
		case TCP_NOTIFY_THRESHOLD:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9162
			*i1 = tcp_ip_notify_interval;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9163
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9164
		case TCP_ABORT_THRESHOLD:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9165
			*i1 = tcp_ip_abort_interval;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9166
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9167
		case TCP_CONN_NOTIFY_THRESHOLD:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9168
			*i1 = tcp_ip_notify_cinterval;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9169
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9170
		case TCP_CONN_ABORT_THRESHOLD:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9171
			*i1 = tcp_ip_abort_cinterval;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9172
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9173
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9174
			return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9175
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9176
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9177
	case IPPROTO_IP:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9178
		switch (name) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9179
		case IP_TTL:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9180
			*i1 = tcp_ipv4_ttl;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9181
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9182
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9183
			return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9184
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9185
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9186
	case IPPROTO_IPV6:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9187
		switch (name) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9188
		case IPV6_UNICAST_HOPS:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9189
			*i1 = tcp_ipv6_hoplimit;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9190
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9191
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9192
			return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9193
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9194
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9195
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9196
		return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9197
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9198
	return (sizeof (int));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9199
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9200
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9201
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9202
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9203
 * TCP routine to get the values of options.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9204
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9205
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9206
tcp_opt_get(queue_t *q, int level, int	name, uchar_t *ptr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9207
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9208
	int		*i1 = (int *)ptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9209
	conn_t		*connp = Q_TO_CONN(q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9210
	tcp_t		*tcp = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9211
	ip6_pkt_t	*ipp = &tcp->tcp_sticky_ipp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9212
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9213
	switch (level) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9214
	case SOL_SOCKET:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9215
		switch (name) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9216
		case SO_LINGER:	{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9217
			struct linger *lgr = (struct linger *)ptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9218
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9219
			lgr->l_onoff = tcp->tcp_linger ? SO_LINGER : 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9220
			lgr->l_linger = tcp->tcp_lingertime;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9221
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9222
			return (sizeof (struct linger));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9223
		case SO_DEBUG:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9224
			*i1 = tcp->tcp_debug ? SO_DEBUG : 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9225
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9226
		case SO_KEEPALIVE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9227
			*i1 = tcp->tcp_ka_enabled ? SO_KEEPALIVE : 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9228
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9229
		case SO_DONTROUTE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9230
			*i1 = tcp->tcp_dontroute ? SO_DONTROUTE : 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9231
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9232
		case SO_USELOOPBACK:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9233
			*i1 = tcp->tcp_useloopback ? SO_USELOOPBACK : 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9234
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9235
		case SO_BROADCAST:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9236
			*i1 = tcp->tcp_broadcast ? SO_BROADCAST : 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9237
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9238
		case SO_REUSEADDR:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9239
			*i1 = tcp->tcp_reuseaddr ? SO_REUSEADDR : 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9240
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9241
		case SO_OOBINLINE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9242
			*i1 = tcp->tcp_oobinline ? SO_OOBINLINE : 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9243
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9244
		case SO_DGRAM_ERRIND:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9245
			*i1 = tcp->tcp_dgram_errind ? SO_DGRAM_ERRIND : 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9246
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9247
		case SO_TYPE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9248
			*i1 = SOCK_STREAM;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9249
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9250
		case SO_SNDBUF:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9251
			*i1 = tcp->tcp_xmit_hiwater;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9252
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9253
		case SO_RCVBUF:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9254
			*i1 = RD(q)->q_hiwat;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9255
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9256
		case SO_SND_COPYAVOID:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9257
			*i1 = tcp->tcp_snd_zcopy_on ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9258
			    SO_SND_COPYAVOID : 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9259
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9260
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9261
			return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9262
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9263
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9264
	case IPPROTO_TCP:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9265
		switch (name) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9266
		case TCP_NODELAY:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9267
			*i1 = (tcp->tcp_naglim == 1) ? TCP_NODELAY : 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9268
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9269
		case TCP_MAXSEG:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9270
			*i1 = tcp->tcp_mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9271
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9272
		case TCP_NOTIFY_THRESHOLD:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9273
			*i1 = (int)tcp->tcp_first_timer_threshold;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9274
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9275
		case TCP_ABORT_THRESHOLD:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9276
			*i1 = tcp->tcp_second_timer_threshold;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9277
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9278
		case TCP_CONN_NOTIFY_THRESHOLD:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9279
			*i1 = tcp->tcp_first_ctimer_threshold;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9280
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9281
		case TCP_CONN_ABORT_THRESHOLD:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9282
			*i1 = tcp->tcp_second_ctimer_threshold;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9283
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9284
		case TCP_RECVDSTADDR:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9285
			*i1 = tcp->tcp_recvdstaddr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9286
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9287
		case TCP_ANONPRIVBIND:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9288
			*i1 = tcp->tcp_anon_priv_bind;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9289
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9290
		case TCP_EXCLBIND:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9291
			*i1 = tcp->tcp_exclbind ? TCP_EXCLBIND : 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9292
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9293
		case TCP_INIT_CWND:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9294
			*i1 = tcp->tcp_init_cwnd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9295
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9296
		case TCP_KEEPALIVE_THRESHOLD:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9297
			*i1 = tcp->tcp_ka_interval;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9298
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9299
		case TCP_KEEPALIVE_ABORT_THRESHOLD:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9300
			*i1 = tcp->tcp_ka_abort_thres;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9301
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9302
		case TCP_CORK:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9303
			*i1 = tcp->tcp_cork;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9304
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9305
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9306
			return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9307
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9308
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9309
	case IPPROTO_IP:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9310
		if (tcp->tcp_family != AF_INET)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9311
			return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9312
		switch (name) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9313
		case IP_OPTIONS:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9314
		case T_IP_OPTIONS: {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9315
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9316
			 * This is compatible with BSD in that in only return
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9317
			 * the reverse source route with the final destination
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9318
			 * as the last entry. The first 4 bytes of the option
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9319
			 * will contain the final destination.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9320
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9321
			char	*opt_ptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9322
			int	opt_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9323
			opt_ptr = (char *)tcp->tcp_ipha + IP_SIMPLE_HDR_LENGTH;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9324
			opt_len = (char *)tcp->tcp_tcph - opt_ptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9325
			/* Caller ensures enough space */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9326
			if (opt_len > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9327
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9328
				 * TODO: Do we have to handle getsockopt on an
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9329
				 * initiator as well?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9330
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9331
				return (tcp_opt_get_user(tcp->tcp_ipha, ptr));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9332
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9333
			return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9334
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9335
		case IP_TOS:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9336
		case T_IP_TOS:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9337
			*i1 = (int)tcp->tcp_ipha->ipha_type_of_service;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9338
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9339
		case IP_TTL:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9340
			*i1 = (int)tcp->tcp_ipha->ipha_ttl;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9341
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9342
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9343
			return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9344
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9345
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9346
	case IPPROTO_IPV6:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9347
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9348
		 * IPPROTO_IPV6 options are only supported for sockets
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9349
		 * that are using IPv6 on the wire.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9350
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9351
		if (tcp->tcp_ipversion != IPV6_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9352
			return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9353
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9354
		switch (name) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9355
		case IPV6_UNICAST_HOPS:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9356
			*i1 = (unsigned int) tcp->tcp_ip6h->ip6_hops;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9357
			break;	/* goto sizeof (int) option return */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9358
		case IPV6_BOUND_IF:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9359
			/* Zero if not set */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9360
			*i1 = tcp->tcp_bound_if;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9361
			break;	/* goto sizeof (int) option return */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9362
		case IPV6_RECVPKTINFO:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9363
			if (tcp->tcp_ipv6_recvancillary & TCP_IPV6_RECVPKTINFO)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9364
				*i1 = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9365
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9366
				*i1 = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9367
			break;	/* goto sizeof (int) option return */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9368
		case IPV6_RECVTCLASS:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9369
			if (tcp->tcp_ipv6_recvancillary & TCP_IPV6_RECVTCLASS)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9370
				*i1 = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9371
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9372
				*i1 = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9373
			break;	/* goto sizeof (int) option return */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9374
		case IPV6_RECVHOPLIMIT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9375
			if (tcp->tcp_ipv6_recvancillary &
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9376
			    TCP_IPV6_RECVHOPLIMIT)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9377
				*i1 = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9378
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9379
				*i1 = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9380
			break;	/* goto sizeof (int) option return */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9381
		case IPV6_RECVHOPOPTS:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9382
			if (tcp->tcp_ipv6_recvancillary & TCP_IPV6_RECVHOPOPTS)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9383
				*i1 = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9384
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9385
				*i1 = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9386
			break;	/* goto sizeof (int) option return */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9387
		case IPV6_RECVDSTOPTS:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9388
			if (tcp->tcp_ipv6_recvancillary & TCP_IPV6_RECVDSTOPTS)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9389
				*i1 = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9390
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9391
				*i1 = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9392
			break;	/* goto sizeof (int) option return */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9393
		case _OLD_IPV6_RECVDSTOPTS:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9394
			if (tcp->tcp_ipv6_recvancillary &
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9395
			    TCP_OLD_IPV6_RECVDSTOPTS)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9396
				*i1 = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9397
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9398
				*i1 = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9399
			break;	/* goto sizeof (int) option return */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9400
		case IPV6_RECVRTHDR:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9401
			if (tcp->tcp_ipv6_recvancillary & TCP_IPV6_RECVRTHDR)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9402
				*i1 = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9403
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9404
				*i1 = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9405
			break;	/* goto sizeof (int) option return */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9406
		case IPV6_RECVRTHDRDSTOPTS:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9407
			if (tcp->tcp_ipv6_recvancillary &
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9408
			    TCP_IPV6_RECVRTDSTOPTS)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9409
				*i1 = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9410
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9411
				*i1 = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9412
			break;	/* goto sizeof (int) option return */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9413
		case IPV6_PKTINFO: {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9414
			/* XXX assumes that caller has room for max size! */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9415
			struct in6_pktinfo *pkti;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9416
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9417
			pkti = (struct in6_pktinfo *)ptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9418
			if (ipp->ipp_fields & IPPF_IFINDEX)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9419
				pkti->ipi6_ifindex = ipp->ipp_ifindex;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9420
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9421
				pkti->ipi6_ifindex = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9422
			if (ipp->ipp_fields & IPPF_ADDR)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9423
				pkti->ipi6_addr = ipp->ipp_addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9424
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9425
				pkti->ipi6_addr = ipv6_all_zeros;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9426
			return (sizeof (struct in6_pktinfo));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9427
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9428
		case IPV6_TCLASS:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9429
			if (ipp->ipp_fields & IPPF_TCLASS)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9430
				*i1 = ipp->ipp_tclass;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9431
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9432
				*i1 = IPV6_FLOW_TCLASS(
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9433
				    IPV6_DEFAULT_VERS_AND_FLOW);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9434
			break;	/* goto sizeof (int) option return */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9435
		case IPV6_NEXTHOP: {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9436
			sin6_t *sin6 = (sin6_t *)ptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9437
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9438
			if (!(ipp->ipp_fields & IPPF_NEXTHOP))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9439
				return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9440
			*sin6 = sin6_null;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9441
			sin6->sin6_family = AF_INET6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9442
			sin6->sin6_addr = ipp->ipp_nexthop;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9443
			return (sizeof (sin6_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9444
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9445
		case IPV6_HOPOPTS:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9446
			if (!(ipp->ipp_fields & IPPF_HOPOPTS))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9447
				return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9448
			bcopy(ipp->ipp_hopopts, ptr, ipp->ipp_hopoptslen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9449
			return (ipp->ipp_hopoptslen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9450
		case IPV6_RTHDRDSTOPTS:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9451
			if (!(ipp->ipp_fields & IPPF_RTDSTOPTS))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9452
				return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9453
			bcopy(ipp->ipp_rtdstopts, ptr, ipp->ipp_rtdstoptslen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9454
			return (ipp->ipp_rtdstoptslen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9455
		case IPV6_RTHDR:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9456
			if (!(ipp->ipp_fields & IPPF_RTHDR))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9457
				return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9458
			bcopy(ipp->ipp_rthdr, ptr, ipp->ipp_rthdrlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9459
			return (ipp->ipp_rthdrlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9460
		case IPV6_DSTOPTS:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9461
			if (!(ipp->ipp_fields & IPPF_DSTOPTS))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9462
				return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9463
			bcopy(ipp->ipp_dstopts, ptr, ipp->ipp_dstoptslen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9464
			return (ipp->ipp_dstoptslen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9465
		case IPV6_SRC_PREFERENCES:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9466
			return (ip6_get_src_preferences(connp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9467
			    (uint32_t *)ptr));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9468
		case IPV6_PATHMTU: {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9469
			struct ip6_mtuinfo *mtuinfo = (struct ip6_mtuinfo *)ptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9470
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9471
			if (tcp->tcp_state < TCPS_ESTABLISHED)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9472
				return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9473
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9474
			return (ip_fill_mtuinfo(&connp->conn_remv6,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9475
				connp->conn_fport, mtuinfo));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9476
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9477
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9478
			return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9479
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9480
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9481
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9482
		return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9483
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9484
	return (sizeof (int));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9485
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9486
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9487
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9488
 * We declare as 'int' rather than 'void' to satisfy pfi_t arg requirements.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9489
 * Parameters are assumed to be verified by the caller.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9490
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9491
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9492
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9493
tcp_opt_set(queue_t *q, uint_t optset_context, int level, int name,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9494
    uint_t inlen, uchar_t *invalp, uint_t *outlenp, uchar_t *outvalp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9495
    void *thisdg_attrs, cred_t *cr, mblk_t *mblk)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9496
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9497
	tcp_t	*tcp = Q_TO_TCP(q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9498
	int	*i1 = (int *)invalp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9499
	boolean_t onoff = (*i1 == 0) ? 0 : 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9500
	boolean_t checkonly;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9501
	int	reterr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9502
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9503
	switch (optset_context) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9504
	case SETFN_OPTCOM_CHECKONLY:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9505
		checkonly = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9506
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9507
		 * Note: Implies T_CHECK semantics for T_OPTCOM_REQ
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9508
		 * inlen != 0 implies value supplied and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9509
		 * 	we have to "pretend" to set it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9510
		 * inlen == 0 implies that there is no
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9511
		 * 	value part in T_CHECK request and just validation
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9512
		 * done elsewhere should be enough, we just return here.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9513
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9514
		if (inlen == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9515
			*outlenp = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9516
			return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9517
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9518
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9519
	case SETFN_OPTCOM_NEGOTIATE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9520
		checkonly = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9521
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9522
	case SETFN_UD_NEGOTIATE: /* error on conn-oriented transports ? */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9523
	case SETFN_CONN_NEGOTIATE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9524
		checkonly = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9525
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9526
		 * Negotiating local and "association-related" options
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9527
		 * from other (T_CONN_REQ, T_CONN_RES,T_UNITDATA_REQ)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9528
		 * primitives is allowed by XTI, but we choose
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9529
		 * to not implement this style negotiation for Internet
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9530
		 * protocols (We interpret it is a must for OSI world but
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9531
		 * optional for Internet protocols) for all options.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9532
		 * [ Will do only for the few options that enable test
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9533
		 * suites that our XTI implementation of this feature
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9534
		 * works for transports that do allow it ]
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9535
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9536
		if (!tcp_allow_connopt_set(level, name)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9537
			*outlenp = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9538
			return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9539
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9540
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9541
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9542
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9543
		 * We should never get here
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9544
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9545
		*outlenp = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9546
		return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9547
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9548
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9549
	ASSERT((optset_context != SETFN_OPTCOM_CHECKONLY) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9550
	    (optset_context == SETFN_OPTCOM_CHECKONLY && inlen != 0));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9551
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9552
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9553
	 * For TCP, we should have no ancillary data sent down
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9554
	 * (sendmsg isn't supported for SOCK_STREAM), so thisdg_attrs
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9555
	 * has to be zero.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9556
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9557
	ASSERT(thisdg_attrs == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9558
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9559
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9560
	 * For fixed length options, no sanity check
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9561
	 * of passed in length is done. It is assumed *_optcom_req()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9562
	 * routines do the right thing.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9563
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9564
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9565
	switch (level) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9566
	case SOL_SOCKET:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9567
		switch (name) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9568
		case SO_LINGER: {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9569
			struct linger *lgr = (struct linger *)invalp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9570
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9571
			if (!checkonly) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9572
				if (lgr->l_onoff) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9573
					tcp->tcp_linger = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9574
					tcp->tcp_lingertime = lgr->l_linger;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9575
				} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9576
					tcp->tcp_linger = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9577
					tcp->tcp_lingertime = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9578
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9579
				/* struct copy */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9580
				*(struct linger *)outvalp = *lgr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9581
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9582
				if (!lgr->l_onoff) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9583
				    ((struct linger *)outvalp)->l_onoff = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9584
				    ((struct linger *)outvalp)->l_linger = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9585
				} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9586
				    /* struct copy */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9587
				    *(struct linger *)outvalp = *lgr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9588
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9589
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9590
			*outlenp = sizeof (struct linger);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9591
			return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9592
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9593
		case SO_DEBUG:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9594
			if (!checkonly)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9595
				tcp->tcp_debug = onoff;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9596
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9597
		case SO_KEEPALIVE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9598
			if (checkonly) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9599
				/* T_CHECK case */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9600
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9601
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9602
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9603
			if (!onoff) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9604
				if (tcp->tcp_ka_enabled) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9605
					if (tcp->tcp_ka_tid != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9606
						(void) TCP_TIMER_CANCEL(tcp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9607
						    tcp->tcp_ka_tid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9608
						tcp->tcp_ka_tid = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9609
					}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9610
					tcp->tcp_ka_enabled = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9611
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9612
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9613
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9614
			if (!tcp->tcp_ka_enabled) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9615
				/* Crank up the keepalive timer */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9616
				tcp->tcp_ka_last_intrvl = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9617
				tcp->tcp_ka_tid = TCP_TIMER(tcp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9618
				    tcp_keepalive_killer,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9619
				    MSEC_TO_TICK(tcp->tcp_ka_interval));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9620
				tcp->tcp_ka_enabled = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9621
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9622
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9623
		case SO_DONTROUTE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9624
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9625
			 * SO_DONTROUTE, SO_USELOOPBACK and SO_BROADCAST are
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9626
			 * only of interest to IP.  We track them here only so
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9627
			 * that we can report their current value.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9628
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9629
			if (!checkonly) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9630
				tcp->tcp_dontroute = onoff;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9631
				tcp->tcp_connp->conn_dontroute = onoff;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9632
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9633
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9634
		case SO_USELOOPBACK:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9635
			if (!checkonly) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9636
				tcp->tcp_useloopback = onoff;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9637
				tcp->tcp_connp->conn_loopback = onoff;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9638
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9639
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9640
		case SO_BROADCAST:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9641
			if (!checkonly) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9642
				tcp->tcp_broadcast = onoff;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9643
				tcp->tcp_connp->conn_broadcast = onoff;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9644
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9645
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9646
		case SO_REUSEADDR:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9647
			if (!checkonly) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9648
				tcp->tcp_reuseaddr = onoff;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9649
				tcp->tcp_connp->conn_reuseaddr = onoff;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9650
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9651
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9652
		case SO_OOBINLINE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9653
			if (!checkonly)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9654
				tcp->tcp_oobinline = onoff;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9655
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9656
		case SO_DGRAM_ERRIND:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9657
			if (!checkonly)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9658
				tcp->tcp_dgram_errind = onoff;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9659
			break;
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  9660
		case SO_SNDBUF: {
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  9661
			tcp_t *peer_tcp;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  9662
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9663
			if (*i1 > tcp_max_buf) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9664
				*outlenp = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9665
				return (ENOBUFS);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9666
			}
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  9667
			if (checkonly)
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  9668
				break;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  9669
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  9670
			tcp->tcp_xmit_hiwater = *i1;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  9671
			if (tcp_snd_lowat_fraction != 0)
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  9672
				tcp->tcp_xmit_lowater =
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  9673
				    tcp->tcp_xmit_hiwater /
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  9674
				    tcp_snd_lowat_fraction;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  9675
			(void) tcp_maxpsz_set(tcp, B_TRUE);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  9676
			/*
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  9677
			 * If we are flow-controlled, recheck the condition.
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  9678
			 * There are apps that increase SO_SNDBUF size when
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  9679
			 * flow-controlled (EWOULDBLOCK), and expect the flow
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  9680
			 * control condition to be lifted right away.
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  9681
			 *
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  9682
			 * For the fused tcp loopback case, in order to avoid
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  9683
			 * 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
  9684
			 * hold its fuse_lock while accessing tcp_flow_stopped.
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  9685
			 */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  9686
			peer_tcp = tcp->tcp_loopback_peer;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  9687
			ASSERT(!tcp->tcp_fused || peer_tcp != NULL);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  9688
			if (tcp->tcp_fused)
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  9689
				mutex_enter(&peer_tcp->tcp_fuse_lock);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  9690
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  9691
			if (tcp->tcp_flow_stopped &&
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  9692
			    TCP_UNSENT_BYTES(tcp) < tcp->tcp_xmit_hiwater) {
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  9693
				tcp_clrqfull(tcp);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  9694
			}
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  9695
			if (tcp->tcp_fused)
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  9696
				mutex_exit(&peer_tcp->tcp_fuse_lock);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  9697
			break;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  9698
		}
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9699
		case SO_RCVBUF:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9700
			if (*i1 > tcp_max_buf) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9701
				*outlenp = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9702
				return (ENOBUFS);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9703
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9704
			/* Silently ignore zero */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9705
			if (!checkonly && *i1 != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9706
				*i1 = MSS_ROUNDUP(*i1, tcp->tcp_mss);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9707
				(void) tcp_rwnd_set(tcp, *i1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9708
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9709
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9710
			 * XXX should we return the rwnd here
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9711
			 * and tcp_opt_get ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9712
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9713
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9714
		case SO_SND_COPYAVOID:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9715
			if (!checkonly) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9716
				/* we only allow enable at most once for now */
184
2b3e636dbda4 6294490 snf_segmap hangs on loopback connection
xy158873
parents: 0
diff changeset
  9717
				if (tcp->tcp_loopback ||
2b3e636dbda4 6294490 snf_segmap hangs on loopback connection
xy158873
parents: 0
diff changeset
  9718
				    (!tcp->tcp_snd_zcopy_aware &&
2b3e636dbda4 6294490 snf_segmap hangs on loopback connection
xy158873
parents: 0
diff changeset
  9719
				    (onoff != 1 || !tcp_zcopy_check(tcp)))) {
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9720
					*outlenp = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9721
					return (EOPNOTSUPP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9722
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9723
				tcp->tcp_snd_zcopy_aware = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9724
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9725
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9726
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9727
			*outlenp = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9728
			return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9729
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9730
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9731
	case IPPROTO_TCP:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9732
		switch (name) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9733
		case TCP_NODELAY:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9734
			if (!checkonly)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9735
				tcp->tcp_naglim = *i1 ? 1 : tcp->tcp_mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9736
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9737
		case TCP_NOTIFY_THRESHOLD:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9738
			if (!checkonly)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9739
				tcp->tcp_first_timer_threshold = *i1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9740
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9741
		case TCP_ABORT_THRESHOLD:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9742
			if (!checkonly)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9743
				tcp->tcp_second_timer_threshold = *i1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9744
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9745
		case TCP_CONN_NOTIFY_THRESHOLD:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9746
			if (!checkonly)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9747
				tcp->tcp_first_ctimer_threshold = *i1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9748
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9749
		case TCP_CONN_ABORT_THRESHOLD:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9750
			if (!checkonly)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9751
				tcp->tcp_second_ctimer_threshold = *i1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9752
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9753
		case TCP_RECVDSTADDR:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9754
			if (tcp->tcp_state > TCPS_LISTEN)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9755
				return (EOPNOTSUPP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9756
			if (!checkonly)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9757
				tcp->tcp_recvdstaddr = onoff;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9758
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9759
		case TCP_ANONPRIVBIND:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9760
			if ((reterr = secpolicy_net_privaddr(cr, 0)) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9761
				*outlenp = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9762
				return (reterr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9763
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9764
			if (!checkonly) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9765
				tcp->tcp_anon_priv_bind = onoff;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9766
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9767
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9768
		case TCP_EXCLBIND:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9769
			if (!checkonly)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9770
				tcp->tcp_exclbind = onoff;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9771
			break;	/* goto sizeof (int) option return */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9772
		case TCP_INIT_CWND: {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9773
			uint32_t init_cwnd = *((uint32_t *)invalp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9774
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9775
			if (checkonly)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9776
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9777
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9778
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9779
			 * Only allow socket with network configuration
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9780
			 * privilege to set the initial cwnd to be larger
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9781
			 * than allowed by RFC 3390.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9782
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9783
			if (init_cwnd <= MIN(4, MAX(2, 4380 / tcp->tcp_mss))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9784
				tcp->tcp_init_cwnd = init_cwnd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9785
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9786
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9787
			if ((reterr = secpolicy_net_config(cr, B_TRUE)) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9788
				*outlenp = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9789
				return (reterr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9790
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9791
			if (init_cwnd > TCP_MAX_INIT_CWND) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9792
				*outlenp = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9793
				return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9794
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9795
			tcp->tcp_init_cwnd = init_cwnd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9796
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9797
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9798
		case TCP_KEEPALIVE_THRESHOLD:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9799
			if (checkonly)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9800
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9801
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9802
			if (*i1 < tcp_keepalive_interval_low ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9803
			    *i1 > tcp_keepalive_interval_high) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9804
				*outlenp = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9805
				return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9806
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9807
			if (*i1 != tcp->tcp_ka_interval) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9808
				tcp->tcp_ka_interval = *i1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9809
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9810
				 * Check if we need to restart the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9811
				 * keepalive timer.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9812
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9813
				if (tcp->tcp_ka_tid != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9814
					ASSERT(tcp->tcp_ka_enabled);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9815
					(void) TCP_TIMER_CANCEL(tcp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9816
					    tcp->tcp_ka_tid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9817
					tcp->tcp_ka_last_intrvl = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9818
					tcp->tcp_ka_tid = TCP_TIMER(tcp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9819
					    tcp_keepalive_killer,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9820
					    MSEC_TO_TICK(tcp->tcp_ka_interval));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9821
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9822
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9823
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9824
		case TCP_KEEPALIVE_ABORT_THRESHOLD:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9825
			if (!checkonly) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9826
				if (*i1 < tcp_keepalive_abort_interval_low ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9827
				    *i1 > tcp_keepalive_abort_interval_high) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9828
					*outlenp = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9829
					return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9830
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9831
				tcp->tcp_ka_abort_thres = *i1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9832
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9833
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9834
		case TCP_CORK:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9835
			if (!checkonly) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9836
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9837
				 * if tcp->tcp_cork was set and is now
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9838
				 * being unset, we have to make sure that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9839
				 * the remaining data gets sent out. Also
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9840
				 * unset tcp->tcp_cork so that tcp_wput_data()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9841
				 * can send data even if it is less than mss
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9842
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9843
				if (tcp->tcp_cork && onoff == 0 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9844
				    tcp->tcp_unsent > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9845
					tcp->tcp_cork = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9846
					tcp_wput_data(tcp, NULL, B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9847
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9848
				tcp->tcp_cork = onoff;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9849
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9850
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9851
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9852
			*outlenp = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9853
			return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9854
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9855
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9856
	case IPPROTO_IP:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9857
		if (tcp->tcp_family != AF_INET) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9858
			*outlenp = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9859
			return (ENOPROTOOPT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9860
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9861
		switch (name) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9862
		case IP_OPTIONS:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9863
		case T_IP_OPTIONS:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9864
			reterr = tcp_opt_set_header(tcp, checkonly,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9865
			    invalp, inlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9866
			if (reterr) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9867
				*outlenp = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9868
				return (reterr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9869
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9870
			/* OK return - copy input buffer into output buffer */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9871
			if (invalp != outvalp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9872
				/* don't trust bcopy for identical src/dst */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9873
				bcopy(invalp, outvalp, inlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9874
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9875
			*outlenp = inlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9876
			return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9877
		case IP_TOS:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9878
		case T_IP_TOS:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9879
			if (!checkonly) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9880
				tcp->tcp_ipha->ipha_type_of_service =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9881
				    (uchar_t)*i1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9882
				tcp->tcp_tos = (uchar_t)*i1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9883
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9884
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9885
		case IP_TTL:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9886
			if (!checkonly) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9887
				tcp->tcp_ipha->ipha_ttl = (uchar_t)*i1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9888
				tcp->tcp_ttl = (uchar_t)*i1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9889
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9890
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9891
		case IP_BOUND_IF:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9892
			/* Handled at the IP level */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9893
			return (-EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9894
		case IP_SEC_OPT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9895
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9896
			 * We should not allow policy setting after
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9897
			 * we start listening for connections.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9898
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9899
			if (tcp->tcp_state == TCPS_LISTEN) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9900
				return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9901
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9902
				/* Handled at the IP level */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9903
				return (-EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9904
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9905
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9906
			*outlenp = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9907
			return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9908
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9909
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9910
	case IPPROTO_IPV6: {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9911
		ip6_pkt_t		*ipp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9912
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9913
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9914
		 * IPPROTO_IPV6 options are only supported for sockets
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9915
		 * that are using IPv6 on the wire.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9916
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9917
		if (tcp->tcp_ipversion != IPV6_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9918
			*outlenp = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9919
			return (ENOPROTOOPT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9920
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9921
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9922
		 * Only sticky options; no ancillary data
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9923
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9924
		ASSERT(thisdg_attrs == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9925
		ipp = &tcp->tcp_sticky_ipp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9926
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9927
		switch (name) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9928
		case IPV6_UNICAST_HOPS:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9929
			/* -1 means use default */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9930
			if (*i1 < -1 || *i1 > IPV6_MAX_HOPS) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9931
				*outlenp = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9932
				return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9933
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9934
			if (!checkonly) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9935
				if (*i1 == -1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9936
					tcp->tcp_ip6h->ip6_hops =
679
f2c9450b58f4 6201425 setting IPV6_UNICAST_HOPS on SCTP socket doesn't do anything
seb
parents: 646
diff changeset
  9937
					    ipp->ipp_unicast_hops =
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9938
					    (uint8_t)tcp_ipv6_hoplimit;
679
f2c9450b58f4 6201425 setting IPV6_UNICAST_HOPS on SCTP socket doesn't do anything
seb
parents: 646
diff changeset
  9939
					ipp->ipp_fields &= ~IPPF_UNICAST_HOPS;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9940
					/* Pass modified value to IP. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9941
					*i1 = tcp->tcp_ip6h->ip6_hops;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9942
				} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9943
					tcp->tcp_ip6h->ip6_hops =
679
f2c9450b58f4 6201425 setting IPV6_UNICAST_HOPS on SCTP socket doesn't do anything
seb
parents: 646
diff changeset
  9944
					    ipp->ipp_unicast_hops =
f2c9450b58f4 6201425 setting IPV6_UNICAST_HOPS on SCTP socket doesn't do anything
seb
parents: 646
diff changeset
  9945
					    (uint8_t)*i1;
f2c9450b58f4 6201425 setting IPV6_UNICAST_HOPS on SCTP socket doesn't do anything
seb
parents: 646
diff changeset
  9946
					ipp->ipp_fields |= IPPF_UNICAST_HOPS;
f2c9450b58f4 6201425 setting IPV6_UNICAST_HOPS on SCTP socket doesn't do anything
seb
parents: 646
diff changeset
  9947
				}
f2c9450b58f4 6201425 setting IPV6_UNICAST_HOPS on SCTP socket doesn't do anything
seb
parents: 646
diff changeset
  9948
				reterr = tcp_build_hdrs(q, tcp);
f2c9450b58f4 6201425 setting IPV6_UNICAST_HOPS on SCTP socket doesn't do anything
seb
parents: 646
diff changeset
  9949
				if (reterr != 0)
f2c9450b58f4 6201425 setting IPV6_UNICAST_HOPS on SCTP socket doesn't do anything
seb
parents: 646
diff changeset
  9950
					return (reterr);
0
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 IPV6_BOUND_IF:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9954
			if (!checkonly) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9955
				int error = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9956
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9957
				tcp->tcp_bound_if = *i1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9958
				error = ip_opt_set_ill(tcp->tcp_connp, *i1,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9959
				    B_TRUE, checkonly, level, name, mblk);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9960
				if (error != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9961
					*outlenp = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9962
					return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9963
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9964
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9965
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9966
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9967
		 * Set boolean switches for ancillary data delivery
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9968
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9969
		case IPV6_RECVPKTINFO:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9970
			if (!checkonly) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9971
				if (onoff)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9972
					tcp->tcp_ipv6_recvancillary |=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9973
					    TCP_IPV6_RECVPKTINFO;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9974
				else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9975
					tcp->tcp_ipv6_recvancillary &=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9976
					    ~TCP_IPV6_RECVPKTINFO;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9977
				/* Force it to be sent up with the next msg */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9978
				tcp->tcp_recvifindex = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9979
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9980
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9981
		case IPV6_RECVTCLASS:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9982
			if (!checkonly) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9983
				if (onoff)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9984
					tcp->tcp_ipv6_recvancillary |=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9985
					    TCP_IPV6_RECVTCLASS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9986
				else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9987
					tcp->tcp_ipv6_recvancillary &=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9988
					    ~TCP_IPV6_RECVTCLASS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9989
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9990
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9991
		case IPV6_RECVHOPLIMIT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9992
			if (!checkonly) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9993
				if (onoff)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9994
					tcp->tcp_ipv6_recvancillary |=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9995
					    TCP_IPV6_RECVHOPLIMIT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9996
				else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9997
					tcp->tcp_ipv6_recvancillary &=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9998
					    ~TCP_IPV6_RECVHOPLIMIT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9999
				/* Force it to be sent up with the next msg */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10000
				tcp->tcp_recvhops = 0xffffffffU;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10001
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10002
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10003
		case IPV6_RECVHOPOPTS:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10004
			if (!checkonly) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10005
				if (onoff)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10006
					tcp->tcp_ipv6_recvancillary |=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10007
					    TCP_IPV6_RECVHOPOPTS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10008
				else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10009
					tcp->tcp_ipv6_recvancillary &=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10010
					    ~TCP_IPV6_RECVHOPOPTS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10011
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10012
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10013
		case IPV6_RECVDSTOPTS:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10014
			if (!checkonly) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10015
				if (onoff)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10016
					tcp->tcp_ipv6_recvancillary |=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10017
					    TCP_IPV6_RECVDSTOPTS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10018
				else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10019
					tcp->tcp_ipv6_recvancillary &=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10020
					    ~TCP_IPV6_RECVDSTOPTS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10021
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10022
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10023
		case _OLD_IPV6_RECVDSTOPTS:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10024
			if (!checkonly) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10025
				if (onoff)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10026
					tcp->tcp_ipv6_recvancillary |=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10027
					    TCP_OLD_IPV6_RECVDSTOPTS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10028
				else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10029
					tcp->tcp_ipv6_recvancillary &=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10030
					    ~TCP_OLD_IPV6_RECVDSTOPTS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10031
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10032
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10033
		case IPV6_RECVRTHDR:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10034
			if (!checkonly) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10035
				if (onoff)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10036
					tcp->tcp_ipv6_recvancillary |=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10037
					    TCP_IPV6_RECVRTHDR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10038
				else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10039
					tcp->tcp_ipv6_recvancillary &=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10040
					    ~TCP_IPV6_RECVRTHDR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10041
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10042
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10043
		case IPV6_RECVRTHDRDSTOPTS:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10044
			if (!checkonly) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10045
				if (onoff)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10046
					tcp->tcp_ipv6_recvancillary |=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10047
					    TCP_IPV6_RECVRTDSTOPTS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10048
				else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10049
					tcp->tcp_ipv6_recvancillary &=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10050
					    ~TCP_IPV6_RECVRTDSTOPTS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10051
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10052
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10053
		case IPV6_PKTINFO:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10054
			if (inlen != 0 && inlen != sizeof (struct in6_pktinfo))
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_IFINDEX|IPPF_ADDR);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10061
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10062
				struct in6_pktinfo *pkti;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10063
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10064
				pkti = (struct in6_pktinfo *)invalp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10065
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10066
				 * RFC 3542 states that ipi6_addr must be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10067
				 * the unspecified address when setting the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10068
				 * IPV6_PKTINFO sticky socket option on a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10069
				 * TCP socket.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10070
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10071
				if (!IN6_IS_ADDR_UNSPECIFIED(&pkti->ipi6_addr))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10072
					return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10073
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10074
				 * ip6_set_pktinfo() validates the source
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10075
				 * address and interface index.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10076
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10077
				reterr = ip6_set_pktinfo(cr, tcp->tcp_connp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10078
				    pkti, mblk);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10079
				if (reterr != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10080
					return (reterr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10081
				ipp->ipp_ifindex = pkti->ipi6_ifindex;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10082
				ipp->ipp_addr = pkti->ipi6_addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10083
				if (ipp->ipp_ifindex != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10084
					ipp->ipp_fields |= IPPF_IFINDEX;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10085
				else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10086
					ipp->ipp_fields &= ~IPPF_IFINDEX;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10087
				if (!IN6_IS_ADDR_UNSPECIFIED(&ipp->ipp_addr))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10088
					ipp->ipp_fields |= IPPF_ADDR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10089
				else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10090
					ipp->ipp_fields &= ~IPPF_ADDR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10091
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10092
			reterr = tcp_build_hdrs(q, tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10093
			if (reterr != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10094
				return (reterr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10095
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10096
		case IPV6_TCLASS:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10097
			if (inlen != 0 && inlen != sizeof (int))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10098
				return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10099
			if (checkonly)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10100
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10101
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10102
			if (inlen == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10103
				ipp->ipp_fields &= ~IPPF_TCLASS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10104
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10105
				if (*i1 > 255 || *i1 < -1)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10106
					return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10107
				if (*i1 == -1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10108
					ipp->ipp_tclass = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10109
					*i1 = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10110
				} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10111
					ipp->ipp_tclass = *i1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10112
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10113
				ipp->ipp_fields |= IPPF_TCLASS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10114
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10115
			reterr = tcp_build_hdrs(q, tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10116
			if (reterr != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10117
				return (reterr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10118
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10119
		case IPV6_NEXTHOP:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10120
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10121
			 * IP will verify that the nexthop is reachable
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10122
			 * and fail for sticky options.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10123
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10124
			if (inlen != 0 && inlen != sizeof (sin6_t))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10125
				return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10126
			if (checkonly)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10127
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10128
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10129
			if (inlen == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10130
				ipp->ipp_fields &= ~IPPF_NEXTHOP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10131
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10132
				sin6_t *sin6 = (sin6_t *)invalp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10133
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10134
				if (sin6->sin6_family != AF_INET6)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10135
					return (EAFNOSUPPORT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10136
				if (IN6_IS_ADDR_V4MAPPED(
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10137
				    &sin6->sin6_addr))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10138
					return (EADDRNOTAVAIL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10139
				ipp->ipp_nexthop = sin6->sin6_addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10140
				if (!IN6_IS_ADDR_UNSPECIFIED(
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10141
				    &ipp->ipp_nexthop))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10142
					ipp->ipp_fields |= IPPF_NEXTHOP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10143
				else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10144
					ipp->ipp_fields &= ~IPPF_NEXTHOP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10145
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10146
			reterr = tcp_build_hdrs(q, tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10147
			if (reterr != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10148
				return (reterr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10149
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10150
		case IPV6_HOPOPTS: {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10151
			ip6_hbh_t *hopts = (ip6_hbh_t *)invalp;
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 * (hopts->ip6h_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_HOPOPTS) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10165
					kmem_free(ipp->ipp_hopopts,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10166
					    ipp->ipp_hopoptslen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10167
					ipp->ipp_hopopts = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10168
					ipp->ipp_hopoptslen = 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_HOPOPTS;
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_hopopts,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10174
				    &ipp->ipp_hopoptslen);
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_HOPOPTS;
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_RTHDRDSTOPTS: {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10185
			ip6_dest_t *dopts = (ip6_dest_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 * (dopts->ip6d_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_RTDSTOPTS) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10200
					kmem_free(ipp->ipp_rtdstopts,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10201
					    ipp->ipp_rtdstoptslen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10202
					ipp->ipp_rtdstopts = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10203
					ipp->ipp_rtdstoptslen = 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_RTDSTOPTS;
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_rtdstopts,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10209
				    &ipp->ipp_rtdstoptslen);
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_RTDSTOPTS;
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_DSTOPTS: {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10220
			ip6_dest_t *dopts = (ip6_dest_t *)invalp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10221
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10222
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10223
			 * Sanity checks - minimum size, size a multiple of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10224
			 * eight bytes, and matching size passed in.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10225
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10226
			if (inlen != 0 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10227
			    inlen != (8 * (dopts->ip6d_len + 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
			if (inlen == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10234
				if ((ipp->ipp_fields & IPPF_DSTOPTS) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10235
					kmem_free(ipp->ipp_dstopts,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10236
					    ipp->ipp_dstoptslen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10237
					ipp->ipp_dstopts = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10238
					ipp->ipp_dstoptslen = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10239
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10240
				ipp->ipp_fields &= ~IPPF_DSTOPTS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10241
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10242
				reterr = tcp_pkt_set(invalp, inlen,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10243
				    (uchar_t **)&ipp->ipp_dstopts,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10244
				    &ipp->ipp_dstoptslen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10245
				if (reterr != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10246
					return (reterr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10247
				ipp->ipp_fields |= IPPF_DSTOPTS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10248
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10249
			reterr = tcp_build_hdrs(q, tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10250
			if (reterr != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10251
				return (reterr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10252
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10253
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10254
		case IPV6_RTHDR: {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10255
			ip6_rthdr_t *rt = (ip6_rthdr_t *)invalp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10256
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10257
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10258
			 * Sanity checks - minimum size, size a multiple of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10259
			 * eight bytes, and matching size passed in.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10260
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10261
			if (inlen != 0 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10262
			    inlen != (8 * (rt->ip6r_len + 1)))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10263
				return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10264
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10265
			if (checkonly)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10266
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10267
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10268
			if (inlen == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10269
				if ((ipp->ipp_fields & IPPF_RTHDR) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10270
					kmem_free(ipp->ipp_rthdr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10271
					    ipp->ipp_rthdrlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10272
					ipp->ipp_rthdr = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10273
					ipp->ipp_rthdrlen = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10274
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10275
				ipp->ipp_fields &= ~IPPF_RTHDR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10276
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10277
				reterr = tcp_pkt_set(invalp, inlen,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10278
				    (uchar_t **)&ipp->ipp_rthdr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10279
				    &ipp->ipp_rthdrlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10280
				if (reterr != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10281
					return (reterr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10282
				ipp->ipp_fields |= IPPF_RTHDR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10283
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10284
			reterr = tcp_build_hdrs(q, tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10285
			if (reterr != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10286
				return (reterr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10287
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10288
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10289
		case IPV6_V6ONLY:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10290
			if (!checkonly)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10291
				tcp->tcp_connp->conn_ipv6_v6only = onoff;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10292
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10293
		case IPV6_USE_MIN_MTU:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10294
			if (inlen != sizeof (int))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10295
				return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10296
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10297
			if (*i1 < -1 || *i1 > 1)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10298
				return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10299
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10300
			if (checkonly)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10301
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10302
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10303
			ipp->ipp_fields |= IPPF_USE_MIN_MTU;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10304
			ipp->ipp_use_min_mtu = *i1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10305
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10306
		case IPV6_BOUND_PIF:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10307
			/* Handled at the IP level */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10308
			return (-EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10309
		case IPV6_SEC_OPT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10310
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10311
			 * We should not allow policy setting after
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10312
			 * we start listening for connections.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10313
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10314
			if (tcp->tcp_state == TCPS_LISTEN) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10315
				return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10316
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10317
				/* Handled at the IP level */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10318
				return (-EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10319
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10320
		case IPV6_SRC_PREFERENCES:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10321
			if (inlen != sizeof (uint32_t))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10322
				return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10323
			reterr = ip6_set_src_preferences(tcp->tcp_connp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10324
			    *(uint32_t *)invalp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10325
			if (reterr != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10326
				*outlenp = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10327
				return (reterr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10328
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10329
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10330
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10331
			*outlenp = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10332
			return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10333
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10334
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10335
	}		/* end IPPROTO_IPV6 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10336
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10337
		*outlenp = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10338
		return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10339
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10340
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10341
	 * Common case of OK return with outval same as inval
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10342
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10343
	if (invalp != outvalp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10344
		/* don't trust bcopy for identical src/dst */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10345
		(void) bcopy(invalp, outvalp, inlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10346
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10347
	*outlenp = inlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10348
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10349
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10350
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10351
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10352
 * Update tcp_sticky_hdrs based on tcp_sticky_ipp.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10353
 * The headers include ip6i_t (if needed), ip6_t, any sticky extension
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10354
 * headers, and the maximum size tcp header (to avoid reallocation
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10355
 * on the fly for additional tcp options).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10356
 * Returns failure if can't allocate memory.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10357
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10358
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10359
tcp_build_hdrs(queue_t *q, tcp_t *tcp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10360
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10361
	char	*hdrs;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10362
	uint_t	hdrs_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10363
	ip6i_t	*ip6i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10364
	char	buf[TCP_MAX_HDR_LENGTH];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10365
	ip6_pkt_t *ipp = &tcp->tcp_sticky_ipp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10366
	in6_addr_t src, dst;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10367
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10368
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10369
	 * save the existing tcp header and source/dest IP addresses
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10370
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10371
	bcopy(tcp->tcp_tcph, buf, tcp->tcp_tcp_hdr_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10372
	src = tcp->tcp_ip6h->ip6_src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10373
	dst = tcp->tcp_ip6h->ip6_dst;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10374
	hdrs_len = ip_total_hdrs_len_v6(ipp) + TCP_MAX_HDR_LENGTH;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10375
	ASSERT(hdrs_len != 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10376
	if (hdrs_len > tcp->tcp_iphc_len) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10377
		/* Need to reallocate */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10378
		hdrs = kmem_zalloc(hdrs_len, KM_NOSLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10379
		if (hdrs == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10380
			return (ENOMEM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10381
		if (tcp->tcp_iphc != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10382
			if (tcp->tcp_hdr_grown) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10383
				kmem_free(tcp->tcp_iphc, tcp->tcp_iphc_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10384
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10385
				bzero(tcp->tcp_iphc, tcp->tcp_iphc_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10386
				kmem_cache_free(tcp_iphc_cache, tcp->tcp_iphc);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10387
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10388
			tcp->tcp_iphc_len = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10389
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10390
		ASSERT(tcp->tcp_iphc_len == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10391
		tcp->tcp_iphc = hdrs;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10392
		tcp->tcp_iphc_len = hdrs_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10393
		tcp->tcp_hdr_grown = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10394
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10395
	ip_build_hdrs_v6((uchar_t *)tcp->tcp_iphc,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10396
	    hdrs_len - TCP_MAX_HDR_LENGTH, ipp, IPPROTO_TCP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10397
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10398
	/* Set header fields not in ipp */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10399
	if (ipp->ipp_fields & IPPF_HAS_IP6I) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10400
		ip6i = (ip6i_t *)tcp->tcp_iphc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10401
		tcp->tcp_ip6h = (ip6_t *)&ip6i[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10402
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10403
		tcp->tcp_ip6h = (ip6_t *)tcp->tcp_iphc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10404
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10405
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10406
	 * tcp->tcp_ip_hdr_len will include ip6i_t if there is one.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10407
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10408
	 * tcp->tcp_tcp_hdr_len doesn't change here.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10409
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10410
	tcp->tcp_ip_hdr_len = hdrs_len - TCP_MAX_HDR_LENGTH;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10411
	tcp->tcp_tcph = (tcph_t *)(tcp->tcp_iphc + tcp->tcp_ip_hdr_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10412
	tcp->tcp_hdr_len = tcp->tcp_ip_hdr_len + tcp->tcp_tcp_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10413
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10414
	bcopy(buf, tcp->tcp_tcph, tcp->tcp_tcp_hdr_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10415
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10416
	tcp->tcp_ip6h->ip6_src = src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10417
	tcp->tcp_ip6h->ip6_dst = dst;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10418
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10419
	/*
679
f2c9450b58f4 6201425 setting IPV6_UNICAST_HOPS on SCTP socket doesn't do anything
seb
parents: 646
diff changeset
 10420
	 * 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
 10421
	 * the default value for TCP.
f2c9450b58f4 6201425 setting IPV6_UNICAST_HOPS on SCTP socket doesn't do anything
seb
parents: 646
diff changeset
 10422
	 */
f2c9450b58f4 6201425 setting IPV6_UNICAST_HOPS on SCTP socket doesn't do anything
seb
parents: 646
diff changeset
 10423
	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
 10424
		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
 10425
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10426
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10427
	 * If we're setting extension headers after a connection
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10428
	 * has been established, and if we have a routing header
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10429
	 * among the extension headers, call ip_massage_options_v6 to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10430
	 * manipulate the routing header/ip6_dst set the checksum
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10431
	 * difference in the tcp header template.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10432
	 * (This happens in tcp_connect_ipv6 if the routing header
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10433
	 * is set prior to the connect.)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10434
	 * Set the tcp_sum to zero first in case we've cleared a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10435
	 * routing header or don't have one at all.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10436
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10437
	tcp->tcp_sum = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10438
	if ((tcp->tcp_state >= TCPS_SYN_SENT) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10439
	    (tcp->tcp_ipp_fields & IPPF_RTHDR)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10440
		ip6_rthdr_t *rth = ip_find_rthdr_v6(tcp->tcp_ip6h,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10441
		    (uint8_t *)tcp->tcp_tcph);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10442
		if (rth != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10443
			tcp->tcp_sum = ip_massage_options_v6(tcp->tcp_ip6h,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10444
			    rth);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10445
			tcp->tcp_sum = ntohs((tcp->tcp_sum & 0xFFFF) +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10446
			    (tcp->tcp_sum >> 16));
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
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10450
	/* Try to get everything in a single mblk */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10451
	(void) mi_set_sth_wroff(RD(q), hdrs_len + tcp_wroff_xtra);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10452
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10453
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10454
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10455
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10456
 * Set optbuf and optlen for the option.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10457
 * Allocate memory (if not already present).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10458
 * Otherwise just point optbuf and optlen at invalp and inlen.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10459
 * Returns failure if memory can not be allocated.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10460
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10461
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10462
tcp_pkt_set(uchar_t *invalp, uint_t inlen, uchar_t **optbufp, uint_t *optlenp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10463
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10464
	uchar_t *optbuf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10465
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10466
	if (inlen == *optlenp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10467
		/* Unchanged length - no need to realocate */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10468
		bcopy(invalp, *optbufp, inlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10469
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10470
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10471
	if (inlen != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10472
		/* Allocate new buffer before free */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10473
		optbuf = kmem_alloc(inlen, KM_NOSLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10474
		if (optbuf == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10475
			return (ENOMEM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10476
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10477
		optbuf = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10478
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10479
	/* Free old buffer */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10480
	if (*optlenp != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10481
		kmem_free(*optbufp, *optlenp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10482
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10483
	bcopy(invalp, optbuf, inlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10484
	*optbufp = optbuf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10485
	*optlenp = inlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10486
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10487
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10488
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10489
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10490
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10491
 * Use the outgoing IP header to create an IP_OPTIONS option the way
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10492
 * it was passed down from the application.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10493
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10494
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10495
tcp_opt_get_user(ipha_t *ipha, uchar_t *buf)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10496
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10497
	ipoptp_t	opts;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10498
	uchar_t		*opt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10499
	uint8_t		optval;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10500
	uint8_t		optlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10501
	uint32_t	len = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10502
	uchar_t	*buf1 = buf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10503
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10504
	buf += IP_ADDR_LEN;	/* Leave room for final destination */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10505
	len += IP_ADDR_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10506
	bzero(buf1, IP_ADDR_LEN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10507
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10508
	for (optval = ipoptp_first(&opts, ipha);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10509
	    optval != IPOPT_EOL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10510
	    optval = ipoptp_next(&opts)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10511
		opt = opts.ipoptp_cur;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10512
		optlen = opts.ipoptp_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10513
		switch (optval) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10514
			int	off;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10515
		case IPOPT_SSRR:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10516
		case IPOPT_LSRR:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10517
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10518
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10519
			 * Insert ipha_dst as the first entry in the source
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10520
			 * route and move down the entries on step.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10521
			 * The last entry gets placed at buf1.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10522
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10523
			buf[IPOPT_OPTVAL] = optval;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10524
			buf[IPOPT_OLEN] = optlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10525
			buf[IPOPT_OFFSET] = optlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10526
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10527
			off = optlen - IP_ADDR_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10528
			if (off < 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
			/* Last entry in source route */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10533
			bcopy(opt + off, buf1, IP_ADDR_LEN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10534
			off -= IP_ADDR_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10535
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10536
			while (off > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10537
				bcopy(opt + off,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10538
				    buf + off + IP_ADDR_LEN,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10539
				    IP_ADDR_LEN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10540
				off -= IP_ADDR_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10541
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10542
			/* ipha_dst into first slot */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10543
			bcopy(&ipha->ipha_dst,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10544
			    buf + off + IP_ADDR_LEN,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10545
			    IP_ADDR_LEN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10546
			buf += optlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10547
			len += optlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10548
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10549
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10550
			bcopy(opt, buf, optlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10551
			buf += optlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10552
			len += optlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10553
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10554
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10555
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10556
done:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10557
	/* Pad the resulting options */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10558
	while (len & 0x3) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10559
		*buf++ = IPOPT_EOL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10560
		len++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10561
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10562
	return (len);
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
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10566
 * Transfer any source route option from ipha to buf/dst in reversed form.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10567
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10568
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10569
tcp_opt_rev_src_route(ipha_t *ipha, char *buf, uchar_t *dst)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10570
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10571
	ipoptp_t	opts;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10572
	uchar_t		*opt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10573
	uint8_t		optval;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10574
	uint8_t		optlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10575
	uint32_t	len = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10576
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10577
	for (optval = ipoptp_first(&opts, ipha);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10578
	    optval != IPOPT_EOL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10579
	    optval = ipoptp_next(&opts)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10580
		opt = opts.ipoptp_cur;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10581
		optlen = opts.ipoptp_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10582
		switch (optval) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10583
			int	off1, off2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10584
		case IPOPT_SSRR:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10585
		case IPOPT_LSRR:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10586
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10587
			/* Reverse source route */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10588
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10589
			 * First entry should be the next to last one in the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10590
			 * current source route (the last entry is our
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10591
			 * address.)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10592
			 * The last entry should be the final destination.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10593
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10594
			buf[IPOPT_OPTVAL] = (uint8_t)optval;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10595
			buf[IPOPT_OLEN] = (uint8_t)optlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10596
			off1 = IPOPT_MINOFF_SR - 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10597
			off2 = opt[IPOPT_OFFSET] - IP_ADDR_LEN - 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10598
			if (off2 < 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10599
				/* No entries in source route */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10600
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10601
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10602
			bcopy(opt + off2, dst, IP_ADDR_LEN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10603
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10604
			 * Note: use src since ipha has not had its src
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10605
			 * and dst reversed (it is in the state it was
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10606
			 * received.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10607
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10608
			bcopy(&ipha->ipha_src, buf + off2,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10609
			    IP_ADDR_LEN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10610
			off2 -= IP_ADDR_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10611
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10612
			while (off2 > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10613
				bcopy(opt + off2, buf + off1,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10614
				    IP_ADDR_LEN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10615
				off1 += IP_ADDR_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10616
				off2 -= IP_ADDR_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10617
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10618
			buf[IPOPT_OFFSET] = IPOPT_MINOFF_SR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10619
			buf += optlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10620
			len += optlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10621
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10622
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10623
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10624
done:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10625
	/* Pad the resulting options */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10626
	while (len & 0x3) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10627
		*buf++ = IPOPT_EOL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10628
		len++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10629
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10630
	return (len);
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
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10634
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10635
 * Extract and revert a source route from ipha (if any)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10636
 * and then update the relevant fields in both tcp_t and the standard header.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10637
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10638
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10639
tcp_opt_reverse(tcp_t *tcp, ipha_t *ipha)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10640
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10641
	char	buf[TCP_MAX_HDR_LENGTH];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10642
	uint_t	tcph_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10643
	int	len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10644
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10645
	ASSERT(IPH_HDR_VERSION(ipha) == IPV4_VERSION);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10646
	len = IPH_HDR_LENGTH(ipha);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10647
	if (len == IP_SIMPLE_HDR_LENGTH)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10648
		/* Nothing to do */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10649
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10650
	if (len > IP_SIMPLE_HDR_LENGTH + TCP_MAX_IP_OPTIONS_LENGTH ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10651
	    (len & 0x3))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10652
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10653
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10654
	tcph_len = tcp->tcp_tcp_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10655
	bcopy(tcp->tcp_tcph, buf, tcph_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10656
	tcp->tcp_sum = (tcp->tcp_ipha->ipha_dst >> 16) +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10657
		(tcp->tcp_ipha->ipha_dst & 0xffff);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10658
	len = tcp_opt_rev_src_route(ipha, (char *)tcp->tcp_ipha +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10659
	    IP_SIMPLE_HDR_LENGTH, (uchar_t *)&tcp->tcp_ipha->ipha_dst);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10660
	len += IP_SIMPLE_HDR_LENGTH;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10661
	tcp->tcp_sum -= ((tcp->tcp_ipha->ipha_dst >> 16) +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10662
	    (tcp->tcp_ipha->ipha_dst & 0xffff));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10663
	if ((int)tcp->tcp_sum < 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10664
		tcp->tcp_sum--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10665
	tcp->tcp_sum = (tcp->tcp_sum & 0xFFFF) + (tcp->tcp_sum >> 16);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10666
	tcp->tcp_sum = ntohs((tcp->tcp_sum & 0xFFFF) + (tcp->tcp_sum >> 16));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10667
	tcp->tcp_tcph = (tcph_t *)((char *)tcp->tcp_ipha + len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10668
	bcopy(buf, tcp->tcp_tcph, tcph_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10669
	tcp->tcp_ip_hdr_len = len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10670
	tcp->tcp_ipha->ipha_version_and_hdr_length =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10671
	    (IP_VERSION << 4) | (len >> 2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10672
	len += tcph_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10673
	tcp->tcp_hdr_len = len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10674
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10675
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10676
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10677
 * Copy the standard header into its new location,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10678
 * lay in the new options and then update the relevant
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10679
 * fields in both tcp_t and the standard header.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10680
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10681
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10682
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
 10683
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10684
	uint_t	tcph_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10685
	char	*ip_optp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10686
	tcph_t	*new_tcph;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10687
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10688
	if (checkonly) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10689
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10690
		 * do not really set, just pretend to - T_CHECK
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10691
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10692
		if (len != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10693
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10694
			 * there is value supplied, validate it as if
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10695
			 * for a real set operation.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10696
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10697
			if ((len > TCP_MAX_IP_OPTIONS_LENGTH) || (len & 0x3))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10698
				return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10699
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10700
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10701
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10702
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10703
	if ((len > TCP_MAX_IP_OPTIONS_LENGTH) || (len & 0x3))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10704
		return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10705
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10706
	ip_optp = (char *)tcp->tcp_ipha + IP_SIMPLE_HDR_LENGTH;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10707
	tcph_len = tcp->tcp_tcp_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10708
	new_tcph = (tcph_t *)(ip_optp + len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10709
	ovbcopy((char *)tcp->tcp_tcph, (char *)new_tcph, tcph_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10710
	tcp->tcp_tcph = new_tcph;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10711
	bcopy(ptr, ip_optp, len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10712
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10713
	len += IP_SIMPLE_HDR_LENGTH;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10714
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10715
	tcp->tcp_ip_hdr_len = len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10716
	tcp->tcp_ipha->ipha_version_and_hdr_length =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10717
		(IP_VERSION << 4) | (len >> 2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10718
	len += tcph_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10719
	tcp->tcp_hdr_len = len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10720
	if (!TCP_IS_DETACHED(tcp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10721
		/* Always allocate room for all options. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10722
		(void) mi_set_sth_wroff(tcp->tcp_rq,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10723
		    TCP_MAX_COMBINED_HEADER_LENGTH + tcp_wroff_xtra);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10724
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10725
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10726
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10727
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10728
/* Get callback routine passed to nd_load by tcp_param_register */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10729
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10730
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10731
tcp_param_get(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *cr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10732
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10733
	tcpparam_t	*tcppa = (tcpparam_t *)cp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10734
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10735
	(void) mi_mpprintf(mp, "%u", tcppa->tcp_param_val);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10736
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10737
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10738
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10739
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10740
 * Walk through the param array specified registering each element with the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10741
 * named dispatch handler.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10742
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10743
static boolean_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10744
tcp_param_register(tcpparam_t *tcppa, int cnt)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10745
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10746
	for (; cnt-- > 0; tcppa++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10747
		if (tcppa->tcp_param_name && tcppa->tcp_param_name[0]) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10748
			if (!nd_load(&tcp_g_nd, tcppa->tcp_param_name,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10749
			    tcp_param_get, tcp_param_set,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10750
			    (caddr_t)tcppa)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10751
				nd_free(&tcp_g_nd);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10752
				return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10753
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10754
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10755
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10756
	if (!nd_load(&tcp_g_nd, tcp_wroff_xtra_param.tcp_param_name,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10757
	    tcp_param_get, tcp_param_set_aligned,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10758
	    (caddr_t)&tcp_wroff_xtra_param)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10759
		nd_free(&tcp_g_nd);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10760
		return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10761
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10762
	if (!nd_load(&tcp_g_nd, tcp_mdt_head_param.tcp_param_name,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10763
	    tcp_param_get, tcp_param_set_aligned,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10764
	    (caddr_t)&tcp_mdt_head_param)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10765
		nd_free(&tcp_g_nd);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10766
		return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10767
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10768
	if (!nd_load(&tcp_g_nd, tcp_mdt_tail_param.tcp_param_name,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10769
	    tcp_param_get, tcp_param_set_aligned,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10770
	    (caddr_t)&tcp_mdt_tail_param)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10771
		nd_free(&tcp_g_nd);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10772
		return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10773
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10774
	if (!nd_load(&tcp_g_nd, tcp_mdt_max_pbufs_param.tcp_param_name,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10775
	    tcp_param_get, tcp_param_set,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10776
	    (caddr_t)&tcp_mdt_max_pbufs_param)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10777
		nd_free(&tcp_g_nd);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10778
		return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10779
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10780
	if (!nd_load(&tcp_g_nd, "tcp_extra_priv_ports",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10781
	    tcp_extra_priv_ports_get, NULL, NULL)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10782
		nd_free(&tcp_g_nd);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10783
		return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10784
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10785
	if (!nd_load(&tcp_g_nd, "tcp_extra_priv_ports_add",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10786
	    NULL, tcp_extra_priv_ports_add, NULL)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10787
		nd_free(&tcp_g_nd);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10788
		return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10789
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10790
	if (!nd_load(&tcp_g_nd, "tcp_extra_priv_ports_del",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10791
	    NULL, tcp_extra_priv_ports_del, NULL)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10792
		nd_free(&tcp_g_nd);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10793
		return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10794
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10795
	if (!nd_load(&tcp_g_nd, "tcp_status", tcp_status_report, NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10796
	    NULL)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10797
		nd_free(&tcp_g_nd);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10798
		return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10799
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10800
	if (!nd_load(&tcp_g_nd, "tcp_bind_hash", tcp_bind_hash_report,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10801
	    NULL, NULL)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10802
		nd_free(&tcp_g_nd);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10803
		return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10804
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10805
	if (!nd_load(&tcp_g_nd, "tcp_listen_hash", tcp_listen_hash_report,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10806
	    NULL, NULL)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10807
		nd_free(&tcp_g_nd);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10808
		return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10809
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10810
	if (!nd_load(&tcp_g_nd, "tcp_conn_hash", tcp_conn_hash_report,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10811
	    NULL, NULL)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10812
		nd_free(&tcp_g_nd);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10813
		return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10814
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10815
	if (!nd_load(&tcp_g_nd, "tcp_acceptor_hash", tcp_acceptor_hash_report,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10816
	    NULL, NULL)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10817
		nd_free(&tcp_g_nd);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10818
		return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10819
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10820
	if (!nd_load(&tcp_g_nd, "tcp_host_param", tcp_host_param_report,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10821
	    tcp_host_param_set, NULL)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10822
		nd_free(&tcp_g_nd);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10823
		return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10824
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10825
	if (!nd_load(&tcp_g_nd, "tcp_host_param_ipv6", tcp_host_param_report,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10826
	    tcp_host_param_set_ipv6, NULL)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10827
		nd_free(&tcp_g_nd);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10828
		return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10829
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10830
	if (!nd_load(&tcp_g_nd, "tcp_1948_phrase", NULL, tcp_1948_phrase_set,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10831
	    NULL)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10832
		nd_free(&tcp_g_nd);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10833
		return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10834
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10835
	if (!nd_load(&tcp_g_nd, "tcp_reserved_port_list",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10836
	    tcp_reserved_port_list, NULL, NULL)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10837
		nd_free(&tcp_g_nd);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10838
		return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10839
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10840
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10841
	 * Dummy ndd variables - only to convey obsolescence information
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10842
	 * through printing of their name (no get or set routines)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10843
	 * XXX Remove in future releases ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10844
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10845
	if (!nd_load(&tcp_g_nd,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10846
	    "tcp_close_wait_interval(obsoleted - "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10847
	    "use tcp_time_wait_interval)", NULL, NULL, NULL)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10848
		nd_free(&tcp_g_nd);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10849
		return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10850
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10851
	return (B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10852
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10853
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10854
/* ndd set routine for tcp_wroff_xtra, tcp_mdt_hdr_{head,tail}_min. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10855
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10856
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10857
tcp_param_set_aligned(queue_t *q, mblk_t *mp, char *value, caddr_t cp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10858
    cred_t *cr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10859
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10860
	long new_value;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10861
	tcpparam_t *tcppa = (tcpparam_t *)cp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10862
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10863
	if (ddi_strtol(value, NULL, 10, &new_value) != 0 ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10864
	    new_value < tcppa->tcp_param_min ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10865
	    new_value > tcppa->tcp_param_max) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10866
		return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10867
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10868
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10869
	 * Need to make sure new_value is a multiple of 4.  If it is not,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10870
	 * round it up.  For future 64 bit requirement, we actually make it
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10871
	 * a multiple of 8.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10872
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10873
	if (new_value & 0x7) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10874
		new_value = (new_value & ~0x7) + 0x8;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10875
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10876
	tcppa->tcp_param_val = new_value;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10877
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10878
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10879
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10880
/* Set callback routine passed to nd_load by tcp_param_register */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10881
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10882
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10883
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
 10884
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10885
	long	new_value;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10886
	tcpparam_t	*tcppa = (tcpparam_t *)cp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10887
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10888
	if (ddi_strtol(value, NULL, 10, &new_value) != 0 ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10889
	    new_value < tcppa->tcp_param_min ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10890
	    new_value > tcppa->tcp_param_max) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10891
		return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10892
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10893
	tcppa->tcp_param_val = new_value;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10894
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10895
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10896
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10897
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10898
 * Add a new piece to the tcp reassembly queue.  If the gap at the beginning
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10899
 * is filled, return as much as we can.  The message passed in may be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10900
 * multi-part, chained using b_cont.  "start" is the starting sequence
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10901
 * number for this piece.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10902
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10903
static mblk_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10904
tcp_reass(tcp_t *tcp, mblk_t *mp, uint32_t start)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10905
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10906
	uint32_t	end;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10907
	mblk_t		*mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10908
	mblk_t		*mp2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10909
	mblk_t		*next_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10910
	uint32_t	u1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10911
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10912
	/* Walk through all the new pieces. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10913
	do {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10914
		ASSERT((uintptr_t)(mp->b_wptr - mp->b_rptr) <=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10915
		    (uintptr_t)INT_MAX);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10916
		end = start + (int)(mp->b_wptr - mp->b_rptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10917
		next_mp = mp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10918
		if (start == end) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10919
			/* Empty.  Blast it. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10920
			freeb(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10921
			continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10922
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10923
		mp->b_cont = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10924
		TCP_REASS_SET_SEQ(mp, start);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10925
		TCP_REASS_SET_END(mp, end);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10926
		mp1 = tcp->tcp_reass_tail;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10927
		if (!mp1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10928
			tcp->tcp_reass_tail = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10929
			tcp->tcp_reass_head = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10930
			BUMP_MIB(&tcp_mib, tcpInDataUnorderSegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10931
			UPDATE_MIB(&tcp_mib,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10932
			    tcpInDataUnorderBytes, end - start);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10933
			continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10934
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10935
		/* New stuff completely beyond tail? */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10936
		if (SEQ_GEQ(start, TCP_REASS_END(mp1))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10937
			/* Link it on end. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10938
			mp1->b_cont = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10939
			tcp->tcp_reass_tail = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10940
			BUMP_MIB(&tcp_mib, tcpInDataUnorderSegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10941
			UPDATE_MIB(&tcp_mib,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10942
			    tcpInDataUnorderBytes, end - start);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10943
			continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10944
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10945
		mp1 = tcp->tcp_reass_head;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10946
		u1 = TCP_REASS_SEQ(mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10947
		/* New stuff at the front? */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10948
		if (SEQ_LT(start, u1)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10949
			/* Yes... Check for overlap. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10950
			mp->b_cont = mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10951
			tcp->tcp_reass_head = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10952
			tcp_reass_elim_overlap(tcp, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10953
			continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10954
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10955
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10956
		 * The new piece fits somewhere between the head and tail.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10957
		 * We find our slot, where mp1 precedes us and mp2 trails.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10958
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10959
		for (; (mp2 = mp1->b_cont) != NULL; mp1 = mp2) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10960
			u1 = TCP_REASS_SEQ(mp2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10961
			if (SEQ_LEQ(start, u1))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10962
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10963
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10964
		/* Link ourselves in */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10965
		mp->b_cont = mp2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10966
		mp1->b_cont = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10967
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10968
		/* Trim overlap with following mblk(s) first */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10969
		tcp_reass_elim_overlap(tcp, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10970
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10971
		/* Trim overlap with preceding mblk */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10972
		tcp_reass_elim_overlap(tcp, mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10973
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10974
	} while (start = end, mp = next_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10975
	mp1 = tcp->tcp_reass_head;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10976
	/* Anything ready to go? */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10977
	if (TCP_REASS_SEQ(mp1) != tcp->tcp_rnxt)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10978
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10979
	/* Eat what we can off the queue */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10980
	for (;;) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10981
		mp = mp1->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10982
		end = TCP_REASS_END(mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10983
		TCP_REASS_SET_SEQ(mp1, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10984
		TCP_REASS_SET_END(mp1, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10985
		if (!mp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10986
			tcp->tcp_reass_tail = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10987
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10988
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10989
		if (end != TCP_REASS_SEQ(mp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10990
			mp1->b_cont = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10991
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10992
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10993
		mp1 = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10994
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10995
	mp1 = tcp->tcp_reass_head;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10996
	tcp->tcp_reass_head = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10997
	return (mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10998
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10999
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11000
/* Eliminate any overlap that mp may have over later mblks */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11001
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11002
tcp_reass_elim_overlap(tcp_t *tcp, mblk_t *mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11003
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11004
	uint32_t	end;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11005
	mblk_t		*mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11006
	uint32_t	u1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11007
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11008
	end = TCP_REASS_END(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11009
	while ((mp1 = mp->b_cont) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11010
		u1 = TCP_REASS_SEQ(mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11011
		if (!SEQ_GT(end, u1))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11012
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11013
		if (!SEQ_GEQ(end, TCP_REASS_END(mp1))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11014
			mp->b_wptr -= end - u1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11015
			TCP_REASS_SET_END(mp, u1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11016
			BUMP_MIB(&tcp_mib, tcpInDataPartDupSegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11017
			UPDATE_MIB(&tcp_mib, tcpInDataPartDupBytes, end - u1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11018
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11019
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11020
		mp->b_cont = mp1->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11021
		TCP_REASS_SET_SEQ(mp1, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11022
		TCP_REASS_SET_END(mp1, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11023
		freeb(mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11024
		BUMP_MIB(&tcp_mib, tcpInDataDupSegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11025
		UPDATE_MIB(&tcp_mib, tcpInDataDupBytes, end - u1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11026
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11027
	if (!mp1)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11028
		tcp->tcp_reass_tail = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11029
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11030
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11031
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11032
 * Send up all messages queued on tcp_rcv_list.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11033
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11034
static uint_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11035
tcp_rcv_drain(queue_t *q, tcp_t *tcp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11036
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11037
	mblk_t *mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11038
	uint_t ret = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11039
	uint_t thwin;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11040
#ifdef DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11041
	uint_t cnt = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11042
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11043
	/* Can't drain on an eager connection */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11044
	if (tcp->tcp_listener != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11045
		return (ret);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11046
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11047
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11048
	 * Handle two cases here: we are currently fused or we were
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11049
	 * previously fused and have some urgent data to be delivered
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11050
	 * upstream.  The latter happens because we either ran out of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11051
	 * memory or were detached and therefore sending the SIGURG was
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11052
	 * deferred until this point.  In either case we pass control
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11053
	 * over to tcp_fuse_rcv_drain() since it may need to complete
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11054
	 * some work.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11055
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11056
	if ((tcp->tcp_fused || tcp->tcp_fused_sigurg)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11057
		ASSERT(tcp->tcp_fused_sigurg_mp != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11058
		if (tcp_fuse_rcv_drain(q, tcp, tcp->tcp_fused ? NULL :
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11059
		    &tcp->tcp_fused_sigurg_mp))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11060
			return (ret);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11061
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11062
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11063
	while ((mp = tcp->tcp_rcv_list) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11064
		tcp->tcp_rcv_list = mp->b_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11065
		mp->b_next = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11066
#ifdef DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11067
		cnt += msgdsize(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11068
#endif
898
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 11069
		/* Does this need SSL processing first? */
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 11070
		if ((tcp->tcp_kssl_ctx  != NULL) && (DB_TYPE(mp) == M_DATA)) {
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 11071
			tcp_kssl_input(tcp, mp);
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 11072
			continue;
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 11073
		}
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11074
		putnext(q, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11075
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11076
	ASSERT(cnt == tcp->tcp_rcv_cnt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11077
	tcp->tcp_rcv_last_head = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11078
	tcp->tcp_rcv_last_tail = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11079
	tcp->tcp_rcv_cnt = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11080
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11081
	/* Learn the latest rwnd information that we sent to the other side. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11082
	thwin = ((uint_t)BE16_TO_U16(tcp->tcp_tcph->th_win))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11083
	    << tcp->tcp_rcv_ws;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11084
	/* This is peer's calculated send window (our receive window). */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11085
	thwin -= tcp->tcp_rnxt - tcp->tcp_rack;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11086
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11087
	 * Increase the receive window to max.  But we need to do receiver
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11088
	 * SWS avoidance.  This means that we need to check the increase of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11089
	 * of receive window is at least 1 MSS.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11090
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11091
	if (canputnext(q) && (q->q_hiwat - thwin >= tcp->tcp_mss)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11092
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11093
		 * If the window that the other side knows is less than max
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11094
		 * deferred acks segments, send an update immediately.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11095
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11096
		if (thwin < tcp->tcp_rack_cur_max * tcp->tcp_mss) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11097
			BUMP_MIB(&tcp_mib, tcpOutWinUpdate);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11098
			ret = TH_ACK_NEEDED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11099
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11100
		tcp->tcp_rwnd = q->q_hiwat;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11101
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11102
	/* No need for the push timer now. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11103
	if (tcp->tcp_push_tid != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11104
		(void) TCP_TIMER_CANCEL(tcp, tcp->tcp_push_tid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11105
		tcp->tcp_push_tid = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11106
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11107
	return (ret);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11108
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11109
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11110
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11111
 * Queue data on tcp_rcv_list which is a b_next chain.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11112
 * tcp_rcv_last_head/tail is the last element of this chain.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11113
 * Each element of the chain is a b_cont chain.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11114
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11115
 * M_DATA messages are added to the current element.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11116
 * Other messages are added as new (b_next) elements.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11117
 */
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 11118
void
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11119
tcp_rcv_enqueue(tcp_t *tcp, mblk_t *mp, uint_t seg_len)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11120
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11121
	ASSERT(seg_len == msgdsize(mp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11122
	ASSERT(tcp->tcp_rcv_list == NULL || tcp->tcp_rcv_last_head != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11123
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11124
	if (tcp->tcp_rcv_list == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11125
		ASSERT(tcp->tcp_rcv_last_head == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11126
		tcp->tcp_rcv_list = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11127
		tcp->tcp_rcv_last_head = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11128
	} else if (DB_TYPE(mp) == DB_TYPE(tcp->tcp_rcv_last_head)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11129
		tcp->tcp_rcv_last_tail->b_cont = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11130
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11131
		tcp->tcp_rcv_last_head->b_next = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11132
		tcp->tcp_rcv_last_head = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11133
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11134
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11135
	while (mp->b_cont)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11136
		mp = mp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11137
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11138
	tcp->tcp_rcv_last_tail = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11139
	tcp->tcp_rcv_cnt += seg_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11140
	tcp->tcp_rwnd -= seg_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11141
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11142
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11143
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11144
 * DEFAULT TCP ENTRY POINT via squeue on READ side.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11145
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11146
 * This is the default entry function into TCP on the read side. TCP is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11147
 * always entered via squeue i.e. using squeue's for mutual exclusion.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11148
 * When classifier does a lookup to find the tcp, it also puts a reference
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11149
 * on the conn structure associated so the tcp is guaranteed to exist
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11150
 * when we come here. We still need to check the state because it might
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11151
 * as well has been closed. The squeue processing function i.e. squeue_enter,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11152
 * squeue_enter_nodrain, or squeue_drain is responsible for doing the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11153
 * CONN_DEC_REF.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11154
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11155
 * Apart from the default entry point, IP also sends packets directly to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11156
 * tcp_rput_data for AF_INET fast path and tcp_conn_request for incoming
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11157
 * connections.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11158
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11159
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11160
tcp_input(void *arg, mblk_t *mp, void *arg2)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11161
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11162
	conn_t	*connp = (conn_t *)arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11163
	tcp_t	*tcp = (tcp_t *)connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11164
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11165
	/* arg2 is the sqp */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11166
	ASSERT(arg2 != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11167
	ASSERT(mp != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11168
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11169
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11170
	 * Don't accept any input on a closed tcp as this TCP logically does
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11171
	 * not exist on the system. Don't proceed further with this TCP.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11172
	 * For eg. this packet could trigger another close of this tcp
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11173
	 * which would be disastrous for tcp_refcnt. tcp_close_detached /
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11174
	 * tcp_clean_death / tcp_closei_local must be called at most once
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11175
	 * on a TCP. In this case we need to refeed the packet into the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11176
	 * classifier and figure out where the packet should go. Need to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11177
	 * preserve the recv_ill somehow. Until we figure that out, for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11178
	 * now just drop the packet if we can't classify the packet.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11179
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11180
	if (tcp->tcp_state == TCPS_CLOSED ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11181
	    tcp->tcp_state == TCPS_BOUND) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11182
		conn_t	*new_connp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11183
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11184
		new_connp = ipcl_classify(mp, connp->conn_zoneid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11185
		if (new_connp != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11186
			tcp_reinput(new_connp, mp, arg2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11187
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11188
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11189
		/* We failed to classify. For now just drop the packet */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11190
		freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11191
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11192
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11193
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11194
	if (DB_TYPE(mp) == M_DATA)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11195
		tcp_rput_data(connp, mp, arg2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11196
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11197
		tcp_rput_common(tcp, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11198
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11199
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11200
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11201
 * The read side put procedure.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11202
 * The packets passed up by ip are assume to be aligned according to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11203
 * OK_32PTR and the IP+TCP headers fitting in the first mblk.
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_rput_common(tcp_t *tcp, mblk_t *mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11207
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11208
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11209
	 * tcp_rput_data() does not expect M_CTL except for the case
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11210
	 * where tcp_ipv6_recvancillary is set and we get a IN_PKTINFO
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11211
	 * type. Need to make sure that any other M_CTLs don't make
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11212
	 * it to tcp_rput_data since it is not expecting any and doesn't
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11213
	 * check for it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11214
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11215
	if (DB_TYPE(mp) == M_CTL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11216
		switch (*(uint32_t *)(mp->b_rptr)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11217
		case TCP_IOC_ABORT_CONN:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11218
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11219
			 * Handle connection abort request.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11220
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11221
			tcp_ioctl_abort_handler(tcp, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11222
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11223
		case IPSEC_IN:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11224
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11225
			 * Only secure icmp arrive in TCP and they
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11226
			 * don't go through data path.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11227
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11228
			tcp_icmp_error(tcp, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11229
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11230
		case IN_PKTINFO:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11231
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11232
			 * Handle IPV6_RECVPKTINFO socket option on AF_INET6
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11233
			 * sockets that are receiving IPv4 traffic. tcp
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11234
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11235
			ASSERT(tcp->tcp_family == AF_INET6);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11236
			ASSERT(tcp->tcp_ipv6_recvancillary &
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11237
			    TCP_IPV6_RECVPKTINFO);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11238
			tcp_rput_data(tcp->tcp_connp, mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11239
			    tcp->tcp_connp->conn_sqp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11240
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11241
		case MDT_IOC_INFO_UPDATE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11242
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11243
			 * Handle Multidata information update; the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11244
			 * following routine will free the message.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11245
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11246
			if (tcp->tcp_connp->conn_mdt_ok) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11247
				tcp_mdt_update(tcp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11248
				    &((ip_mdt_info_t *)mp->b_rptr)->mdt_capab,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11249
				    B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11250
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11251
			freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11252
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11253
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11254
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11255
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11256
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11257
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11258
	/* No point processing the message if tcp is already closed */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11259
	if (TCP_IS_DETACHED_NONEAGER(tcp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11260
		freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11261
		return;
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
	tcp_rput_other(tcp, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11265
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11266
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11267
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11268
/* The minimum of smoothed mean deviation in RTO calculation. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11269
#define	TCP_SD_MIN	400
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11270
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11271
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11272
 * Set RTO for this connection.  The formula is from Jacobson and Karels'
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11273
 * "Congestion Avoidance and Control" in SIGCOMM '88.  The variable names
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11274
 * are the same as those in Appendix A.2 of that paper.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11275
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11276
 * m = new measurement
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11277
 * sa = smoothed RTT average (8 * average estimates).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11278
 * sv = smoothed mean deviation (mdev) of RTT (4 * deviation estimates).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11279
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11280
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11281
tcp_set_rto(tcp_t *tcp, clock_t rtt)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11282
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11283
	long m = TICK_TO_MSEC(rtt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11284
	clock_t sa = tcp->tcp_rtt_sa;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11285
	clock_t sv = tcp->tcp_rtt_sd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11286
	clock_t rto;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11287
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11288
	BUMP_MIB(&tcp_mib, tcpRttUpdate);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11289
	tcp->tcp_rtt_update++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11290
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11291
	/* tcp_rtt_sa is not 0 means this is a new sample. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11292
	if (sa != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11293
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11294
		 * Update average estimator:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11295
		 *	new rtt = 7/8 old rtt + 1/8 Error
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11296
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11297
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11298
		/* m is now Error in estimate. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11299
		m -= sa >> 3;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11300
		if ((sa += m) <= 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11301
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11302
			 * Don't allow the smoothed average to be negative.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11303
			 * We use 0 to denote reinitialization of the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11304
			 * variables.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11305
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11306
			sa = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11307
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11308
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11309
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11310
		 * Update deviation estimator:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11311
		 *	new mdev = 3/4 old mdev + 1/4 (abs(Error) - old mdev)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11312
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11313
		if (m < 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11314
			m = -m;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11315
		m -= sv >> 2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11316
		sv += m;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11317
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11318
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11319
		 * This follows BSD's implementation.  So the reinitialized
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11320
		 * RTO is 3 * m.  We cannot go less than 2 because if the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11321
		 * link is bandwidth dominated, doubling the window size
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11322
		 * during slow start means doubling the RTT.  We want to be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11323
		 * more conservative when we reinitialize our estimates.  3
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11324
		 * is just a convenient number.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11325
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11326
		sa = m << 3;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11327
		sv = m << 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11328
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11329
	if (sv < TCP_SD_MIN) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11330
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11331
		 * We do not know that if sa captures the delay ACK
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11332
		 * effect as in a long train of segments, a receiver
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11333
		 * does not delay its ACKs.  So set the minimum of sv
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11334
		 * to be TCP_SD_MIN, which is default to 400 ms, twice
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11335
		 * of BSD DATO.  That means the minimum of mean
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11336
		 * deviation is 100 ms.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11337
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11338
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11339
		sv = TCP_SD_MIN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11340
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11341
	tcp->tcp_rtt_sa = sa;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11342
	tcp->tcp_rtt_sd = sv;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11343
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11344
	 * RTO = average estimates (sa / 8) + 4 * deviation estimates (sv)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11345
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11346
	 * Add tcp_rexmit_interval extra in case of extreme environment
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11347
	 * where the algorithm fails to work.  The default value of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11348
	 * tcp_rexmit_interval_extra should be 0.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11349
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11350
	 * As we use a finer grained clock than BSD and update
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11351
	 * RTO for every ACKs, add in another .25 of RTT to the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11352
	 * deviation of RTO to accomodate burstiness of 1/4 of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11353
	 * window size.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11354
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11355
	rto = (sa >> 3) + sv + tcp_rexmit_interval_extra + (sa >> 5);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11356
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11357
	if (rto > tcp_rexmit_interval_max) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11358
		tcp->tcp_rto = tcp_rexmit_interval_max;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11359
	} else if (rto < tcp_rexmit_interval_min) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11360
		tcp->tcp_rto = tcp_rexmit_interval_min;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11361
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11362
		tcp->tcp_rto = rto;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11363
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11364
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11365
	/* Now, we can reset tcp_timer_backoff to use the new RTO... */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11366
	tcp->tcp_timer_backoff = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11367
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11368
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11369
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11370
 * tcp_get_seg_mp() is called to get the pointer to a segment in the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11371
 * send queue which starts at the given seq. no.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11372
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11373
 * Parameters:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11374
 *	tcp_t *tcp: the tcp instance pointer.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11375
 *	uint32_t seq: the starting seq. no of the requested segment.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11376
 *	int32_t *off: after the execution, *off will be the offset to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11377
 *		the returned mblk which points to the requested seq no.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11378
 *		It is the caller's responsibility to send in a non-null off.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11379
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11380
 * Return:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11381
 *	A mblk_t pointer pointing to the requested segment in send queue.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11382
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11383
static mblk_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11384
tcp_get_seg_mp(tcp_t *tcp, uint32_t seq, int32_t *off)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11385
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11386
	int32_t	cnt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11387
	mblk_t	*mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11388
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11389
	/* Defensive coding.  Make sure we don't send incorrect data. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11390
	if (SEQ_LT(seq, tcp->tcp_suna) || SEQ_GEQ(seq, tcp->tcp_snxt))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11391
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11392
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11393
	cnt = seq - tcp->tcp_suna;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11394
	mp = tcp->tcp_xmit_head;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11395
	while (cnt > 0 && mp != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11396
		cnt -= mp->b_wptr - mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11397
		if (cnt < 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11398
			cnt += mp->b_wptr - mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11399
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11400
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11401
		mp = mp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11402
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11403
	ASSERT(mp != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11404
	*off = cnt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11405
	return (mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11406
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11407
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11408
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11409
 * This function handles all retransmissions if SACK is enabled for this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11410
 * connection.  First it calculates how many segments can be retransmitted
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11411
 * based on tcp_pipe.  Then it goes thru the notsack list to find eligible
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11412
 * segments.  A segment is eligible if sack_cnt for that segment is greater
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11413
 * than or equal tcp_dupack_fast_retransmit.  After it has retransmitted
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11414
 * all eligible segments, it checks to see if TCP can send some new segments
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11415
 * (fast recovery).  If it can, set the appropriate flag for tcp_rput_data().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11416
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11417
 * Parameters:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11418
 *	tcp_t *tcp: the tcp structure of the connection.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11419
 *	uint_t *flags: in return, appropriate value will be set for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11420
 *	tcp_rput_data().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11421
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11422
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11423
tcp_sack_rxmit(tcp_t *tcp, uint_t *flags)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11424
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11425
	notsack_blk_t	*notsack_blk;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11426
	int32_t		usable_swnd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11427
	int32_t		mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11428
	uint32_t	seg_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11429
	mblk_t		*xmit_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11430
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11431
	ASSERT(tcp->tcp_sack_info != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11432
	ASSERT(tcp->tcp_notsack_list != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11433
	ASSERT(tcp->tcp_rexmit == B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11434
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11435
	/* Defensive coding in case there is a bug... */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11436
	if (tcp->tcp_notsack_list == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11437
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11438
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11439
	notsack_blk = tcp->tcp_notsack_list;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11440
	mss = tcp->tcp_mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11441
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11442
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11443
	 * Limit the num of outstanding data in the network to be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11444
	 * tcp_cwnd_ssthresh, which is half of the original congestion wnd.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11445
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11446
	usable_swnd = tcp->tcp_cwnd_ssthresh - tcp->tcp_pipe;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11447
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11448
	/* At least retransmit 1 MSS of data. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11449
	if (usable_swnd <= 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11450
		usable_swnd = mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11451
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11452
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11453
	/* Make sure no new RTT samples will be taken. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11454
	tcp->tcp_csuna = tcp->tcp_snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11455
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11456
	notsack_blk = tcp->tcp_notsack_list;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11457
	while (usable_swnd > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11458
		mblk_t		*snxt_mp, *tmp_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11459
		tcp_seq		begin = tcp->tcp_sack_snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11460
		tcp_seq		end;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11461
		int32_t		off;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11462
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11463
		for (; notsack_blk != NULL; notsack_blk = notsack_blk->next) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11464
			if (SEQ_GT(notsack_blk->end, begin) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11465
			    (notsack_blk->sack_cnt >=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11466
			    tcp_dupack_fast_retransmit)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11467
				end = notsack_blk->end;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11468
				if (SEQ_LT(begin, notsack_blk->begin)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11469
					begin = notsack_blk->begin;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11470
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11471
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11472
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11473
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11474
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11475
		 * All holes are filled.  Manipulate tcp_cwnd to send more
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11476
		 * if we can.  Note that after the SACK recovery, tcp_cwnd is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11477
		 * set to tcp_cwnd_ssthresh.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11478
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11479
		if (notsack_blk == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11480
			usable_swnd = tcp->tcp_cwnd_ssthresh - tcp->tcp_pipe;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11481
			if (usable_swnd <= 0 || tcp->tcp_unsent == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11482
				tcp->tcp_cwnd = tcp->tcp_snxt - tcp->tcp_suna;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11483
				ASSERT(tcp->tcp_cwnd > 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11484
				return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11485
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11486
				usable_swnd = usable_swnd / mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11487
				tcp->tcp_cwnd = tcp->tcp_snxt - tcp->tcp_suna +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11488
				    MAX(usable_swnd * mss, mss);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11489
				*flags |= TH_XMIT_NEEDED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11490
				return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11491
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11492
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11493
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11494
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11495
		 * Note that we may send more than usable_swnd allows here
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11496
		 * because of round off, but no more than 1 MSS of data.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11497
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11498
		seg_len = end - begin;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11499
		if (seg_len > mss)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11500
			seg_len = mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11501
		snxt_mp = tcp_get_seg_mp(tcp, begin, &off);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11502
		ASSERT(snxt_mp != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11503
		/* This should not happen.  Defensive coding again... */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11504
		if (snxt_mp == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11505
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11506
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11507
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11508
		xmit_mp = tcp_xmit_mp(tcp, snxt_mp, seg_len, &off,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11509
		    &tmp_mp, begin, B_TRUE, &seg_len, B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11510
		if (xmit_mp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11511
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11512
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11513
		usable_swnd -= seg_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11514
		tcp->tcp_pipe += seg_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11515
		tcp->tcp_sack_snxt = begin + seg_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11516
		TCP_RECORD_TRACE(tcp, xmit_mp, TCP_TRACE_SEND_PKT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11517
		tcp_send_data(tcp, tcp->tcp_wq, xmit_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11518
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11519
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11520
		 * Update the send timestamp to avoid false retransmission.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11521
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11522
		snxt_mp->b_prev = (mblk_t *)lbolt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11523
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11524
		BUMP_MIB(&tcp_mib, tcpRetransSegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11525
		UPDATE_MIB(&tcp_mib, tcpRetransBytes, seg_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11526
		BUMP_MIB(&tcp_mib, tcpOutSackRetransSegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11527
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11528
		 * Update tcp_rexmit_max to extend this SACK recovery phase.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11529
		 * This happens when new data sent during fast recovery is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11530
		 * also lost.  If TCP retransmits those new data, it needs
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11531
		 * to extend SACK recover phase to avoid starting another
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11532
		 * fast retransmit/recovery unnecessarily.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11533
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11534
		if (SEQ_GT(tcp->tcp_sack_snxt, tcp->tcp_rexmit_max)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11535
			tcp->tcp_rexmit_max = tcp->tcp_sack_snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11536
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11537
	}
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
 * This function handles policy checking at TCP level for non-hard_bound/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11542
 * detached connections.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11543
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11544
static boolean_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11545
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
 11546
    boolean_t secure, boolean_t mctl_present)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11547
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11548
	ipsec_latch_t *ipl = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11549
	ipsec_action_t *act = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11550
	mblk_t *data_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11551
	ipsec_in_t *ii;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11552
	const char *reason;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11553
	kstat_named_t *counter;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11554
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11555
	ASSERT(mctl_present || !secure);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11556
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11557
	ASSERT((ipha == NULL && ip6h != NULL) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11558
	    (ip6h == NULL && ipha != NULL));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11559
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11560
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11561
	 * We don't necessarily have an ipsec_in_act action to verify
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11562
	 * policy because of assymetrical policy where we have only
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11563
	 * outbound policy and no inbound policy (possible with global
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11564
	 * policy).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11565
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11566
	if (!secure) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11567
		if (act == NULL || act->ipa_act.ipa_type == IPSEC_ACT_BYPASS ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11568
		    act->ipa_act.ipa_type == IPSEC_ACT_CLEAR)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11569
			return (B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11570
		ipsec_log_policy_failure(tcp->tcp_wq, IPSEC_POLICY_MISMATCH,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11571
		    "tcp_check_policy", ipha, ip6h, secure);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11572
		ip_drop_packet(first_mp, B_TRUE, NULL, NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11573
		    &ipdrops_tcp_clear, &tcp_dropper);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11574
		return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11575
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11576
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11577
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11578
	 * We have a secure packet.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11579
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11580
	if (act == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11581
		ipsec_log_policy_failure(tcp->tcp_wq,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11582
		    IPSEC_POLICY_NOT_NEEDED, "tcp_check_policy", ipha, ip6h,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11583
		    secure);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11584
		ip_drop_packet(first_mp, B_TRUE, NULL, NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11585
		    &ipdrops_tcp_secure, &tcp_dropper);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11586
		return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11587
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11588
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11589
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11590
	 * XXX This whole routine is currently incorrect.  ipl should
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11591
	 * be set to the latch pointer, but is currently not set, so
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11592
	 * we initialize it to NULL to avoid picking up random garbage.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11593
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11594
	if (ipl == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11595
		return (B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11596
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11597
	data_mp = first_mp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11598
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11599
	ii = (ipsec_in_t *)first_mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11600
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11601
	if (ipsec_check_ipsecin_latch(ii, data_mp, ipl, ipha, ip6h, &reason,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11602
	    &counter)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11603
		BUMP_MIB(&ip_mib, ipsecInSucceeded);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11604
		return (B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11605
	}
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 11606
	(void) strlog(TCP_MOD_ID, 0, 0, SL_ERROR|SL_WARN|SL_CONSOLE,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11607
	    "tcp inbound policy mismatch: %s, packet dropped\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11608
	    reason);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11609
	BUMP_MIB(&ip_mib, ipsecInFailed);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11610
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11611
	ip_drop_packet(first_mp, B_TRUE, NULL, NULL, counter, &tcp_dropper);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11612
	return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11613
}
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
 * tcp_ss_rexmit() is called in tcp_rput_data() to do slow start
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11617
 * retransmission after a timeout.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11618
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11619
 * To limit the number of duplicate segments, we limit the number of segment
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11620
 * to be sent in one time to tcp_snd_burst, the burst variable.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11621
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11622
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11623
tcp_ss_rexmit(tcp_t *tcp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11624
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11625
	uint32_t	snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11626
	uint32_t	smax;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11627
	int32_t		win;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11628
	int32_t		mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11629
	int32_t		off;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11630
	int32_t		burst = tcp->tcp_snd_burst;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11631
	mblk_t		*snxt_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11632
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11633
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11634
	 * Note that tcp_rexmit can be set even though TCP has retransmitted
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11635
	 * all unack'ed segments.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11636
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11637
	if (SEQ_LT(tcp->tcp_rexmit_nxt, tcp->tcp_rexmit_max)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11638
		smax = tcp->tcp_rexmit_max;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11639
		snxt = tcp->tcp_rexmit_nxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11640
		if (SEQ_LT(snxt, tcp->tcp_suna)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11641
			snxt = tcp->tcp_suna;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11642
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11643
		win = MIN(tcp->tcp_cwnd, tcp->tcp_swnd);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11644
		win -= snxt - tcp->tcp_suna;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11645
		mss = tcp->tcp_mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11646
		snxt_mp = tcp_get_seg_mp(tcp, snxt, &off);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11647
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11648
		while (SEQ_LT(snxt, smax) && (win > 0) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11649
		    (burst > 0) && (snxt_mp != NULL)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11650
			mblk_t	*xmit_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11651
			mblk_t	*old_snxt_mp = snxt_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11652
			uint32_t cnt = mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11653
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11654
			if (win < cnt) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11655
				cnt = win;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11656
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11657
			if (SEQ_GT(snxt + cnt, smax)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11658
				cnt = smax - snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11659
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11660
			xmit_mp = tcp_xmit_mp(tcp, snxt_mp, cnt, &off,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11661
			    &snxt_mp, snxt, B_TRUE, &cnt, B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11662
			if (xmit_mp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11663
				return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11664
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11665
			tcp_send_data(tcp, tcp->tcp_wq, xmit_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11666
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11667
			snxt += cnt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11668
			win -= cnt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11669
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11670
			 * Update the send timestamp to avoid false
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11671
			 * retransmission.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11672
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11673
			old_snxt_mp->b_prev = (mblk_t *)lbolt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11674
			BUMP_MIB(&tcp_mib, tcpRetransSegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11675
			UPDATE_MIB(&tcp_mib, tcpRetransBytes, cnt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11676
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11677
			tcp->tcp_rexmit_nxt = snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11678
			burst--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11679
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11680
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11681
		 * If we have transmitted all we have at the time
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11682
		 * we started the retranmission, we can leave
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11683
		 * the rest of the job to tcp_wput_data().  But we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11684
		 * need to check the send window first.  If the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11685
		 * win is not 0, go on with tcp_wput_data().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11686
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11687
		if (SEQ_LT(snxt, smax) || win == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11688
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11689
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11690
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11691
	/* Only call tcp_wput_data() if there is data to be sent. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11692
	if (tcp->tcp_unsent) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11693
		tcp_wput_data(tcp, NULL, B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11694
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11695
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11696
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11697
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11698
 * Process all TCP option in SYN segment.  Note that this function should
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11699
 * be called after tcp_adapt_ire() is called so that the necessary info
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11700
 * from IRE is already set in the tcp structure.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11701
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11702
 * This function sets up the correct tcp_mss value according to the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11703
 * MSS option value and our header size.  It also sets up the window scale
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11704
 * and timestamp values, and initialize SACK info blocks.  But it does not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11705
 * change receive window size after setting the tcp_mss value.  The caller
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11706
 * should do the appropriate change.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11707
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11708
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11709
tcp_process_options(tcp_t *tcp, tcph_t *tcph)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11710
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11711
	int options;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11712
	tcp_opt_t tcpopt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11713
	uint32_t mss_max;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11714
	char *tmp_tcph;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11715
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11716
	tcpopt.tcp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11717
	options = tcp_parse_options(tcph, &tcpopt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11718
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11719
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11720
	 * Process MSS option.  Note that MSS option value does not account
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11721
	 * for IP or TCP options.  This means that it is equal to MTU - minimum
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11722
	 * IP+TCP header size, which is 40 bytes for IPv4 and 60 bytes for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11723
	 * IPv6.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11724
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11725
	if (!(options & TCP_OPT_MSS_PRESENT)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11726
		if (tcp->tcp_ipversion == IPV4_VERSION)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11727
			tcpopt.tcp_opt_mss = tcp_mss_def_ipv4;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11728
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11729
			tcpopt.tcp_opt_mss = tcp_mss_def_ipv6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11730
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11731
		if (tcp->tcp_ipversion == IPV4_VERSION)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11732
			mss_max = tcp_mss_max_ipv4;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11733
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11734
			mss_max = tcp_mss_max_ipv6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11735
		if (tcpopt.tcp_opt_mss < tcp_mss_min)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11736
			tcpopt.tcp_opt_mss = tcp_mss_min;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11737
		else if (tcpopt.tcp_opt_mss > mss_max)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11738
			tcpopt.tcp_opt_mss = mss_max;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11739
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11740
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11741
	/* Process Window Scale option. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11742
	if (options & TCP_OPT_WSCALE_PRESENT) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11743
		tcp->tcp_snd_ws = tcpopt.tcp_opt_wscale;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11744
		tcp->tcp_snd_ws_ok = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11745
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11746
		tcp->tcp_snd_ws = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11747
		tcp->tcp_snd_ws_ok = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11748
		tcp->tcp_rcv_ws = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11749
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11750
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11751
	/* Process Timestamp option. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11752
	if ((options & TCP_OPT_TSTAMP_PRESENT) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11753
	    (tcp->tcp_snd_ts_ok || TCP_IS_DETACHED(tcp))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11754
		tmp_tcph = (char *)tcp->tcp_tcph;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11755
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11756
		tcp->tcp_snd_ts_ok = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11757
		tcp->tcp_ts_recent = tcpopt.tcp_opt_ts_val;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11758
		tcp->tcp_last_rcv_lbolt = lbolt64;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11759
		ASSERT(OK_32PTR(tmp_tcph));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11760
		ASSERT(tcp->tcp_tcp_hdr_len == TCP_MIN_HEADER_LENGTH);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11761
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11762
		/* Fill in our template header with basic timestamp option. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11763
		tmp_tcph += tcp->tcp_tcp_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11764
		tmp_tcph[0] = TCPOPT_NOP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11765
		tmp_tcph[1] = TCPOPT_NOP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11766
		tmp_tcph[2] = TCPOPT_TSTAMP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11767
		tmp_tcph[3] = TCPOPT_TSTAMP_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11768
		tcp->tcp_hdr_len += TCPOPT_REAL_TS_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11769
		tcp->tcp_tcp_hdr_len += TCPOPT_REAL_TS_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11770
		tcp->tcp_tcph->th_offset_and_rsrvd[0] += (3 << 4);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11771
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11772
		tcp->tcp_snd_ts_ok = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11773
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11774
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11775
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11776
	 * Process SACK options.  If SACK is enabled for this connection,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11777
	 * then allocate the SACK info structure.  Note the following ways
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11778
	 * when tcp_snd_sack_ok is set to true.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11779
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11780
	 * For active connection: in tcp_adapt_ire() called in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11781
	 * tcp_rput_other(), or in tcp_rput_other() when tcp_sack_permitted
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11782
	 * is checked.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11783
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11784
	 * For passive connection: in tcp_adapt_ire() called in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11785
	 * tcp_accept_comm().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11786
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11787
	 * That's the reason why the extra TCP_IS_DETACHED() check is there.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11788
	 * That check makes sure that if we did not send a SACK OK option,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11789
	 * we will not enable SACK for this connection even though the other
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11790
	 * side sends us SACK OK option.  For active connection, the SACK
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11791
	 * info structure has already been allocated.  So we need to free
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11792
	 * it if SACK is disabled.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11793
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11794
	if ((options & TCP_OPT_SACK_OK_PRESENT) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11795
	    (tcp->tcp_snd_sack_ok ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11796
	    (tcp_sack_permitted != 0 && TCP_IS_DETACHED(tcp)))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11797
		/* This should be true only in the passive case. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11798
		if (tcp->tcp_sack_info == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11799
			ASSERT(TCP_IS_DETACHED(tcp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11800
			tcp->tcp_sack_info =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11801
			    kmem_cache_alloc(tcp_sack_info_cache, KM_NOSLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11802
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11803
		if (tcp->tcp_sack_info == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11804
			tcp->tcp_snd_sack_ok = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11805
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11806
			tcp->tcp_snd_sack_ok = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11807
			if (tcp->tcp_snd_ts_ok) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11808
				tcp->tcp_max_sack_blk = 3;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11809
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11810
				tcp->tcp_max_sack_blk = 4;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11811
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11812
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11813
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11814
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11815
		 * Resetting tcp_snd_sack_ok to B_FALSE so that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11816
		 * no SACK info will be used for this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11817
		 * connection.  This assumes that SACK usage
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11818
		 * permission is negotiated.  This may need
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11819
		 * to be changed once this is clarified.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11820
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11821
		if (tcp->tcp_sack_info != NULL) {
646
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
 11822
			ASSERT(tcp->tcp_notsack_list == NULL);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11823
			kmem_cache_free(tcp_sack_info_cache,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11824
			    tcp->tcp_sack_info);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11825
			tcp->tcp_sack_info = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11826
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11827
		tcp->tcp_snd_sack_ok = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11828
	}
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
	 * Now we know the exact TCP/IP header length, subtract
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11832
	 * that from tcp_mss to get our side's MSS.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11833
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11834
	tcp->tcp_mss -= tcp->tcp_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11835
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11836
	 * Here we assume that the other side's header size will be equal to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11837
	 * our header size.  We calculate the real MSS accordingly.  Need to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11838
	 * take into additional stuffs IPsec puts in.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11839
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11840
	 * Real MSS = Opt.MSS - (our TCP/IP header - min TCP/IP header)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11841
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11842
	tcpopt.tcp_opt_mss -= tcp->tcp_hdr_len + tcp->tcp_ipsec_overhead -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11843
	    ((tcp->tcp_ipversion == IPV4_VERSION ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11844
	    IP_SIMPLE_HDR_LENGTH : IPV6_HDR_LEN) + TCP_MIN_HEADER_LENGTH);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11845
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11846
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11847
	 * Set MSS to the smaller one of both ends of the connection.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11848
	 * We should not have called tcp_mss_set() before, but our
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11849
	 * side of the MSS should have been set to a proper value
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11850
	 * by tcp_adapt_ire().  tcp_mss_set() will also set up the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11851
	 * STREAM head parameters properly.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11852
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11853
	 * If we have a larger-than-16-bit window but the other side
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11854
	 * didn't want to do window scale, tcp_rwnd_set() will take
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11855
	 * care of that.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11856
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11857
	tcp_mss_set(tcp, MIN(tcpopt.tcp_opt_mss, tcp->tcp_mss));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11858
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11859
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11860
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11861
 * Sends the T_CONN_IND to the listener. The caller calls this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11862
 * functions via squeue to get inside the listener's perimeter
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11863
 * once the 3 way hand shake is done a T_CONN_IND needs to be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11864
 * sent. As an optimization, the caller can call this directly
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11865
 * if listener's perimeter is same as eager's.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11866
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11867
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11868
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11869
tcp_send_conn_ind(void *arg, mblk_t *mp, void *arg2)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11870
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11871
	conn_t			*lconnp = (conn_t *)arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11872
	tcp_t			*listener = lconnp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11873
	tcp_t			*tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11874
	struct T_conn_ind	*conn_ind;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11875
	ipaddr_t 		*addr_cache;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11876
	boolean_t		need_send_conn_ind = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11877
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11878
	/* retrieve the eager */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11879
	conn_ind = (struct T_conn_ind *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11880
	ASSERT(conn_ind->OPT_offset != 0 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11881
	    conn_ind->OPT_length == sizeof (intptr_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11882
	bcopy(mp->b_rptr + conn_ind->OPT_offset, &tcp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11883
		conn_ind->OPT_length);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11884
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11885
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11886
	 * TLI/XTI applications will get confused by
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11887
	 * sending eager as an option since it violates
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11888
	 * the option semantics. So remove the eager as
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11889
	 * option since TLI/XTI app doesn't need it anyway.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11890
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11891
	if (!TCP_IS_SOCKET(listener)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11892
		conn_ind->OPT_length = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11893
		conn_ind->OPT_offset = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11894
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11895
	if (listener->tcp_state == TCPS_CLOSED ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11896
	    TCP_IS_DETACHED(listener)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11897
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11898
		 * If listener has closed, it would have caused a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11899
		 * a cleanup/blowoff to happen for the eager. We
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11900
		 * just need to return.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11901
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11902
		freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11903
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11904
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11905
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11906
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11907
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11908
	 * if the conn_req_q is full defer passing up the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11909
	 * T_CONN_IND until space is availabe after t_accept()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11910
	 * processing
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11911
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11912
	mutex_enter(&listener->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11913
	if (listener->tcp_conn_req_cnt_q < listener->tcp_conn_req_max) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11914
		tcp_t *tail;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11915
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11916
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11917
		 * The eager already has an extra ref put in tcp_rput_data
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11918
		 * so that it stays till accept comes back even though it
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11919
		 * might get into TCPS_CLOSED as a result of a TH_RST etc.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11920
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11921
		ASSERT(listener->tcp_conn_req_cnt_q0 > 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11922
		listener->tcp_conn_req_cnt_q0--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11923
		listener->tcp_conn_req_cnt_q++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11924
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11925
		/* Move from SYN_RCVD to ESTABLISHED list  */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11926
		tcp->tcp_eager_next_q0->tcp_eager_prev_q0 =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11927
		    tcp->tcp_eager_prev_q0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11928
		tcp->tcp_eager_prev_q0->tcp_eager_next_q0 =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11929
		    tcp->tcp_eager_next_q0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11930
		tcp->tcp_eager_prev_q0 = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11931
		tcp->tcp_eager_next_q0 = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11932
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11933
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11934
		 * Insert at end of the queue because sockfs
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11935
		 * sends down T_CONN_RES in chronological
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11936
		 * order. Leaving the older conn indications
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11937
		 * at front of the queue helps reducing search
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11938
		 * time.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11939
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11940
		tail = listener->tcp_eager_last_q;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11941
		if (tail != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11942
			tail->tcp_eager_next_q = tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11943
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11944
			listener->tcp_eager_next_q = tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11945
		listener->tcp_eager_last_q = tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11946
		tcp->tcp_eager_next_q = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11947
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11948
		 * Delay sending up the T_conn_ind until we are
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11949
		 * done with the eager. Once we have have sent up
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11950
		 * the T_conn_ind, the accept can potentially complete
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11951
		 * any time and release the refhold we have on the eager.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11952
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11953
		need_send_conn_ind = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11954
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11955
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11956
		 * Defer connection on q0 and set deferred
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11957
		 * connection bit true
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11958
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11959
		tcp->tcp_conn_def_q0 = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11960
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11961
		/* take tcp out of q0 ... */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11962
		tcp->tcp_eager_prev_q0->tcp_eager_next_q0 =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11963
		    tcp->tcp_eager_next_q0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11964
		tcp->tcp_eager_next_q0->tcp_eager_prev_q0 =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11965
		    tcp->tcp_eager_prev_q0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11966
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11967
		/* ... and place it at the end of q0 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11968
		tcp->tcp_eager_prev_q0 = listener->tcp_eager_prev_q0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11969
		tcp->tcp_eager_next_q0 = listener;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11970
		listener->tcp_eager_prev_q0->tcp_eager_next_q0 = tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11971
		listener->tcp_eager_prev_q0 = tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11972
		tcp->tcp_conn.tcp_eager_conn_ind = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11973
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11974
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11975
	/* we have timed out before */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11976
	if (tcp->tcp_syn_rcvd_timeout != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11977
		tcp->tcp_syn_rcvd_timeout = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11978
		listener->tcp_syn_rcvd_timeout--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11979
		if (listener->tcp_syn_defense &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11980
		    listener->tcp_syn_rcvd_timeout <=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11981
		    (tcp_conn_req_max_q0 >> 5) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11982
		    10*MINUTES < TICK_TO_MSEC(lbolt64 -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11983
			listener->tcp_last_rcv_lbolt)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11984
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11985
			 * Turn off the defense mode if we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11986
			 * believe the SYN attack is over.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11987
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11988
			listener->tcp_syn_defense = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11989
			if (listener->tcp_ip_addr_cache) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11990
				kmem_free((void *)listener->tcp_ip_addr_cache,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11991
				    IP_ADDR_CACHE_SIZE * sizeof (ipaddr_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11992
				listener->tcp_ip_addr_cache = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11993
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11994
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11995
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11996
	addr_cache = (ipaddr_t *)(listener->tcp_ip_addr_cache);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11997
	if (addr_cache != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11998
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11999
		 * We have finished a 3-way handshake with this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12000
		 * remote host. This proves the IP addr is good.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12001
		 * Cache it!
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12002
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12003
		addr_cache[IP_ADDR_CACHE_HASH(
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12004
			tcp->tcp_remote)] = tcp->tcp_remote;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12005
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12006
	mutex_exit(&listener->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12007
	if (need_send_conn_ind)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12008
		putnext(listener->tcp_rq, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12009
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12010
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12011
mblk_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12012
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
 12013
    uint_t *ifindexp, ip6_pkt_t *ippp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12014
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12015
	in_pktinfo_t	*pinfo;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12016
	ip6_t		*ip6h;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12017
	uchar_t		*rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12018
	mblk_t		*first_mp = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12019
	boolean_t	mctl_present = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12020
	uint_t 		ifindex = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12021
	ip6_pkt_t	ipp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12022
	uint_t		ipvers;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12023
	uint_t		ip_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12024
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12025
	rptr = mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12026
	ASSERT(OK_32PTR(rptr));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12027
	ASSERT(tcp != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12028
	ipp.ipp_fields = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12029
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12030
	switch DB_TYPE(mp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12031
	case M_CTL:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12032
		mp = mp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12033
		if (mp == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12034
			freemsg(first_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12035
			return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12036
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12037
		if (DB_TYPE(mp) != M_DATA) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12038
			freemsg(first_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12039
			return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12040
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12041
		mctl_present = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12042
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12043
	case M_DATA:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12044
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12045
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12046
		cmn_err(CE_NOTE, "tcp_find_pktinfo: unknown db_type");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12047
		freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12048
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12049
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12050
	ipvers = IPH_HDR_VERSION(rptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12051
	if (ipvers == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12052
		if (tcp == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12053
			ip_hdr_len = IPH_HDR_LENGTH(rptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12054
			goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12055
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12056
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12057
		ipp.ipp_fields |= IPPF_HOPLIMIT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12058
		ipp.ipp_hoplimit = ((ipha_t *)rptr)->ipha_ttl;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12059
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12060
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12061
		 * If we have IN_PKTINFO in an M_CTL and tcp_ipv6_recvancillary
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12062
		 * has TCP_IPV6_RECVPKTINFO set, pass I/F index along in ipp.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12063
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12064
		if ((tcp->tcp_ipv6_recvancillary & TCP_IPV6_RECVPKTINFO) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12065
		    mctl_present) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12066
			pinfo = (in_pktinfo_t *)first_mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12067
			if ((MBLKL(first_mp) == sizeof (in_pktinfo_t)) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12068
			    (pinfo->in_pkt_ulp_type == IN_PKTINFO) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12069
			    (pinfo->in_pkt_flags & IPF_RECVIF)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12070
				ipp.ipp_fields |= IPPF_IFINDEX;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12071
				ipp.ipp_ifindex = pinfo->in_pkt_ifindex;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12072
				ifindex = pinfo->in_pkt_ifindex;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12073
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12074
			freeb(first_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12075
			mctl_present = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12076
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12077
		ip_hdr_len = IPH_HDR_LENGTH(rptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12078
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12079
		ip6h = (ip6_t *)rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12080
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12081
		ASSERT(ipvers == IPV6_VERSION);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12082
		ipp.ipp_fields = IPPF_HOPLIMIT | IPPF_TCLASS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12083
		ipp.ipp_tclass = (ip6h->ip6_flow & 0x0FF00000) >> 20;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12084
		ipp.ipp_hoplimit = ip6h->ip6_hops;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12085
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12086
		if (ip6h->ip6_nxt != IPPROTO_TCP) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12087
			uint8_t	nexthdrp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12088
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12089
			/* Look for ifindex information */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12090
			if (ip6h->ip6_nxt == IPPROTO_RAW) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12091
				ip6i_t *ip6i = (ip6i_t *)ip6h;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12092
				if ((uchar_t *)&ip6i[1] > mp->b_wptr) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12093
					BUMP_MIB(&ip_mib, tcpInErrs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12094
					freemsg(first_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12095
					return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12096
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12097
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12098
				if (ip6i->ip6i_flags & IP6I_IFINDEX) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12099
					ASSERT(ip6i->ip6i_ifindex != 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12100
					ipp.ipp_fields |= IPPF_IFINDEX;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12101
					ipp.ipp_ifindex = ip6i->ip6i_ifindex;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12102
					ifindex = ip6i->ip6i_ifindex;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12103
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12104
				rptr = (uchar_t *)&ip6i[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12105
				mp->b_rptr = rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12106
				if (rptr == mp->b_wptr) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12107
					mblk_t *mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12108
					mp1 = mp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12109
					freeb(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12110
					mp = mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12111
					rptr = mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12112
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12113
				if (MBLKL(mp) < IPV6_HDR_LEN +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12114
				    sizeof (tcph_t)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12115
					BUMP_MIB(&ip_mib, tcpInErrs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12116
					freemsg(first_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12117
					return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12118
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12119
				ip6h = (ip6_t *)rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12120
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12121
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12122
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12123
			 * Find any potentially interesting extension headers
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12124
			 * as well as the length of the IPv6 + extension
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12125
			 * headers.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12126
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12127
			ip_hdr_len = ip_find_hdr_v6(mp, ip6h, &ipp, &nexthdrp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12128
			/* Verify if this is a TCP packet */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12129
			if (nexthdrp != IPPROTO_TCP) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12130
				BUMP_MIB(&ip_mib, tcpInErrs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12131
				freemsg(first_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12132
				return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12133
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12134
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12135
			ip_hdr_len = IPV6_HDR_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12136
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12137
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12138
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12139
done:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12140
	if (ipversp != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12141
		*ipversp = ipvers;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12142
	if (ip_hdr_lenp != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12143
		*ip_hdr_lenp = ip_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12144
	if (ippp != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12145
		*ippp = ipp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12146
	if (ifindexp != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12147
		*ifindexp = ifindex;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12148
	if (mctl_present) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12149
		freeb(first_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12150
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12151
	return (mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12152
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12153
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12154
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12155
 * Handle M_DATA messages from IP. Its called directly from IP via
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12156
 * squeue for AF_INET type sockets fast path. No M_CTL are expected
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12157
 * in this path.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12158
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12159
 * For everything else (including AF_INET6 sockets with 'tcp_ipversion'
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12160
 * v4 and v6), we are called through tcp_input() and a M_CTL can
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12161
 * be present for options but tcp_find_pktinfo() deals with it. We
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12162
 * only expect M_DATA packets after tcp_find_pktinfo() is done.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12163
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12164
 * The first argument is always the connp/tcp to which the mp belongs.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12165
 * There are no exceptions to this rule. The caller has already put
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12166
 * a reference on this connp/tcp and once tcp_rput_data() returns,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12167
 * the squeue will do the refrele.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12168
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12169
 * The TH_SYN for the listener directly go to tcp_conn_request via
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12170
 * squeue.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12171
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12172
 * sqp: NULL = recursive, sqp != NULL means called from squeue
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12173
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12174
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12175
tcp_rput_data(void *arg, mblk_t *mp, void *arg2)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12176
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12177
	int32_t		bytes_acked;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12178
	int32_t		gap;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12179
	mblk_t		*mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12180
	uint_t		flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12181
	uint32_t	new_swnd = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12182
	uchar_t		*iphdr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12183
	uchar_t		*rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12184
	int32_t		rgap;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12185
	uint32_t	seg_ack;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12186
	int		seg_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12187
	uint_t		ip_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12188
	uint32_t	seg_seq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12189
	tcph_t		*tcph;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12190
	int		urp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12191
	tcp_opt_t	tcpopt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12192
	uint_t		ipvers;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12193
	ip6_pkt_t	ipp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12194
	boolean_t	ofo_seg = B_FALSE; /* Out of order segment */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12195
	uint32_t	cwnd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12196
	uint32_t	add;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12197
	int		npkt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12198
	int		mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12199
	conn_t		*connp = (conn_t *)arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12200
	squeue_t	*sqp = (squeue_t *)arg2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12201
	tcp_t		*tcp = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12202
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12203
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12204
	 * RST from fused tcp loopback peer should trigger an unfuse.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12205
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12206
	if (tcp->tcp_fused) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12207
		TCP_STAT(tcp_fusion_aborted);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12208
		tcp_unfuse(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12209
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12210
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12211
	iphdr = mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12212
	rptr = mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12213
	ASSERT(OK_32PTR(rptr));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12214
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12215
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12216
	 * An AF_INET socket is not capable of receiving any pktinfo. Do inline
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12217
	 * processing here. For rest call tcp_find_pktinfo to fill up the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12218
	 * necessary information.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12219
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12220
	if (IPCL_IS_TCP4(connp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12221
		ipvers = IPV4_VERSION;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12222
		ip_hdr_len = IPH_HDR_LENGTH(rptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12223
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12224
		mp = tcp_find_pktinfo(tcp, mp, &ipvers, &ip_hdr_len,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12225
		    NULL, &ipp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12226
		if (mp == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12227
			TCP_STAT(tcp_rput_v6_error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12228
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12229
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12230
		iphdr = mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12231
		rptr = mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12232
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12233
	ASSERT(DB_TYPE(mp) == M_DATA);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12234
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12235
	tcph = (tcph_t *)&rptr[ip_hdr_len];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12236
	seg_seq = ABE32_TO_U32(tcph->th_seq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12237
	seg_ack = ABE32_TO_U32(tcph->th_ack);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12238
	ASSERT((uintptr_t)(mp->b_wptr - rptr) <= (uintptr_t)INT_MAX);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12239
	seg_len = (int)(mp->b_wptr - rptr) -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12240
	    (ip_hdr_len + TCP_HDR_LENGTH(tcph));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12241
	if ((mp1 = mp->b_cont) != NULL && mp1->b_datap->db_type == M_DATA) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12242
		do {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12243
			ASSERT((uintptr_t)(mp1->b_wptr - mp1->b_rptr) <=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12244
			    (uintptr_t)INT_MAX);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12245
			seg_len += (int)(mp1->b_wptr - mp1->b_rptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12246
		} while ((mp1 = mp1->b_cont) != NULL &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12247
		    mp1->b_datap->db_type == M_DATA);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12248
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12249
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12250
	if (tcp->tcp_state == TCPS_TIME_WAIT) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12251
		tcp_time_wait_processing(tcp, mp, seg_seq, seg_ack,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12252
		    seg_len, tcph);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12253
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12254
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12255
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12256
	if (sqp != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12257
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12258
		 * This is the correct place to update tcp_last_recv_time. Note
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12259
		 * that it is also updated for tcp structure that belongs to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12260
		 * global and listener queues which do not really need updating.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12261
		 * But that should not cause any harm.  And it is updated for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12262
		 * all kinds of incoming segments, not only for data segments.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12263
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12264
		tcp->tcp_last_recv_time = lbolt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12265
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12266
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12267
	flags = (unsigned int)tcph->th_flags[0] & 0xFF;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12268
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12269
	BUMP_LOCAL(tcp->tcp_ibsegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12270
	TCP_RECORD_TRACE(tcp, mp, TCP_TRACE_RECV_PKT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12271
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12272
	if ((flags & TH_URG) && sqp != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12273
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12274
		 * TCP can't handle urgent pointers that arrive before
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12275
		 * the connection has been accept()ed since it can't
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12276
		 * buffer OOB data.  Discard segment if this happens.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12277
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12278
		 * Nor can it reassemble urgent pointers, so discard
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12279
		 * if it's not the next segment expected.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12280
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12281
		 * Otherwise, collapse chain into one mblk (discard if
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12282
		 * that fails).  This makes sure the headers, retransmitted
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12283
		 * data, and new data all are in the same mblk.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12284
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12285
		ASSERT(mp != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12286
		if (tcp->tcp_listener || !pullupmsg(mp, -1)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12287
			freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12288
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12289
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12290
		/* Update pointers into message */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12291
		iphdr = rptr = mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12292
		tcph = (tcph_t *)&rptr[ip_hdr_len];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12293
		if (SEQ_GT(seg_seq, tcp->tcp_rnxt)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12294
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12295
			 * Since we can't handle any data with this urgent
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12296
			 * pointer that is out of sequence, we expunge
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12297
			 * the data.  This allows us to still register
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12298
			 * the urgent mark and generate the M_PCSIG,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12299
			 * which we can do.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12300
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12301
			mp->b_wptr = (uchar_t *)tcph + TCP_HDR_LENGTH(tcph);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12302
			seg_len = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12303
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12304
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12305
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12306
	switch (tcp->tcp_state) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12307
	case TCPS_SYN_SENT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12308
		if (flags & TH_ACK) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12309
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12310
			 * Note that our stack cannot send data before a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12311
			 * connection is established, therefore the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12312
			 * following check is valid.  Otherwise, it has
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12313
			 * to be changed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12314
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12315
			if (SEQ_LEQ(seg_ack, tcp->tcp_iss) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12316
			    SEQ_GT(seg_ack, tcp->tcp_snxt)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12317
				freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12318
				if (flags & TH_RST)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12319
					return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12320
				tcp_xmit_ctl("TCPS_SYN_SENT-Bad_seq",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12321
				    tcp, seg_ack, 0, TH_RST);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12322
				return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12323
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12324
			ASSERT(tcp->tcp_suna + 1 == seg_ack);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12325
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12326
		if (flags & TH_RST) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12327
			freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12328
			if (flags & TH_ACK)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12329
				(void) tcp_clean_death(tcp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12330
				    ECONNREFUSED, 13);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12331
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12332
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12333
		if (!(flags & TH_SYN)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12334
			freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12335
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12336
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12337
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12338
		/* Process all TCP options. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12339
		tcp_process_options(tcp, tcph);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12340
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12341
		 * The following changes our rwnd to be a multiple of the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12342
		 * MIN(peer MSS, our MSS) for performance reason.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12343
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12344
		(void) tcp_rwnd_set(tcp, MSS_ROUNDUP(tcp->tcp_rq->q_hiwat,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12345
		    tcp->tcp_mss));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12346
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12347
		/* Is the other end ECN capable? */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12348
		if (tcp->tcp_ecn_ok) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12349
			if ((flags & (TH_ECE|TH_CWR)) != TH_ECE) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12350
				tcp->tcp_ecn_ok = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12351
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12352
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12353
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12354
		 * Clear ECN flags because it may interfere with later
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12355
		 * processing.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12356
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12357
		flags &= ~(TH_ECE|TH_CWR);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12358
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12359
		tcp->tcp_irs = seg_seq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12360
		tcp->tcp_rack = seg_seq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12361
		tcp->tcp_rnxt = seg_seq + 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12362
		U32_TO_ABE32(tcp->tcp_rnxt, tcp->tcp_tcph->th_ack);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12363
		if (!TCP_IS_DETACHED(tcp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12364
			/* Allocate room for SACK options if needed. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12365
			if (tcp->tcp_snd_sack_ok) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12366
				(void) mi_set_sth_wroff(tcp->tcp_rq,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12367
				    tcp->tcp_hdr_len + TCPOPT_MAX_SACK_LEN +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12368
				    (tcp->tcp_loopback ? 0 : tcp_wroff_xtra));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12369
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12370
				(void) mi_set_sth_wroff(tcp->tcp_rq,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12371
				    tcp->tcp_hdr_len +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12372
				    (tcp->tcp_loopback ? 0 : tcp_wroff_xtra));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12373
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12374
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12375
		if (flags & TH_ACK) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12376
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12377
			 * If we can't get the confirmation upstream, pretend
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12378
			 * we didn't even see this one.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12379
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12380
			 * XXX: how can we pretend we didn't see it if we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12381
			 * have updated rnxt et. al.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12382
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12383
			 * For loopback we defer sending up the T_CONN_CON
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12384
			 * until after some checks below.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12385
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12386
			mp1 = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12387
			if (!tcp_conn_con(tcp, iphdr, tcph, mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12388
			    tcp->tcp_loopback ? &mp1 : NULL)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12389
				freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12390
				return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12391
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12392
			/* SYN was acked - making progress */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12393
			if (tcp->tcp_ipversion == IPV6_VERSION)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12394
				tcp->tcp_ip_forward_progress = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12395
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12396
			/* One for the SYN */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12397
			tcp->tcp_suna = tcp->tcp_iss + 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12398
			tcp->tcp_valid_bits &= ~TCP_ISS_VALID;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12399
			tcp->tcp_state = TCPS_ESTABLISHED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12400
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12401
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12402
			 * If SYN was retransmitted, need to reset all
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12403
			 * retransmission info.  This is because this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12404
			 * segment will be treated as a dup ACK.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12405
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12406
			if (tcp->tcp_rexmit) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12407
				tcp->tcp_rexmit = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12408
				tcp->tcp_rexmit_nxt = tcp->tcp_snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12409
				tcp->tcp_rexmit_max = tcp->tcp_snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12410
				tcp->tcp_snd_burst = tcp->tcp_localnet ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12411
				    TCP_CWND_INFINITE : TCP_CWND_NORMAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12412
				tcp->tcp_ms_we_have_waited = 0;
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
				 * Set tcp_cwnd back to 1 MSS, per
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12416
				 * recommendation from
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12417
				 * draft-floyd-incr-init-win-01.txt,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12418
				 * Increasing TCP's Initial Window.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12419
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12420
				tcp->tcp_cwnd = tcp->tcp_mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12421
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12422
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12423
			tcp->tcp_swl1 = seg_seq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12424
			tcp->tcp_swl2 = seg_ack;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12425
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12426
			new_swnd = BE16_TO_U16(tcph->th_win);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12427
			tcp->tcp_swnd = new_swnd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12428
			if (new_swnd > tcp->tcp_max_swnd)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12429
				tcp->tcp_max_swnd = new_swnd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12430
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12431
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12432
			 * Always send the three-way handshake ack immediately
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12433
			 * in order to make the connection complete as soon as
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12434
			 * possible on the accepting host.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12435
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12436
			flags |= TH_ACK_NEEDED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12437
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12438
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12439
			 * Special case for loopback.  At this point we have
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12440
			 * received SYN-ACK from the remote endpoint.  In
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12441
			 * order to ensure that both endpoints reach the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12442
			 * fused state prior to any data exchange, the final
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12443
			 * ACK needs to be sent before we indicate T_CONN_CON
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12444
			 * to the module upstream.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12445
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12446
			if (tcp->tcp_loopback) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12447
				mblk_t *ack_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12448
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12449
				ASSERT(!tcp->tcp_unfusable);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12450
				ASSERT(mp1 != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12451
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12452
				 * For loopback, we always get a pure SYN-ACK
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12453
				 * and only need to send back the final ACK
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12454
				 * with no data (this is because the other
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12455
				 * tcp is ours and we don't do T/TCP).  This
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12456
				 * final ACK triggers the passive side to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12457
				 * perform fusion in ESTABLISHED state.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12458
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12459
				if ((ack_mp = tcp_ack_mp(tcp)) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12460
					if (tcp->tcp_ack_tid != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12461
						(void) TCP_TIMER_CANCEL(tcp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12462
						    tcp->tcp_ack_tid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12463
						tcp->tcp_ack_tid = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12464
					}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12465
					TCP_RECORD_TRACE(tcp, ack_mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12466
					    TCP_TRACE_SEND_PKT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12467
					tcp_send_data(tcp, tcp->tcp_wq, ack_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12468
					BUMP_LOCAL(tcp->tcp_obsegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12469
					BUMP_MIB(&tcp_mib, tcpOutAck);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12470
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12471
					/* Send up T_CONN_CON */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12472
					putnext(tcp->tcp_rq, mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12473
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12474
					freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12475
					return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12476
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12477
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12478
				 * Forget fusion; we need to handle more
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12479
				 * complex cases below.  Send the deferred
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12480
				 * T_CONN_CON message upstream and proceed
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12481
				 * as usual.  Mark this tcp as not capable
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12482
				 * of fusion.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12483
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12484
				TCP_STAT(tcp_fusion_unfusable);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12485
				tcp->tcp_unfusable = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12486
				putnext(tcp->tcp_rq, mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12487
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12488
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12489
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12490
			 * Check to see if there is data to be sent.  If
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12491
			 * yes, set the transmit flag.  Then check to see
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12492
			 * if received data processing needs to be done.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12493
			 * If not, go straight to xmit_check.  This short
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12494
			 * cut is OK as we don't support T/TCP.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12495
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12496
			if (tcp->tcp_unsent)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12497
				flags |= TH_XMIT_NEEDED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12498
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12499
			if (seg_len == 0 && !(flags & TH_URG)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12500
				freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12501
				goto xmit_check;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12502
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12503
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12504
			flags &= ~TH_SYN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12505
			seg_seq++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12506
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12507
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12508
		tcp->tcp_state = TCPS_SYN_RCVD;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12509
		mp1 = tcp_xmit_mp(tcp, tcp->tcp_xmit_head, tcp->tcp_mss,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12510
		    NULL, NULL, tcp->tcp_iss, B_FALSE, NULL, B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12511
		if (mp1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12512
			mblk_setcred(mp1, tcp->tcp_cred);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12513
			DB_CPID(mp1) = tcp->tcp_cpid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12514
			TCP_RECORD_TRACE(tcp, mp1, TCP_TRACE_SEND_PKT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12515
			tcp_send_data(tcp, tcp->tcp_wq, mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12516
			TCP_TIMER_RESTART(tcp, tcp->tcp_rto);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12517
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12518
		freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12519
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12520
	case TCPS_SYN_RCVD:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12521
		if (flags & TH_ACK) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12522
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12523
			 * In this state, a SYN|ACK packet is either bogus
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12524
			 * because the other side must be ACKing our SYN which
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12525
			 * indicates it has seen the ACK for their SYN and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12526
			 * shouldn't retransmit it or we're crossing SYNs
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12527
			 * on active open.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12528
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12529
			if ((flags & TH_SYN) && !tcp->tcp_active_open) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12530
				freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12531
				tcp_xmit_ctl("TCPS_SYN_RCVD-bad_syn",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12532
				    tcp, seg_ack, 0, TH_RST);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12533
				return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12534
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12535
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12536
			 * NOTE: RFC 793 pg. 72 says this should be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12537
			 * tcp->tcp_suna <= seg_ack <= tcp->tcp_snxt
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12538
			 * but that would mean we have an ack that ignored
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12539
			 * our SYN.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12540
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12541
			if (SEQ_LEQ(seg_ack, tcp->tcp_suna) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12542
			    SEQ_GT(seg_ack, tcp->tcp_snxt)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12543
				freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12544
				tcp_xmit_ctl("TCPS_SYN_RCVD-bad_ack",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12545
				    tcp, seg_ack, 0, TH_RST);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12546
				return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12547
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12548
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12549
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12550
	case TCPS_LISTEN:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12551
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12552
		 * Only a TLI listener can come through this path when a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12553
		 * acceptor is going back to be a listener and a packet
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12554
		 * for the acceptor hits the classifier. For a socket
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12555
		 * listener, this can never happen because a listener
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12556
		 * can never accept connection on itself and hence a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12557
		 * socket acceptor can not go back to being a listener.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12558
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12559
		ASSERT(!TCP_IS_SOCKET(tcp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12560
		/*FALLTHRU*/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12561
	case TCPS_CLOSED:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12562
	case TCPS_BOUND: {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12563
		conn_t	*new_connp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12564
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12565
		new_connp = ipcl_classify(mp, connp->conn_zoneid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12566
		if (new_connp != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12567
			tcp_reinput(new_connp, mp, connp->conn_sqp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12568
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12569
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12570
		/* We failed to classify. For now just drop the packet */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12571
		freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12572
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12573
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12574
	case TCPS_IDLE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12575
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12576
		 * Handle the case where the tcp_clean_death() has happened
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12577
		 * on a connection (application hasn't closed yet) but a packet
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12578
		 * was already queued on squeue before tcp_clean_death()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12579
		 * was processed. Calling tcp_clean_death() twice on same
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12580
		 * connection can result in weird behaviour.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12581
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12582
		freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12583
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12584
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12585
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12586
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12587
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12588
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12589
	 * Already on the correct queue/perimeter.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12590
	 * If this is a detached connection and not an eager
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12591
	 * connection hanging off a listener then new data
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12592
	 * (past the FIN) will cause a reset.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12593
	 * We do a special check here where it
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12594
	 * is out of the main line, rather than check
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12595
	 * if we are detached every time we see new
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12596
	 * data down below.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12597
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12598
	if (TCP_IS_DETACHED_NONEAGER(tcp) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12599
	    (seg_len > 0 && SEQ_GT(seg_seq + seg_len, tcp->tcp_rnxt))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12600
		BUMP_MIB(&tcp_mib, tcpInClosed);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12601
		TCP_RECORD_TRACE(tcp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12602
		    mp, TCP_TRACE_RECV_PKT);
898
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 12603
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12604
		freemsg(mp);
898
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 12605
		/*
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 12606
		 * This could be an SSL closure alert. We're detached so just
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 12607
		 * acknowledge it this last time.
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 12608
		 */
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 12609
		if (tcp->tcp_kssl_ctx != NULL) {
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 12610
			kssl_release_ctx(tcp->tcp_kssl_ctx);
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 12611
			tcp->tcp_kssl_ctx = NULL;
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 12612
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 12613
			tcp->tcp_rnxt += seg_len;
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 12614
			U32_TO_ABE32(tcp->tcp_rnxt, tcp->tcp_tcph->th_ack);
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 12615
			flags |= TH_ACK_NEEDED;
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 12616
			goto ack_check;
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 12617
		}
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 12618
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12619
		tcp_xmit_ctl("new data when detached", tcp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12620
		    tcp->tcp_snxt, 0, TH_RST);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12621
		(void) tcp_clean_death(tcp, EPROTO, 12);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12622
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12623
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12624
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12625
	mp->b_rptr = (uchar_t *)tcph + TCP_HDR_LENGTH(tcph);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12626
	urp = BE16_TO_U16(tcph->th_urp) - TCP_OLD_URP_INTERPRETATION;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12627
	new_swnd = BE16_TO_U16(tcph->th_win) <<
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12628
	    ((tcph->th_flags[0] & TH_SYN) ? 0 : tcp->tcp_snd_ws);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12629
	mss = tcp->tcp_mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12630
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12631
	if (tcp->tcp_snd_ts_ok) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12632
		if (!tcp_paws_check(tcp, tcph, &tcpopt)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12633
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12634
			 * This segment is not acceptable.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12635
			 * Drop it and send back an ACK.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12636
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12637
			freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12638
			flags |= TH_ACK_NEEDED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12639
			goto ack_check;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12640
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12641
	} else if (tcp->tcp_snd_sack_ok) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12642
		ASSERT(tcp->tcp_sack_info != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12643
		tcpopt.tcp = tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12644
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12645
		 * SACK info in already updated in tcp_parse_options.  Ignore
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12646
		 * all other TCP options...
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12647
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12648
		(void) tcp_parse_options(tcph, &tcpopt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12649
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12650
try_again:;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12651
	gap = seg_seq - tcp->tcp_rnxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12652
	rgap = tcp->tcp_rwnd - (gap + seg_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12653
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12654
	 * gap is the amount of sequence space between what we expect to see
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12655
	 * and what we got for seg_seq.  A positive value for gap means
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12656
	 * something got lost.  A negative value means we got some old stuff.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12657
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12658
	if (gap < 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12659
		/* Old stuff present.  Is the SYN in there? */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12660
		if (seg_seq == tcp->tcp_irs && (flags & TH_SYN) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12661
		    (seg_len != 0)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12662
			flags &= ~TH_SYN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12663
			seg_seq++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12664
			urp--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12665
			/* Recompute the gaps after noting the SYN. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12666
			goto try_again;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12667
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12668
		BUMP_MIB(&tcp_mib, tcpInDataDupSegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12669
		UPDATE_MIB(&tcp_mib, tcpInDataDupBytes,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12670
		    (seg_len > -gap ? -gap : seg_len));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12671
		/* Remove the old stuff from seg_len. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12672
		seg_len += gap;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12673
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12674
		 * Anything left?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12675
		 * Make sure to check for unack'd FIN when rest of data
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12676
		 * has been previously ack'd.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12677
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12678
		if (seg_len < 0 || (seg_len == 0 && !(flags & TH_FIN))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12679
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12680
			 * Resets are only valid if they lie within our offered
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12681
			 * window.  If the RST bit is set, we just ignore this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12682
			 * segment.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12683
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12684
			if (flags & TH_RST) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12685
				freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12686
				return;
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
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12690
			 * The arriving of dup data packets indicate that we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12691
			 * may have postponed an ack for too long, or the other
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12692
			 * side's RTT estimate is out of shape. Start acking
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12693
			 * more often.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12694
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12695
			if (SEQ_GEQ(seg_seq + seg_len - gap, tcp->tcp_rack) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12696
			    tcp->tcp_rack_cnt >= 1 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12697
			    tcp->tcp_rack_abs_max > 2) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12698
				tcp->tcp_rack_abs_max--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12699
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12700
			tcp->tcp_rack_cur_max = 1;
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
			 * This segment is "unacceptable".  None of its
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12704
			 * sequence space lies within our advertized window.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12705
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12706
			 * Adjust seg_len to the original value for tracing.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12707
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12708
			seg_len -= gap;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12709
			if (tcp->tcp_debug) {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 12710
				(void) strlog(TCP_MOD_ID, 0, 1, SL_TRACE,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12711
				    "tcp_rput: unacceptable, gap %d, rgap %d, "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12712
				    "flags 0x%x, seg_seq %u, seg_ack %u, "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12713
				    "seg_len %d, rnxt %u, snxt %u, %s",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12714
				    gap, rgap, flags, seg_seq, seg_ack,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12715
				    seg_len, tcp->tcp_rnxt, tcp->tcp_snxt,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12716
				    tcp_display(tcp, NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12717
				    DISP_ADDR_AND_PORT));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12718
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12719
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12720
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12721
			 * Arrange to send an ACK in response to the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12722
			 * unacceptable segment per RFC 793 page 69. There
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12723
			 * is only one small difference between ours and the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12724
			 * acceptability test in the RFC - we accept ACK-only
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12725
			 * packet with SEG.SEQ = RCV.NXT+RCV.WND and no ACK
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12726
			 * will be generated.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12727
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12728
			 * Note that we have to ACK an ACK-only packet at least
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12729
			 * for stacks that send 0-length keep-alives with
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12730
			 * SEG.SEQ = SND.NXT-1 as recommended by RFC1122,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12731
			 * section 4.2.3.6. As long as we don't ever generate
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12732
			 * an unacceptable packet in response to an incoming
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12733
			 * packet that is unacceptable, it should not cause
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12734
			 * "ACK wars".
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12735
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12736
			flags |=  TH_ACK_NEEDED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12737
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12738
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12739
			 * Continue processing this segment in order to use the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12740
			 * ACK information it contains, but skip all other
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12741
			 * sequence-number processing.	Processing the ACK
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12742
			 * information is necessary in order to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12743
			 * re-synchronize connections that may have lost
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12744
			 * synchronization.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12745
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12746
			 * We clear seg_len and flag fields related to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12747
			 * sequence number processing as they are not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12748
			 * to be trusted for an unacceptable segment.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12749
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12750
			seg_len = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12751
			flags &= ~(TH_SYN | TH_FIN | TH_URG);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12752
			goto process_ack;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12753
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12754
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12755
		/* Fix seg_seq, and chew the gap off the front. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12756
		seg_seq = tcp->tcp_rnxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12757
		urp += gap;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12758
		do {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12759
			mblk_t	*mp2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12760
			ASSERT((uintptr_t)(mp->b_wptr - mp->b_rptr) <=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12761
			    (uintptr_t)UINT_MAX);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12762
			gap += (uint_t)(mp->b_wptr - mp->b_rptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12763
			if (gap > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12764
				mp->b_rptr = mp->b_wptr - gap;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12765
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12766
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12767
			mp2 = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12768
			mp = mp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12769
			freeb(mp2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12770
		} while (gap < 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12771
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12772
		 * If the urgent data has already been acknowledged, we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12773
		 * should ignore TH_URG below
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12774
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12775
		if (urp < 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12776
			flags &= ~TH_URG;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12777
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12778
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12779
	 * rgap is the amount of stuff received out of window.  A negative
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12780
	 * value is the amount out of window.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12781
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12782
	if (rgap < 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12783
		mblk_t	*mp2;
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) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12786
			BUMP_MIB(&tcp_mib, tcpInWinProbe);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12787
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12788
			BUMP_MIB(&tcp_mib, tcpInDataPastWinSegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12789
			UPDATE_MIB(&tcp_mib, tcpInDataPastWinBytes, -rgap);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12790
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12791
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12792
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12793
		 * seg_len does not include the FIN, so if more than
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12794
		 * just the FIN is out of window, we act like we don't
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12795
		 * see it.  (If just the FIN is out of window, rgap
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12796
		 * will be zero and we will go ahead and acknowledge
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12797
		 * the FIN.)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12798
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12799
		flags &= ~TH_FIN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12800
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12801
		/* Fix seg_len and make sure there is something left. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12802
		seg_len += rgap;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12803
		if (seg_len <= 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12804
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12805
			 * Resets are only valid if they lie within our offered
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12806
			 * window.  If the RST bit is set, we just ignore this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12807
			 * segment.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12808
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12809
			if (flags & TH_RST) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12810
				freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12811
				return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12812
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12813
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12814
			/* Per RFC 793, we need to send back an ACK. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12815
			flags |= TH_ACK_NEEDED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12816
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12817
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12818
			 * Send SIGURG as soon as possible i.e. even
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12819
			 * if the TH_URG was delivered in a window probe
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12820
			 * packet (which will be unacceptable).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12821
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12822
			 * We generate a signal if none has been generated
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12823
			 * for this connection or if this is a new urgent
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12824
			 * byte. Also send a zero-length "unmarked" message
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12825
			 * to inform SIOCATMARK that this is not the mark.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12826
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12827
			 * tcp_urp_last_valid is cleared when the T_exdata_ind
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12828
			 * is sent up. This plus the check for old data
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12829
			 * (gap >= 0) handles the wraparound of the sequence
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12830
			 * number space without having to always track the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12831
			 * correct MAX(tcp_urp_last, tcp_rnxt). (BSD tracks
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12832
			 * this max in its rcv_up variable).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12833
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12834
			 * This prevents duplicate SIGURGS due to a "late"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12835
			 * zero-window probe when the T_EXDATA_IND has already
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12836
			 * been sent up.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12837
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12838
			if ((flags & TH_URG) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12839
			    (!tcp->tcp_urp_last_valid || SEQ_GT(urp + seg_seq,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12840
			    tcp->tcp_urp_last))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12841
				mp1 = allocb(0, BPRI_MED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12842
				if (mp1 == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12843
					freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12844
					return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12845
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12846
				if (!TCP_IS_DETACHED(tcp) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12847
				    !putnextctl1(tcp->tcp_rq, M_PCSIG,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12848
				    SIGURG)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12849
					/* Try again on the rexmit. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12850
					freemsg(mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12851
					freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12852
					return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12853
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12854
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12855
				 * If the next byte would be the mark
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12856
				 * then mark with MARKNEXT else mark
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12857
				 * with NOTMARKNEXT.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12858
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12859
				if (gap == 0 && urp == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12860
					mp1->b_flag |= MSGMARKNEXT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12861
				else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12862
					mp1->b_flag |= MSGNOTMARKNEXT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12863
				freemsg(tcp->tcp_urp_mark_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12864
				tcp->tcp_urp_mark_mp = mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12865
				flags |= TH_SEND_URP_MARK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12866
				tcp->tcp_urp_last_valid = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12867
				tcp->tcp_urp_last = urp + seg_seq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12868
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12869
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12870
			 * If this is a zero window probe, continue to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12871
			 * process the ACK part.  But we need to set seg_len
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12872
			 * to 0 to avoid data processing.  Otherwise just
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12873
			 * drop the segment and send back an ACK.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12874
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12875
			if (tcp->tcp_rwnd == 0 && seg_seq == tcp->tcp_rnxt) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12876
				flags &= ~(TH_SYN | TH_URG);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12877
				seg_len = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12878
				goto process_ack;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12879
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12880
				freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12881
				goto ack_check;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12882
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12883
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12884
		/* Pitch out of window stuff off the end. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12885
		rgap = seg_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12886
		mp2 = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12887
		do {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12888
			ASSERT((uintptr_t)(mp2->b_wptr - mp2->b_rptr) <=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12889
			    (uintptr_t)INT_MAX);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12890
			rgap -= (int)(mp2->b_wptr - mp2->b_rptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12891
			if (rgap < 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12892
				mp2->b_wptr += rgap;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12893
				if ((mp1 = mp2->b_cont) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12894
					mp2->b_cont = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12895
					freemsg(mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12896
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12897
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12898
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12899
		} while ((mp2 = mp2->b_cont) != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12900
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12901
ok:;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12902
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12903
	 * TCP should check ECN info for segments inside the window only.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12904
	 * Therefore the check should be done here.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12905
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12906
	if (tcp->tcp_ecn_ok) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12907
		if (flags & TH_CWR) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12908
			tcp->tcp_ecn_echo_on = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12909
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12910
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12911
		 * Note that both ECN_CE and CWR can be set in the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12912
		 * same segment.  In this case, we once again turn
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12913
		 * on ECN_ECHO.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12914
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12915
		if (tcp->tcp_ipversion == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12916
			uchar_t tos = ((ipha_t *)rptr)->ipha_type_of_service;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12917
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12918
			if ((tos & IPH_ECN_CE) == IPH_ECN_CE) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12919
				tcp->tcp_ecn_echo_on = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12920
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12921
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12922
			uint32_t vcf = ((ip6_t *)rptr)->ip6_vcf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12923
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12924
			if ((vcf & htonl(IPH_ECN_CE << 20)) ==
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12925
			    htonl(IPH_ECN_CE << 20)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12926
				tcp->tcp_ecn_echo_on = B_TRUE;
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
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12930
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12931
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12932
	 * Check whether we can update tcp_ts_recent.  This test is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12933
	 * NOT the one in RFC 1323 3.4.  It is from Braden, 1993, "TCP
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12934
	 * Extensions for High Performance: An Update", Internet Draft.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12935
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12936
	if (tcp->tcp_snd_ts_ok &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12937
	    TSTMP_GEQ(tcpopt.tcp_opt_ts_val, tcp->tcp_ts_recent) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12938
	    SEQ_LEQ(seg_seq, tcp->tcp_rack)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12939
		tcp->tcp_ts_recent = tcpopt.tcp_opt_ts_val;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12940
		tcp->tcp_last_rcv_lbolt = lbolt64;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12941
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12942
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12943
	if (seg_seq != tcp->tcp_rnxt || tcp->tcp_reass_head) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12944
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12945
		 * FIN in an out of order segment.  We record this in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12946
		 * tcp_valid_bits and the seq num of FIN in tcp_ofo_fin_seq.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12947
		 * Clear the FIN so that any check on FIN flag will fail.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12948
		 * Remember that FIN also counts in the sequence number
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12949
		 * space.  So we need to ack out of order FIN only segments.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12950
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12951
		if (flags & TH_FIN) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12952
			tcp->tcp_valid_bits |= TCP_OFO_FIN_VALID;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12953
			tcp->tcp_ofo_fin_seq = seg_seq + seg_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12954
			flags &= ~TH_FIN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12955
			flags |= TH_ACK_NEEDED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12956
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12957
		if (seg_len > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12958
			/* Fill in the SACK blk list. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12959
			if (tcp->tcp_snd_sack_ok) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12960
				ASSERT(tcp->tcp_sack_info != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12961
				tcp_sack_insert(tcp->tcp_sack_list,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12962
				    seg_seq, seg_seq + seg_len,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12963
				    &(tcp->tcp_num_sack_blk));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12964
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12965
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12966
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12967
			 * Attempt reassembly and see if we have something
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12968
			 * ready to go.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12969
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12970
			mp = tcp_reass(tcp, mp, seg_seq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12971
			/* Always ack out of order packets */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12972
			flags |= TH_ACK_NEEDED | TH_PUSH;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12973
			if (mp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12974
				ASSERT((uintptr_t)(mp->b_wptr - mp->b_rptr) <=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12975
				    (uintptr_t)INT_MAX);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12976
				seg_len = mp->b_cont ? msgdsize(mp) :
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12977
					(int)(mp->b_wptr - mp->b_rptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12978
				seg_seq = tcp->tcp_rnxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12979
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12980
				 * A gap is filled and the seq num and len
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12981
				 * of the gap match that of a previously
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12982
				 * received FIN, put the FIN flag back in.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12983
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12984
				if ((tcp->tcp_valid_bits & TCP_OFO_FIN_VALID) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12985
				    seg_seq + seg_len == tcp->tcp_ofo_fin_seq) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12986
					flags |= TH_FIN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12987
					tcp->tcp_valid_bits &=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12988
					    ~TCP_OFO_FIN_VALID;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12989
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12990
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12991
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12992
				 * Keep going even with NULL mp.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12993
				 * There may be a useful ACK or something else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12994
				 * we don't want to miss.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12995
				 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12996
				 * But TCP should not perform fast retransmit
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12997
				 * because of the ack number.  TCP uses
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12998
				 * seg_len == 0 to determine if it is a pure
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12999
				 * ACK.  And this is not a pure ACK.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13000
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13001
				seg_len = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13002
				ofo_seg = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13003
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13004
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13005
	} else if (seg_len > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13006
		BUMP_MIB(&tcp_mib, tcpInDataInorderSegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13007
		UPDATE_MIB(&tcp_mib, tcpInDataInorderBytes, seg_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13008
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13009
		 * If an out of order FIN was received before, and the seq
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13010
		 * num and len of the new segment match that of the FIN,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13011
		 * put the FIN flag back in.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13012
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13013
		if ((tcp->tcp_valid_bits & TCP_OFO_FIN_VALID) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13014
		    seg_seq + seg_len == tcp->tcp_ofo_fin_seq) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13015
			flags |= TH_FIN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13016
			tcp->tcp_valid_bits &= ~TCP_OFO_FIN_VALID;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13017
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13018
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13019
	if ((flags & (TH_RST | TH_SYN | TH_URG | TH_ACK)) != TH_ACK) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13020
	if (flags & TH_RST) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13021
		freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13022
		switch (tcp->tcp_state) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13023
		case TCPS_SYN_RCVD:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13024
			(void) tcp_clean_death(tcp, ECONNREFUSED, 14);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13025
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13026
		case TCPS_ESTABLISHED:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13027
		case TCPS_FIN_WAIT_1:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13028
		case TCPS_FIN_WAIT_2:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13029
		case TCPS_CLOSE_WAIT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13030
			(void) tcp_clean_death(tcp, ECONNRESET, 15);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13031
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13032
		case TCPS_CLOSING:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13033
		case TCPS_LAST_ACK:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13034
			(void) tcp_clean_death(tcp, 0, 16);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13035
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13036
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13037
			ASSERT(tcp->tcp_state != TCPS_TIME_WAIT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13038
			(void) tcp_clean_death(tcp, ENXIO, 17);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13039
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13040
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13041
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13042
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13043
	if (flags & TH_SYN) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13044
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13045
		 * See RFC 793, Page 71
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13046
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13047
		 * The seq number must be in the window as it should
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13048
		 * be "fixed" above.  If it is outside window, it should
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13049
		 * be already rejected.  Note that we allow seg_seq to be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13050
		 * rnxt + rwnd because we want to accept 0 window probe.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13051
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13052
		ASSERT(SEQ_GEQ(seg_seq, tcp->tcp_rnxt) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13053
		    SEQ_LEQ(seg_seq, tcp->tcp_rnxt + tcp->tcp_rwnd));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13054
		freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13055
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13056
		 * If the ACK flag is not set, just use our snxt as the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13057
		 * seq number of the RST segment.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13058
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13059
		if (!(flags & TH_ACK)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13060
			seg_ack = tcp->tcp_snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13061
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13062
		tcp_xmit_ctl("TH_SYN", tcp, seg_ack, seg_seq + 1,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13063
		    TH_RST|TH_ACK);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13064
		ASSERT(tcp->tcp_state != TCPS_TIME_WAIT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13065
		(void) tcp_clean_death(tcp, ECONNRESET, 18);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13066
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13067
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13068
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13069
	 * urp could be -1 when the urp field in the packet is 0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13070
	 * and TCP_OLD_URP_INTERPRETATION is set. This implies that the urgent
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13071
	 * byte was at seg_seq - 1, in which case we ignore the urgent flag.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13072
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13073
	if (flags & TH_URG && urp >= 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13074
		if (!tcp->tcp_urp_last_valid ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13075
		    SEQ_GT(urp + seg_seq, tcp->tcp_urp_last)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13076
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13077
			 * If we haven't generated the signal yet for this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13078
			 * urgent pointer value, do it now.  Also, send up a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13079
			 * zero-length M_DATA indicating whether or not this is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13080
			 * the mark. The latter is not needed when a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13081
			 * T_EXDATA_IND is sent up. However, if there are
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13082
			 * allocation failures this code relies on the sender
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13083
			 * retransmitting and the socket code for determining
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13084
			 * the mark should not block waiting for the peer to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13085
			 * transmit. Thus, for simplicity we always send up the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13086
			 * mark indication.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13087
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13088
			mp1 = allocb(0, BPRI_MED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13089
			if (mp1 == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13090
				freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13091
				return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13092
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13093
			if (!TCP_IS_DETACHED(tcp) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13094
			    !putnextctl1(tcp->tcp_rq, M_PCSIG, SIGURG)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13095
				/* Try again on the rexmit. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13096
				freemsg(mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13097
				freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13098
				return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13099
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13100
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13101
			 * Mark with NOTMARKNEXT for now.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13102
			 * The code below will change this to MARKNEXT
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13103
			 * if we are at the mark.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13104
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13105
			 * If there are allocation failures (e.g. in dupmsg
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13106
			 * below) the next time tcp_rput_data sees the urgent
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13107
			 * segment it will send up the MSG*MARKNEXT message.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13108
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13109
			mp1->b_flag |= MSGNOTMARKNEXT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13110
			freemsg(tcp->tcp_urp_mark_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13111
			tcp->tcp_urp_mark_mp = mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13112
			flags |= TH_SEND_URP_MARK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13113
#ifdef DEBUG
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 13114
			(void) strlog(TCP_MOD_ID, 0, 1, SL_TRACE,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13115
			    "tcp_rput: sent M_PCSIG 2 seq %x urp %x "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13116
			    "last %x, %s",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13117
			    seg_seq, urp, tcp->tcp_urp_last,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13118
			    tcp_display(tcp, NULL, DISP_PORT_ONLY));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13119
#endif /* DEBUG */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13120
			tcp->tcp_urp_last_valid = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13121
			tcp->tcp_urp_last = urp + seg_seq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13122
		} else if (tcp->tcp_urp_mark_mp != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13123
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13124
			 * An allocation failure prevented the previous
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13125
			 * tcp_rput_data from sending up the allocated
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13126
			 * MSG*MARKNEXT message - send it up this time
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13127
			 * around.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13128
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13129
			flags |= TH_SEND_URP_MARK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13130
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13131
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13132
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13133
		 * If the urgent byte is in this segment, make sure that it is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13134
		 * all by itself.  This makes it much easier to deal with the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13135
		 * possibility of an allocation failure on the T_exdata_ind.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13136
		 * Note that seg_len is the number of bytes in the segment, and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13137
		 * urp is the offset into the segment of the urgent byte.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13138
		 * urp < seg_len means that the urgent byte is in this segment.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13139
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13140
		if (urp < seg_len) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13141
			if (seg_len != 1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13142
				uint32_t  tmp_rnxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13143
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13144
				 * Break it up and feed it back in.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13145
				 * Re-attach the IP header.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13146
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13147
				mp->b_rptr = iphdr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13148
				if (urp > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13149
					/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13150
					 * There is stuff before the urgent
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13151
					 * byte.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13152
					 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13153
					mp1 = dupmsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13154
					if (!mp1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13155
						/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13156
						 * Trim from urgent byte on.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13157
						 * The rest will come back.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13158
						 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13159
						(void) adjmsg(mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13160
						    urp - seg_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13161
						tcp_rput_data(connp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13162
						    mp, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13163
						return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13164
					}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13165
					(void) adjmsg(mp1, urp - seg_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13166
					/* Feed this piece back in. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13167
					tmp_rnxt = tcp->tcp_rnxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13168
					tcp_rput_data(connp, mp1, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13169
					/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13170
					 * If the data passed back in was not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13171
					 * processed (ie: bad ACK) sending
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13172
					 * the remainder back in will cause a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13173
					 * loop. In this case, drop the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13174
					 * packet and let the sender try
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13175
					 * sending a good packet.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13176
					 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13177
					if (tmp_rnxt == tcp->tcp_rnxt) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13178
						freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13179
						return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13180
					}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13181
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13182
				if (urp != seg_len - 1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13183
					uint32_t  tmp_rnxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13184
					/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13185
					 * There is stuff after the urgent
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13186
					 * byte.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13187
					 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13188
					mp1 = dupmsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13189
					if (!mp1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13190
						/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13191
						 * Trim everything beyond the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13192
						 * urgent byte.  The rest will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13193
						 * come back.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13194
						 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13195
						(void) adjmsg(mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13196
						    urp + 1 - seg_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13197
						tcp_rput_data(connp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13198
						    mp, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13199
						return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13200
					}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13201
					(void) adjmsg(mp1, urp + 1 - seg_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13202
					tmp_rnxt = tcp->tcp_rnxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13203
					tcp_rput_data(connp, mp1, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13204
					/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13205
					 * If the data passed back in was not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13206
					 * processed (ie: bad ACK) sending
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13207
					 * the remainder back in will cause a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13208
					 * loop. In this case, drop the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13209
					 * packet and let the sender try
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13210
					 * sending a good packet.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13211
					 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13212
					if (tmp_rnxt == tcp->tcp_rnxt) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13213
						freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13214
						return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13215
					}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13216
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13217
				tcp_rput_data(connp, mp, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13218
				return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13219
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13220
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13221
			 * This segment contains only the urgent byte.  We
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13222
			 * have to allocate the T_exdata_ind, if we can.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13223
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13224
			if (!tcp->tcp_urp_mp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13225
				struct T_exdata_ind *tei;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13226
				mp1 = allocb(sizeof (struct T_exdata_ind),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13227
				    BPRI_MED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13228
				if (!mp1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13229
					/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13230
					 * Sigh... It'll be back.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13231
					 * Generate any MSG*MARK message now.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13232
					 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13233
					freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13234
					seg_len = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13235
					if (flags & TH_SEND_URP_MARK) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13236
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13237
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13238
						ASSERT(tcp->tcp_urp_mark_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13239
						tcp->tcp_urp_mark_mp->b_flag &=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13240
							~MSGNOTMARKNEXT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13241
						tcp->tcp_urp_mark_mp->b_flag |=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13242
							MSGMARKNEXT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13243
					}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13244
					goto ack_check;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13245
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13246
				mp1->b_datap->db_type = M_PROTO;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13247
				tei = (struct T_exdata_ind *)mp1->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13248
				tei->PRIM_type = T_EXDATA_IND;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13249
				tei->MORE_flag = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13250
				mp1->b_wptr = (uchar_t *)&tei[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13251
				tcp->tcp_urp_mp = mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13252
#ifdef DEBUG
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 13253
				(void) strlog(TCP_MOD_ID, 0, 1, SL_TRACE,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13254
				    "tcp_rput: allocated exdata_ind %s",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13255
				    tcp_display(tcp, NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13256
				    DISP_PORT_ONLY));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13257
#endif /* DEBUG */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13258
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13259
				 * There is no need to send a separate MSG*MARK
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13260
				 * message since the T_EXDATA_IND will be sent
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13261
				 * now.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13262
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13263
				flags &= ~TH_SEND_URP_MARK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13264
				freemsg(tcp->tcp_urp_mark_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13265
				tcp->tcp_urp_mark_mp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13266
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13267
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13268
			 * Now we are all set.  On the next putnext upstream,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13269
			 * tcp_urp_mp will be non-NULL and will get prepended
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13270
			 * to what has to be this piece containing the urgent
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13271
			 * byte.  If for any reason we abort this segment below,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13272
			 * if it comes back, we will have this ready, or it
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13273
			 * will get blown off in close.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13274
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13275
		} else if (urp == seg_len) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13276
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13277
			 * The urgent byte is the next byte after this sequence
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13278
			 * number. If there is data it is marked with
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13279
			 * MSGMARKNEXT and any tcp_urp_mark_mp is discarded
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13280
			 * since it is not needed. Otherwise, if the code
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13281
			 * above just allocated a zero-length tcp_urp_mark_mp
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13282
			 * message, that message is tagged with MSGMARKNEXT.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13283
			 * Sending up these MSGMARKNEXT messages makes
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13284
			 * SIOCATMARK work correctly even though
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13285
			 * the T_EXDATA_IND will not be sent up until the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13286
			 * urgent byte arrives.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13287
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13288
			if (seg_len != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13289
				flags |= TH_MARKNEXT_NEEDED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13290
				freemsg(tcp->tcp_urp_mark_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13291
				tcp->tcp_urp_mark_mp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13292
				flags &= ~TH_SEND_URP_MARK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13293
			} else if (tcp->tcp_urp_mark_mp != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13294
				flags |= TH_SEND_URP_MARK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13295
				tcp->tcp_urp_mark_mp->b_flag &=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13296
					~MSGNOTMARKNEXT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13297
				tcp->tcp_urp_mark_mp->b_flag |= MSGMARKNEXT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13298
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13299
#ifdef DEBUG
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 13300
			(void) strlog(TCP_MOD_ID, 0, 1, SL_TRACE,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13301
			    "tcp_rput: AT MARK, len %d, flags 0x%x, %s",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13302
			    seg_len, flags,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13303
			    tcp_display(tcp, NULL, DISP_PORT_ONLY));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13304
#endif /* DEBUG */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13305
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13306
			/* Data left until we hit mark */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13307
#ifdef DEBUG
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 13308
			(void) strlog(TCP_MOD_ID, 0, 1, SL_TRACE,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13309
			    "tcp_rput: URP %d bytes left, %s",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13310
			    urp - seg_len, tcp_display(tcp, NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13311
			    DISP_PORT_ONLY));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13312
#endif /* DEBUG */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13313
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13314
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13315
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13316
process_ack:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13317
	if (!(flags & TH_ACK)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13318
		freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13319
		goto xmit_check;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13320
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13321
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13322
	bytes_acked = (int)(seg_ack - tcp->tcp_suna);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13323
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13324
	if (tcp->tcp_ipversion == IPV6_VERSION && bytes_acked > 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13325
		tcp->tcp_ip_forward_progress = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13326
	if (tcp->tcp_state == TCPS_SYN_RCVD) {
898
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 13327
		if ((tcp->tcp_conn.tcp_eager_conn_ind != NULL) &&
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 13328
		    ((tcp->tcp_kssl_ent == NULL) || !tcp->tcp_kssl_pending)) {
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13329
			/* 3-way handshake complete - pass up the T_CONN_IND */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13330
			tcp_t	*listener = tcp->tcp_listener;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13331
			mblk_t	*mp = tcp->tcp_conn.tcp_eager_conn_ind;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13332
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13333
			tcp->tcp_conn.tcp_eager_conn_ind = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13334
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13335
			 * We are here means eager is fine but it can
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13336
			 * get a TH_RST at any point between now and till
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13337
			 * accept completes and disappear. We need to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13338
			 * ensure that reference to eager is valid after
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13339
			 * we get out of eager's perimeter. So we do
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13340
			 * an extra refhold.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13341
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13342
			CONN_INC_REF(connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13343
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13344
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13345
			 * The listener also exists because of the refhold
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13346
			 * done in tcp_conn_request. Its possible that it
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13347
			 * might have closed. We will check that once we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13348
			 * get inside listeners context.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13349
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13350
			CONN_INC_REF(listener->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13351
			if (listener->tcp_connp->conn_sqp ==
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13352
			    connp->conn_sqp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13353
				tcp_send_conn_ind(listener->tcp_connp, mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13354
				    listener->tcp_connp->conn_sqp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13355
				CONN_DEC_REF(listener->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13356
			} else if (!tcp->tcp_loopback) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13357
				squeue_fill(listener->tcp_connp->conn_sqp, mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13358
				    tcp_send_conn_ind,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13359
				    listener->tcp_connp, SQTAG_TCP_CONN_IND);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13360
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13361
				squeue_enter(listener->tcp_connp->conn_sqp, mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13362
				    tcp_send_conn_ind, listener->tcp_connp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13363
				    SQTAG_TCP_CONN_IND);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13364
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13365
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13366
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13367
		if (tcp->tcp_active_open) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13368
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13369
			 * We are seeing the final ack in the three way
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13370
			 * hand shake of a active open'ed connection
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13371
			 * so we must send up a T_CONN_CON
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13372
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13373
			if (!tcp_conn_con(tcp, iphdr, tcph, mp, NULL)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13374
				freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13375
				return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13376
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13377
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13378
			 * Don't fuse the loopback endpoints for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13379
			 * simultaneous active opens.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13380
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13381
			if (tcp->tcp_loopback) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13382
				TCP_STAT(tcp_fusion_unfusable);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13383
				tcp->tcp_unfusable = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13384
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13385
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13386
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13387
		tcp->tcp_suna = tcp->tcp_iss + 1;	/* One for the SYN */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13388
		bytes_acked--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13389
		/* SYN was acked - making progress */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13390
		if (tcp->tcp_ipversion == IPV6_VERSION)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13391
			tcp->tcp_ip_forward_progress = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13392
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13393
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13394
		 * If SYN was retransmitted, need to reset all
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13395
		 * retransmission info as this segment will be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13396
		 * treated as a dup ACK.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13397
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13398
		if (tcp->tcp_rexmit) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13399
			tcp->tcp_rexmit = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13400
			tcp->tcp_rexmit_nxt = tcp->tcp_snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13401
			tcp->tcp_rexmit_max = tcp->tcp_snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13402
			tcp->tcp_snd_burst = tcp->tcp_localnet ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13403
			    TCP_CWND_INFINITE : TCP_CWND_NORMAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13404
			tcp->tcp_ms_we_have_waited = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13405
			tcp->tcp_cwnd = mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13406
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13407
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13408
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13409
		 * We set the send window to zero here.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13410
		 * This is needed if there is data to be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13411
		 * processed already on the queue.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13412
		 * Later (at swnd_update label), the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13413
		 * "new_swnd > tcp_swnd" condition is satisfied
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13414
		 * the XMIT_NEEDED flag is set in the current
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13415
		 * (SYN_RCVD) state. This ensures tcp_wput_data() is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13416
		 * called if there is already data on queue in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13417
		 * this state.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13418
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13419
		tcp->tcp_swnd = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13420
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13421
		if (new_swnd > tcp->tcp_max_swnd)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13422
			tcp->tcp_max_swnd = new_swnd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13423
		tcp->tcp_swl1 = seg_seq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13424
		tcp->tcp_swl2 = seg_ack;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13425
		tcp->tcp_state = TCPS_ESTABLISHED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13426
		tcp->tcp_valid_bits &= ~TCP_ISS_VALID;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13427
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13428
		/* Fuse when both sides are in ESTABLISHED state */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13429
		if (tcp->tcp_loopback && do_tcp_fusion)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13430
			tcp_fuse(tcp, iphdr, tcph);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13431
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13432
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13433
	/* This code follows 4.4BSD-Lite2 mostly. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13434
	if (bytes_acked < 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13435
		goto est;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13436
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13437
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13438
	 * If TCP is ECN capable and the congestion experience bit is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13439
	 * set, reduce tcp_cwnd and tcp_ssthresh.  But this should only be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13440
	 * done once per window (or more loosely, per RTT).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13441
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13442
	if (tcp->tcp_cwr && SEQ_GT(seg_ack, tcp->tcp_cwr_snd_max))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13443
		tcp->tcp_cwr = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13444
	if (tcp->tcp_ecn_ok && (flags & TH_ECE)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13445
		if (!tcp->tcp_cwr) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13446
			npkt = ((tcp->tcp_snxt - tcp->tcp_suna) >> 1) / mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13447
			tcp->tcp_cwnd_ssthresh = MAX(npkt, 2) * mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13448
			tcp->tcp_cwnd = npkt * mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13449
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13450
			 * If the cwnd is 0, use the timer to clock out
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13451
			 * new segments.  This is required by the ECN spec.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13452
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13453
			if (npkt == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13454
				TCP_TIMER_RESTART(tcp, tcp->tcp_rto);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13455
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13456
				 * This makes sure that when the ACK comes
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13457
				 * back, we will increase tcp_cwnd by 1 MSS.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13458
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13459
				tcp->tcp_cwnd_cnt = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13460
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13461
			tcp->tcp_cwr = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13462
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13463
			 * This marks the end of the current window of in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13464
			 * flight data.  That is why we don't use
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13465
			 * tcp_suna + tcp_swnd.  Only data in flight can
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13466
			 * provide ECN info.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13467
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13468
			tcp->tcp_cwr_snd_max = tcp->tcp_snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13469
			tcp->tcp_ecn_cwr_sent = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13470
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13471
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13472
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13473
	mp1 = tcp->tcp_xmit_head;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13474
	if (bytes_acked == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13475
		if (!ofo_seg && seg_len == 0 && new_swnd == tcp->tcp_swnd) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13476
			int dupack_cnt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13477
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13478
			BUMP_MIB(&tcp_mib, tcpInDupAck);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13479
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13480
			 * Fast retransmit.  When we have seen exactly three
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13481
			 * identical ACKs while we have unacked data
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13482
			 * outstanding we take it as a hint that our peer
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13483
			 * dropped something.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13484
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13485
			 * If TCP is retransmitting, don't do fast retransmit.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13486
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13487
			if (mp1 && tcp->tcp_suna != tcp->tcp_snxt &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13488
			    ! tcp->tcp_rexmit) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13489
				/* Do Limited Transmit */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13490
				if ((dupack_cnt = ++tcp->tcp_dupack_cnt) <
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13491
				    tcp_dupack_fast_retransmit) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13492
					/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13493
					 * RFC 3042
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13494
					 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13495
					 * What we need to do is temporarily
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13496
					 * increase tcp_cwnd so that new
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13497
					 * data can be sent if it is allowed
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13498
					 * by the receive window (tcp_rwnd).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13499
					 * tcp_wput_data() will take care of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13500
					 * the rest.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13501
					 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13502
					 * If the connection is SACK capable,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13503
					 * only do limited xmit when there
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13504
					 * is SACK info.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13505
					 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13506
					 * Note how tcp_cwnd is incremented.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13507
					 * The first dup ACK will increase
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13508
					 * it by 1 MSS.  The second dup ACK
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13509
					 * will increase it by 2 MSS.  This
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13510
					 * means that only 1 new segment will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13511
					 * be sent for each dup ACK.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13512
					 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13513
					if (tcp->tcp_unsent > 0 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13514
					    (!tcp->tcp_snd_sack_ok ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13515
					    (tcp->tcp_snd_sack_ok &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13516
					    tcp->tcp_notsack_list != NULL))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13517
						tcp->tcp_cwnd += mss <<
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13518
						    (tcp->tcp_dupack_cnt - 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13519
						flags |= TH_LIMIT_XMIT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13520
					}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13521
				} else if (dupack_cnt ==
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13522
				    tcp_dupack_fast_retransmit) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13523
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13524
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13525
				 * If we have reduced tcp_ssthresh
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13526
				 * because of ECN, do not reduce it again
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13527
				 * unless it is already one window of data
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13528
				 * away.  After one window of data, tcp_cwr
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13529
				 * should then be cleared.  Note that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13530
				 * for non ECN capable connection, tcp_cwr
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13531
				 * should always be false.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13532
				 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13533
				 * Adjust cwnd since the duplicate
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13534
				 * ack indicates that a packet was
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13535
				 * dropped (due to congestion.)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13536
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13537
				if (!tcp->tcp_cwr) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13538
					npkt = ((tcp->tcp_snxt -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13539
					    tcp->tcp_suna) >> 1) / mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13540
					tcp->tcp_cwnd_ssthresh = MAX(npkt, 2) *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13541
					    mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13542
					tcp->tcp_cwnd = (npkt +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13543
					    tcp->tcp_dupack_cnt) * mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13544
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13545
				if (tcp->tcp_ecn_ok) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13546
					tcp->tcp_cwr = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13547
					tcp->tcp_cwr_snd_max = tcp->tcp_snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13548
					tcp->tcp_ecn_cwr_sent = B_FALSE;
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
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13552
				 * We do Hoe's algorithm.  Refer to her
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13553
				 * paper "Improving the Start-up Behavior
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13554
				 * of a Congestion Control Scheme for TCP,"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13555
				 * appeared in SIGCOMM'96.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13556
				 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13557
				 * Save highest seq no we have sent so far.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13558
				 * Be careful about the invisible FIN byte.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13559
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13560
				if ((tcp->tcp_valid_bits & TCP_FSS_VALID) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13561
				    (tcp->tcp_unsent == 0)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13562
					tcp->tcp_rexmit_max = tcp->tcp_fss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13563
				} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13564
					tcp->tcp_rexmit_max = tcp->tcp_snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13565
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13566
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13567
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13568
				 * Do not allow bursty traffic during.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13569
				 * fast recovery.  Refer to Fall and Floyd's
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13570
				 * paper "Simulation-based Comparisons of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13571
				 * Tahoe, Reno and SACK TCP" (in CCR?)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13572
				 * This is a best current practise.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13573
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13574
				tcp->tcp_snd_burst = TCP_CWND_SS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13575
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13576
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13577
				 * For SACK:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13578
				 * Calculate tcp_pipe, which is the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13579
				 * estimated number of bytes in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13580
				 * network.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13581
				 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13582
				 * tcp_fack is the highest sack'ed seq num
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13583
				 * TCP has received.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13584
				 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13585
				 * tcp_pipe is explained in the above quoted
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13586
				 * Fall and Floyd's paper.  tcp_fack is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13587
				 * explained in Mathis and Mahdavi's
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13588
				 * "Forward Acknowledgment: Refining TCP
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13589
				 * Congestion Control" in SIGCOMM '96.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13590
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13591
				if (tcp->tcp_snd_sack_ok) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13592
					ASSERT(tcp->tcp_sack_info != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13593
					if (tcp->tcp_notsack_list != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13594
						tcp->tcp_pipe = tcp->tcp_snxt -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13595
						    tcp->tcp_fack;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13596
						tcp->tcp_sack_snxt = seg_ack;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13597
						flags |= TH_NEED_SACK_REXMIT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13598
					} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13599
						/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13600
						 * Always initialize tcp_pipe
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13601
						 * even though we don't have
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13602
						 * any SACK info.  If later
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13603
						 * we get SACK info and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13604
						 * tcp_pipe is not initialized,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13605
						 * funny things will happen.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13606
						 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13607
						tcp->tcp_pipe =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13608
						    tcp->tcp_cwnd_ssthresh;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13609
					}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13610
				} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13611
					flags |= TH_REXMIT_NEEDED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13612
				} /* tcp_snd_sack_ok */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13613
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13614
				} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13615
					/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13616
					 * Here we perform congestion
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13617
					 * avoidance, but NOT slow start.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13618
					 * This is known as the Fast
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13619
					 * Recovery Algorithm.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13620
					 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13621
					if (tcp->tcp_snd_sack_ok &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13622
					    tcp->tcp_notsack_list != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13623
						flags |= TH_NEED_SACK_REXMIT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13624
						tcp->tcp_pipe -= mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13625
						if (tcp->tcp_pipe < 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13626
							tcp->tcp_pipe = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13627
					} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13628
					/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13629
					 * We know that one more packet has
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13630
					 * left the pipe thus we can update
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13631
					 * cwnd.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13632
					 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13633
					cwnd = tcp->tcp_cwnd + mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13634
					if (cwnd > tcp->tcp_cwnd_max)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13635
						cwnd = tcp->tcp_cwnd_max;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13636
					tcp->tcp_cwnd = cwnd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13637
					if (tcp->tcp_unsent > 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13638
						flags |= TH_XMIT_NEEDED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13639
					}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13640
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13641
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13642
		} else if (tcp->tcp_zero_win_probe) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13643
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13644
			 * If the window has opened, need to arrange
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13645
			 * to send additional data.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13646
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13647
			if (new_swnd != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13648
				/* tcp_suna != tcp_snxt */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13649
				/* Packet contains a window update */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13650
				BUMP_MIB(&tcp_mib, tcpInWinUpdate);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13651
				tcp->tcp_zero_win_probe = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13652
				tcp->tcp_timer_backoff = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13653
				tcp->tcp_ms_we_have_waited = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13654
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13655
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13656
				 * Transmit starting with tcp_suna since
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13657
				 * the one byte probe is not ack'ed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13658
				 * If TCP has sent more than one identical
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13659
				 * probe, tcp_rexmit will be set.  That means
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13660
				 * tcp_ss_rexmit() will send out the one
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13661
				 * byte along with new data.  Otherwise,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13662
				 * fake the retransmission.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13663
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13664
				flags |= TH_XMIT_NEEDED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13665
				if (!tcp->tcp_rexmit) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13666
					tcp->tcp_rexmit = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13667
					tcp->tcp_dupack_cnt = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13668
					tcp->tcp_rexmit_nxt = tcp->tcp_suna;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13669
					tcp->tcp_rexmit_max = tcp->tcp_suna + 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13670
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13671
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13672
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13673
		goto swnd_update;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13674
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13675
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13676
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13677
	 * Check for "acceptability" of ACK value per RFC 793, pages 72 - 73.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13678
	 * If the ACK value acks something that we have not yet sent, it might
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13679
	 * be an old duplicate segment.  Send an ACK to re-synchronize the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13680
	 * other side.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13681
	 * Note: reset in response to unacceptable ACK in SYN_RECEIVE
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13682
	 * state is handled above, so we can always just drop the segment and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13683
	 * send an ACK here.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13684
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13685
	 * Should we send ACKs in response to ACK only segments?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13686
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13687
	if (SEQ_GT(seg_ack, tcp->tcp_snxt)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13688
		BUMP_MIB(&tcp_mib, tcpInAckUnsent);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13689
		/* drop the received segment */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13690
		freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13691
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13692
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13693
		 * Send back an ACK.  If tcp_drop_ack_unsent_cnt is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13694
		 * greater than 0, check if the number of such
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13695
		 * bogus ACks is greater than that count.  If yes,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13696
		 * don't send back any ACK.  This prevents TCP from
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13697
		 * getting into an ACK storm if somehow an attacker
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13698
		 * successfully spoofs an acceptable segment to our
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13699
		 * peer.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13700
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13701
		if (tcp_drop_ack_unsent_cnt > 0 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13702
		    ++tcp->tcp_in_ack_unsent > tcp_drop_ack_unsent_cnt) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13703
			TCP_STAT(tcp_in_ack_unsent_drop);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13704
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13705
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13706
		mp = tcp_ack_mp(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13707
		if (mp != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13708
			TCP_RECORD_TRACE(tcp, mp, TCP_TRACE_SEND_PKT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13709
			BUMP_LOCAL(tcp->tcp_obsegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13710
			BUMP_MIB(&tcp_mib, tcpOutAck);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13711
			tcp_send_data(tcp, tcp->tcp_wq, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13712
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13713
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13714
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13715
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13716
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13717
	 * TCP gets a new ACK, update the notsack'ed list to delete those
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13718
	 * blocks that are covered by this ACK.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13719
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13720
	if (tcp->tcp_snd_sack_ok && tcp->tcp_notsack_list != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13721
		tcp_notsack_remove(&(tcp->tcp_notsack_list), seg_ack,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13722
		    &(tcp->tcp_num_notsack_blk), &(tcp->tcp_cnt_notsack_list));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13723
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13724
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13725
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13726
	 * If we got an ACK after fast retransmit, check to see
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13727
	 * if it is a partial ACK.  If it is not and the congestion
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13728
	 * window was inflated to account for the other side's
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13729
	 * cached packets, retract it.  If it is, do Hoe's algorithm.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13730
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13731
	if (tcp->tcp_dupack_cnt >= tcp_dupack_fast_retransmit) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13732
		ASSERT(tcp->tcp_rexmit == B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13733
		if (SEQ_GEQ(seg_ack, tcp->tcp_rexmit_max)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13734
			tcp->tcp_dupack_cnt = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13735
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13736
			 * Restore the orig tcp_cwnd_ssthresh after
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13737
			 * fast retransmit phase.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13738
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13739
			if (tcp->tcp_cwnd > tcp->tcp_cwnd_ssthresh) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13740
				tcp->tcp_cwnd = tcp->tcp_cwnd_ssthresh;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13741
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13742
			tcp->tcp_rexmit_max = seg_ack;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13743
			tcp->tcp_cwnd_cnt = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13744
			tcp->tcp_snd_burst = tcp->tcp_localnet ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13745
			    TCP_CWND_INFINITE : TCP_CWND_NORMAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13746
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13747
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13748
			 * Remove all notsack info to avoid confusion with
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13749
			 * the next fast retrasnmit/recovery phase.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13750
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13751
			if (tcp->tcp_snd_sack_ok &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13752
			    tcp->tcp_notsack_list != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13753
				TCP_NOTSACK_REMOVE_ALL(tcp->tcp_notsack_list);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13754
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13755
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13756
			if (tcp->tcp_snd_sack_ok &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13757
			    tcp->tcp_notsack_list != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13758
				flags |= TH_NEED_SACK_REXMIT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13759
				tcp->tcp_pipe -= mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13760
				if (tcp->tcp_pipe < 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13761
					tcp->tcp_pipe = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13762
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13763
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13764
				 * Hoe's algorithm:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13765
				 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13766
				 * Retransmit the unack'ed segment and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13767
				 * restart fast recovery.  Note that we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13768
				 * need to scale back tcp_cwnd to the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13769
				 * original value when we started fast
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13770
				 * recovery.  This is to prevent overly
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13771
				 * aggressive behaviour in sending new
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13772
				 * segments.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13773
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13774
				tcp->tcp_cwnd = tcp->tcp_cwnd_ssthresh +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13775
					tcp_dupack_fast_retransmit * mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13776
				tcp->tcp_cwnd_cnt = tcp->tcp_cwnd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13777
				flags |= TH_REXMIT_NEEDED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13778
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13779
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13780
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13781
		tcp->tcp_dupack_cnt = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13782
		if (tcp->tcp_rexmit) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13783
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13784
			 * TCP is retranmitting.  If the ACK ack's all
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13785
			 * outstanding data, update tcp_rexmit_max and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13786
			 * tcp_rexmit_nxt.  Otherwise, update tcp_rexmit_nxt
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13787
			 * to the correct value.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13788
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13789
			 * Note that SEQ_LEQ() is used.  This is to avoid
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13790
			 * unnecessary fast retransmit caused by dup ACKs
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13791
			 * received when TCP does slow start retransmission
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13792
			 * after a time out.  During this phase, TCP may
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13793
			 * send out segments which are already received.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13794
			 * This causes dup ACKs to be sent back.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13795
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13796
			if (SEQ_LEQ(seg_ack, tcp->tcp_rexmit_max)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13797
				if (SEQ_GT(seg_ack, tcp->tcp_rexmit_nxt)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13798
					tcp->tcp_rexmit_nxt = seg_ack;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13799
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13800
				if (seg_ack != tcp->tcp_rexmit_max) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13801
					flags |= TH_XMIT_NEEDED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13802
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13803
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13804
				tcp->tcp_rexmit = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13805
				tcp->tcp_xmit_zc_clean = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13806
				tcp->tcp_rexmit_nxt = tcp->tcp_snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13807
				tcp->tcp_snd_burst = tcp->tcp_localnet ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13808
				    TCP_CWND_INFINITE : TCP_CWND_NORMAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13809
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13810
			tcp->tcp_ms_we_have_waited = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13811
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13812
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13813
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13814
	BUMP_MIB(&tcp_mib, tcpInAckSegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13815
	UPDATE_MIB(&tcp_mib, tcpInAckBytes, bytes_acked);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13816
	tcp->tcp_suna = seg_ack;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13817
	if (tcp->tcp_zero_win_probe != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13818
		tcp->tcp_zero_win_probe = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13819
		tcp->tcp_timer_backoff = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13820
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13821
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13822
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13823
	 * If tcp_xmit_head is NULL, then it must be the FIN being ack'ed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13824
	 * Note that it cannot be the SYN being ack'ed.  The code flow
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13825
	 * will not reach here.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13826
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13827
	if (mp1 == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13828
		goto fin_acked;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13829
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13830
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13831
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13832
	 * Update the congestion window.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13833
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13834
	 * If TCP is not ECN capable or TCP is ECN capable but the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13835
	 * congestion experience bit is not set, increase the tcp_cwnd as
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13836
	 * usual.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13837
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13838
	if (!tcp->tcp_ecn_ok || !(flags & TH_ECE)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13839
		cwnd = tcp->tcp_cwnd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13840
		add = mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13841
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13842
		if (cwnd >= tcp->tcp_cwnd_ssthresh) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13843
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13844
			 * This is to prevent an increase of less than 1 MSS of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13845
			 * tcp_cwnd.  With partial increase, tcp_wput_data()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13846
			 * may send out tinygrams in order to preserve mblk
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13847
			 * boundaries.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13848
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13849
			 * By initializing tcp_cwnd_cnt to new tcp_cwnd and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13850
			 * decrementing it by 1 MSS for every ACKs, tcp_cwnd is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13851
			 * increased by 1 MSS for every RTTs.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13852
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13853
			if (tcp->tcp_cwnd_cnt <= 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13854
				tcp->tcp_cwnd_cnt = cwnd + add;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13855
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13856
				tcp->tcp_cwnd_cnt -= add;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13857
				add = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13858
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13859
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13860
		tcp->tcp_cwnd = MIN(cwnd + add, tcp->tcp_cwnd_max);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13861
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13862
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13863
	/* See if the latest urgent data has been acknowledged */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13864
	if ((tcp->tcp_valid_bits & TCP_URG_VALID) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13865
	    SEQ_GT(seg_ack, tcp->tcp_urg))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13866
		tcp->tcp_valid_bits &= ~TCP_URG_VALID;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13867
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13868
	/* Can we update the RTT estimates? */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13869
	if (tcp->tcp_snd_ts_ok) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13870
		/* Ignore zero timestamp echo-reply. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13871
		if (tcpopt.tcp_opt_ts_ecr != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13872
			tcp_set_rto(tcp, (int32_t)lbolt -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13873
			    (int32_t)tcpopt.tcp_opt_ts_ecr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13874
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13875
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13876
		/* If needed, restart the timer. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13877
		if (tcp->tcp_set_timer == 1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13878
			TCP_TIMER_RESTART(tcp, tcp->tcp_rto);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13879
			tcp->tcp_set_timer = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13880
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13881
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13882
		 * Update tcp_csuna in case the other side stops sending
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13883
		 * us timestamps.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13884
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13885
		tcp->tcp_csuna = tcp->tcp_snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13886
	} else if (SEQ_GT(seg_ack, tcp->tcp_csuna)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13887
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13888
		 * An ACK sequence we haven't seen before, so get the RTT
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13889
		 * and update the RTO. But first check if the timestamp is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13890
		 * valid to use.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13891
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13892
		if ((mp1->b_next != NULL) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13893
		    SEQ_GT(seg_ack, (uint32_t)(uintptr_t)(mp1->b_next)))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13894
			tcp_set_rto(tcp, (int32_t)lbolt -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13895
			    (int32_t)(intptr_t)mp1->b_prev);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13896
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13897
			BUMP_MIB(&tcp_mib, tcpRttNoUpdate);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13898
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13899
		/* Remeber the last sequence to be ACKed */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13900
		tcp->tcp_csuna = seg_ack;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13901
		if (tcp->tcp_set_timer == 1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13902
			TCP_TIMER_RESTART(tcp, tcp->tcp_rto);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13903
			tcp->tcp_set_timer = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13904
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13905
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13906
		BUMP_MIB(&tcp_mib, tcpRttNoUpdate);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13907
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13908
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13909
	/* Eat acknowledged bytes off the xmit queue. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13910
	for (;;) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13911
		mblk_t	*mp2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13912
		uchar_t	*wptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13913
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13914
		wptr = mp1->b_wptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13915
		ASSERT((uintptr_t)(wptr - mp1->b_rptr) <= (uintptr_t)INT_MAX);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13916
		bytes_acked -= (int)(wptr - mp1->b_rptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13917
		if (bytes_acked < 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13918
			mp1->b_rptr = wptr + bytes_acked;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13919
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13920
			 * Set a new timestamp if all the bytes timed by the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13921
			 * old timestamp have been ack'ed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13922
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13923
			if (SEQ_GT(seg_ack,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13924
			    (uint32_t)(uintptr_t)(mp1->b_next))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13925
				mp1->b_prev = (mblk_t *)(uintptr_t)lbolt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13926
				mp1->b_next = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13927
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13928
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13929
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13930
		mp1->b_next = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13931
		mp1->b_prev = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13932
		mp2 = mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13933
		mp1 = mp1->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13934
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13935
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13936
		 * This notification is required for some zero-copy
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13937
		 * clients to maintain a copy semantic. After the data
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13938
		 * is ack'ed, client is safe to modify or reuse the buffer.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13939
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13940
		if (tcp->tcp_snd_zcopy_aware &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13941
		    (mp2->b_datap->db_struioflag & STRUIO_ZCNOTIFY))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13942
			tcp_zcopy_notify(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13943
		freeb(mp2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13944
		if (bytes_acked == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13945
			if (mp1 == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13946
				/* Everything is ack'ed, clear the tail. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13947
				tcp->tcp_xmit_tail = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13948
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13949
				 * Cancel the timer unless we are still
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13950
				 * waiting for an ACK for the FIN packet.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13951
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13952
				if (tcp->tcp_timer_tid != 0 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13953
				    tcp->tcp_snxt == tcp->tcp_suna) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13954
					(void) TCP_TIMER_CANCEL(tcp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13955
					    tcp->tcp_timer_tid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13956
					tcp->tcp_timer_tid = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13957
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13958
				goto pre_swnd_update;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13959
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13960
			if (mp2 != tcp->tcp_xmit_tail)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13961
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13962
			tcp->tcp_xmit_tail = mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13963
			ASSERT((uintptr_t)(mp1->b_wptr - mp1->b_rptr) <=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13964
			    (uintptr_t)INT_MAX);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13965
			tcp->tcp_xmit_tail_unsent = (int)(mp1->b_wptr -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13966
			    mp1->b_rptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13967
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13968
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13969
		if (mp1 == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13970
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13971
			 * More was acked but there is nothing more
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13972
			 * outstanding.  This means that the FIN was
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13973
			 * just acked or that we're talking to a clown.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13974
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13975
fin_acked:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13976
			ASSERT(tcp->tcp_fin_sent);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13977
			tcp->tcp_xmit_tail = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13978
			if (tcp->tcp_fin_sent) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13979
				/* FIN was acked - making progress */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13980
				if (tcp->tcp_ipversion == IPV6_VERSION &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13981
				    !tcp->tcp_fin_acked)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13982
					tcp->tcp_ip_forward_progress = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13983
				tcp->tcp_fin_acked = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13984
				if (tcp->tcp_linger_tid != 0 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13985
				    TCP_TIMER_CANCEL(tcp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13986
					tcp->tcp_linger_tid) >= 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13987
					tcp_stop_lingering(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13988
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13989
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13990
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13991
				 * We should never get here because
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13992
				 * we have already checked that the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13993
				 * number of bytes ack'ed should be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13994
				 * smaller than or equal to what we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13995
				 * have sent so far (it is the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13996
				 * acceptability check of the ACK).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13997
				 * We can only get here if the send
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13998
				 * queue is corrupted.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13999
				 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14000
				 * Terminate the connection and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14001
				 * panic the system.  It is better
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14002
				 * for us to panic instead of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14003
				 * continuing to avoid other disaster.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14004
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14005
				tcp_xmit_ctl(NULL, tcp, tcp->tcp_snxt,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14006
				    tcp->tcp_rnxt, TH_RST|TH_ACK);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14007
				panic("Memory corruption "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14008
				    "detected for connection %s.",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14009
				    tcp_display(tcp, NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14010
					DISP_ADDR_AND_PORT));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14011
				/*NOTREACHED*/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14012
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14013
			goto pre_swnd_update;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14014
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14015
		ASSERT(mp2 != tcp->tcp_xmit_tail);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14016
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14017
	if (tcp->tcp_unsent) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14018
		flags |= TH_XMIT_NEEDED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14019
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14020
pre_swnd_update:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14021
	tcp->tcp_xmit_head = mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14022
swnd_update:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14023
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14024
	 * The following check is different from most other implementations.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14025
	 * For bi-directional transfer, when segments are dropped, the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14026
	 * "normal" check will not accept a window update in those
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14027
	 * retransmitted segemnts.  Failing to do that, TCP may send out
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14028
	 * segments which are outside receiver's window.  As TCP accepts
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14029
	 * the ack in those retransmitted segments, if the window update in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14030
	 * the same segment is not accepted, TCP will incorrectly calculates
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14031
	 * that it can send more segments.  This can create a deadlock
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14032
	 * with the receiver if its window becomes zero.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14033
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14034
	if (SEQ_LT(tcp->tcp_swl2, seg_ack) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14035
	    SEQ_LT(tcp->tcp_swl1, seg_seq) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14036
	    (tcp->tcp_swl1 == seg_seq && new_swnd > tcp->tcp_swnd)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14037
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14038
		 * The criteria for update is:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14039
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14040
		 * 1. the segment acknowledges some data.  Or
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14041
		 * 2. the segment is new, i.e. it has a higher seq num. Or
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14042
		 * 3. the segment is not old and the advertised window is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14043
		 * larger than the previous advertised window.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14044
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14045
		if (tcp->tcp_unsent && new_swnd > tcp->tcp_swnd)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14046
			flags |= TH_XMIT_NEEDED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14047
		tcp->tcp_swnd = new_swnd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14048
		if (new_swnd > tcp->tcp_max_swnd)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14049
			tcp->tcp_max_swnd = new_swnd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14050
		tcp->tcp_swl1 = seg_seq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14051
		tcp->tcp_swl2 = seg_ack;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14052
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14053
est:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14054
	if (tcp->tcp_state > TCPS_ESTABLISHED) {
898
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 14055
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14056
		switch (tcp->tcp_state) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14057
		case TCPS_FIN_WAIT_1:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14058
			if (tcp->tcp_fin_acked) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14059
				tcp->tcp_state = TCPS_FIN_WAIT_2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14060
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14061
				 * We implement the non-standard BSD/SunOS
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14062
				 * FIN_WAIT_2 flushing algorithm.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14063
				 * If there is no user attached to this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14064
				 * TCP endpoint, then this TCP struct
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14065
				 * could hang around forever in FIN_WAIT_2
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14066
				 * state if the peer forgets to send us
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14067
				 * a FIN.  To prevent this, we wait only
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14068
				 * 2*MSL (a convenient time value) for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14069
				 * the FIN to arrive.  If it doesn't show up,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14070
				 * we flush the TCP endpoint.  This algorithm,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14071
				 * though a violation of RFC-793, has worked
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14072
				 * for over 10 years in BSD systems.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14073
				 * Note: SunOS 4.x waits 675 seconds before
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14074
				 * flushing the FIN_WAIT_2 connection.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14075
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14076
				TCP_TIMER_RESTART(tcp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14077
				    tcp_fin_wait_2_flush_interval);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14078
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14079
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14080
		case TCPS_FIN_WAIT_2:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14081
			break;	/* Shutdown hook? */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14082
		case TCPS_LAST_ACK:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14083
			freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14084
			if (tcp->tcp_fin_acked) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14085
				(void) tcp_clean_death(tcp, 0, 19);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14086
				return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14087
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14088
			goto xmit_check;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14089
		case TCPS_CLOSING:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14090
			if (tcp->tcp_fin_acked) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14091
				tcp->tcp_state = TCPS_TIME_WAIT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14092
				if (!TCP_IS_DETACHED(tcp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14093
					TCP_TIMER_RESTART(tcp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14094
					    tcp_time_wait_interval);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14095
				} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14096
					tcp_time_wait_append(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14097
					TCP_DBGSTAT(tcp_rput_time_wait);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14098
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14099
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14100
			/*FALLTHRU*/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14101
		case TCPS_CLOSE_WAIT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14102
			freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14103
			goto xmit_check;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14104
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14105
			ASSERT(tcp->tcp_state != TCPS_TIME_WAIT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14106
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14107
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14108
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14109
	if (flags & TH_FIN) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14110
		/* Make sure we ack the fin */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14111
		flags |= TH_ACK_NEEDED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14112
		if (!tcp->tcp_fin_rcvd) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14113
			tcp->tcp_fin_rcvd = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14114
			tcp->tcp_rnxt++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14115
			tcph = tcp->tcp_tcph;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14116
			U32_TO_ABE32(tcp->tcp_rnxt, tcph->th_ack);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14117
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14118
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14119
			 * Generate the ordrel_ind at the end unless we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14120
			 * are an eager guy.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14121
			 * In the eager case tcp_rsrv will do this when run
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14122
			 * after tcp_accept is done.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14123
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14124
			if (tcp->tcp_listener == NULL &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14125
			    !TCP_IS_DETACHED(tcp) && (!tcp->tcp_hard_binding))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14126
				flags |= TH_ORDREL_NEEDED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14127
			switch (tcp->tcp_state) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14128
			case TCPS_SYN_RCVD:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14129
			case TCPS_ESTABLISHED:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14130
				tcp->tcp_state = TCPS_CLOSE_WAIT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14131
				/* Keepalive? */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14132
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14133
			case TCPS_FIN_WAIT_1:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14134
				if (!tcp->tcp_fin_acked) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14135
					tcp->tcp_state = TCPS_CLOSING;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14136
					break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14137
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14138
				/* FALLTHRU */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14139
			case TCPS_FIN_WAIT_2:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14140
				tcp->tcp_state = TCPS_TIME_WAIT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14141
				if (!TCP_IS_DETACHED(tcp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14142
					TCP_TIMER_RESTART(tcp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14143
					    tcp_time_wait_interval);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14144
				} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14145
					tcp_time_wait_append(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14146
					TCP_DBGSTAT(tcp_rput_time_wait);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14147
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14148
				if (seg_len) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14149
					/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14150
					 * implies data piggybacked on FIN.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14151
					 * break to handle data.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14152
					 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14153
					break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14154
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14155
				freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14156
				goto ack_check;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14157
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14158
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14159
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14160
	if (mp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14161
		goto xmit_check;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14162
	if (seg_len == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14163
		freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14164
		goto xmit_check;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14165
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14166
	if (mp->b_rptr == mp->b_wptr) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14167
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14168
		 * The header has been consumed, so we remove the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14169
		 * zero-length mblk here.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14170
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14171
		mp1 = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14172
		mp = mp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14173
		freeb(mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14174
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14175
	tcph = tcp->tcp_tcph;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14176
	tcp->tcp_rack_cnt++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14177
	{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14178
		uint32_t cur_max;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14179
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14180
		cur_max = tcp->tcp_rack_cur_max;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14181
		if (tcp->tcp_rack_cnt >= cur_max) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14182
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14183
			 * We have more unacked data than we should - send
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14184
			 * an ACK now.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14185
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14186
			flags |= TH_ACK_NEEDED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14187
			cur_max++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14188
			if (cur_max > tcp->tcp_rack_abs_max)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14189
				tcp->tcp_rack_cur_max = tcp->tcp_rack_abs_max;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14190
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14191
				tcp->tcp_rack_cur_max = cur_max;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14192
		} else if (TCP_IS_DETACHED(tcp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14193
			/* We don't have an ACK timer for detached TCP. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14194
			flags |= TH_ACK_NEEDED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14195
		} else if (seg_len < mss) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14196
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14197
			 * If we get a segment that is less than an mss, and we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14198
			 * already have unacknowledged data, and the amount
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14199
			 * unacknowledged is not a multiple of mss, then we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14200
			 * better generate an ACK now.  Otherwise, this may be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14201
			 * the tail piece of a transaction, and we would rather
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14202
			 * wait for the response.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14203
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14204
			uint32_t udif;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14205
			ASSERT((uintptr_t)(tcp->tcp_rnxt - tcp->tcp_rack) <=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14206
			    (uintptr_t)INT_MAX);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14207
			udif = (int)(tcp->tcp_rnxt - tcp->tcp_rack);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14208
			if (udif && (udif % mss))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14209
				flags |= TH_ACK_NEEDED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14210
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14211
				flags |= TH_ACK_TIMER_NEEDED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14212
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14213
			/* Start delayed ack timer */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14214
			flags |= TH_ACK_TIMER_NEEDED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14215
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14216
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14217
	tcp->tcp_rnxt += seg_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14218
	U32_TO_ABE32(tcp->tcp_rnxt, tcph->th_ack);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14219
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14220
	/* Update SACK list */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14221
	if (tcp->tcp_snd_sack_ok && tcp->tcp_num_sack_blk > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14222
		tcp_sack_remove(tcp->tcp_sack_list, tcp->tcp_rnxt,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14223
		    &(tcp->tcp_num_sack_blk));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14224
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14225
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14226
	if (tcp->tcp_urp_mp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14227
		tcp->tcp_urp_mp->b_cont = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14228
		mp = tcp->tcp_urp_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14229
		tcp->tcp_urp_mp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14230
		/* Ready for a new signal. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14231
		tcp->tcp_urp_last_valid = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14232
#ifdef DEBUG
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 14233
		(void) strlog(TCP_MOD_ID, 0, 1, SL_TRACE,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14234
		    "tcp_rput: sending exdata_ind %s",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14235
		    tcp_display(tcp, NULL, DISP_PORT_ONLY));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14236
#endif /* DEBUG */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14237
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14238
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14239
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14240
	 * Check for ancillary data changes compared to last segment.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14241
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14242
	if (tcp->tcp_ipv6_recvancillary != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14243
		mp = tcp_rput_add_ancillary(tcp, mp, &ipp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14244
		if (mp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14245
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14246
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14247
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14248
	if (tcp->tcp_listener || tcp->tcp_hard_binding) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14249
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14250
		 * Side queue inbound data until the accept happens.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14251
		 * tcp_accept/tcp_rput drains this when the accept happens.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14252
		 * M_DATA is queued on b_cont. Otherwise (T_OPTDATA_IND or
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14253
		 * T_EXDATA_IND) it is queued on b_next.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14254
		 * XXX Make urgent data use this. Requires:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14255
		 *	Removing tcp_listener check for TH_URG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14256
		 *	Making M_PCPROTO and MARK messages skip the eager case
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14257
		 */
898
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 14258
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 14259
		if (tcp->tcp_kssl_pending) {
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 14260
			tcp_kssl_input(tcp, mp);
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 14261
		} else {
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 14262
			tcp_rcv_enqueue(tcp, mp, seg_len);
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 14263
		}
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14264
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14265
		if (mp->b_datap->db_type != M_DATA ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14266
		    (flags & TH_MARKNEXT_NEEDED)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14267
			if (tcp->tcp_rcv_list != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14268
				flags |= tcp_rcv_drain(tcp->tcp_rq, tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14269
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14270
			ASSERT(tcp->tcp_rcv_list == NULL ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14271
			    tcp->tcp_fused_sigurg);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14272
			if (flags & TH_MARKNEXT_NEEDED) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14273
#ifdef DEBUG
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 14274
				(void) strlog(TCP_MOD_ID, 0, 1, SL_TRACE,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14275
				    "tcp_rput: sending MSGMARKNEXT %s",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14276
				    tcp_display(tcp, NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14277
				    DISP_PORT_ONLY));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14278
#endif /* DEBUG */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14279
				mp->b_flag |= MSGMARKNEXT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14280
				flags &= ~TH_MARKNEXT_NEEDED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14281
			}
898
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 14282
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 14283
			/* Does this need SSL processing first? */
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 14284
			if ((tcp->tcp_kssl_ctx  != NULL) &&
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 14285
			    (DB_TYPE(mp) == M_DATA)) {
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 14286
				tcp_kssl_input(tcp, mp);
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 14287
			} else {
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 14288
				putnext(tcp->tcp_rq, mp);
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 14289
				if (!canputnext(tcp->tcp_rq))
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 14290
					tcp->tcp_rwnd -= seg_len;
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 14291
			}
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14292
		} else if (((flags & (TH_PUSH|TH_FIN)) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14293
		    tcp->tcp_rcv_cnt + seg_len >= tcp->tcp_rq->q_hiwat >> 3) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14294
		    (sqp != NULL)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14295
			if (tcp->tcp_rcv_list != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14296
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14297
				 * Enqueue the new segment first and then
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14298
				 * call tcp_rcv_drain() to send all data
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14299
				 * up.  The other way to do this is to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14300
				 * send all queued data up and then call
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14301
				 * putnext() to send the new segment up.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14302
				 * This way can remove the else part later
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14303
				 * on.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14304
				 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14305
				 * We don't this to avoid one more call to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14306
				 * canputnext() as tcp_rcv_drain() needs to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14307
				 * call canputnext().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14308
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14309
				tcp_rcv_enqueue(tcp, mp, seg_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14310
				flags |= tcp_rcv_drain(tcp->tcp_rq, tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14311
			} else {
898
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 14312
				/* Does this need SSL processing first? */
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 14313
				if ((tcp->tcp_kssl_ctx  != NULL) &&
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 14314
				    (DB_TYPE(mp) == M_DATA)) {
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 14315
					tcp_kssl_input(tcp, mp);
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 14316
				} else {
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 14317
					putnext(tcp->tcp_rq, mp);
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 14318
					if (!canputnext(tcp->tcp_rq))
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 14319
						tcp->tcp_rwnd -= seg_len;
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 14320
				}
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14321
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14322
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14323
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14324
			 * Enqueue all packets when processing an mblk
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14325
			 * from the co queue and also enqueue normal packets.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14326
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14327
			tcp_rcv_enqueue(tcp, mp, seg_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14328
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14329
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14330
		 * Make sure the timer is running if we have data waiting
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14331
		 * for a push bit. This provides resiliency against
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14332
		 * implementations that do not correctly generate push bits.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14333
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14334
		if ((sqp != NULL) && tcp->tcp_rcv_list != NULL &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14335
		    tcp->tcp_push_tid == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14336
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14337
			 * The connection may be closed at this point, so don't
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14338
			 * do anything for a detached tcp.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14339
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14340
			if (!TCP_IS_DETACHED(tcp))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14341
				tcp->tcp_push_tid = TCP_TIMER(tcp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14342
				    tcp_push_timer,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14343
				    MSEC_TO_TICK(tcp_push_timer_interval));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14344
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14345
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14346
xmit_check:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14347
	/* Is there anything left to do? */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14348
	ASSERT(!(flags & TH_MARKNEXT_NEEDED));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14349
	if ((flags & (TH_REXMIT_NEEDED|TH_XMIT_NEEDED|TH_ACK_NEEDED|
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14350
	    TH_NEED_SACK_REXMIT|TH_LIMIT_XMIT|TH_ACK_TIMER_NEEDED|
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14351
	    TH_ORDREL_NEEDED|TH_SEND_URP_MARK)) == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14352
		goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14353
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14354
	/* Any transmit work to do and a non-zero window? */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14355
	if ((flags & (TH_REXMIT_NEEDED|TH_XMIT_NEEDED|TH_NEED_SACK_REXMIT|
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14356
	    TH_LIMIT_XMIT)) && tcp->tcp_swnd != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14357
		if (flags & TH_REXMIT_NEEDED) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14358
			uint32_t snd_size = tcp->tcp_snxt - tcp->tcp_suna;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14359
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14360
			BUMP_MIB(&tcp_mib, tcpOutFastRetrans);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14361
			if (snd_size > mss)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14362
				snd_size = mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14363
			if (snd_size > tcp->tcp_swnd)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14364
				snd_size = tcp->tcp_swnd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14365
			mp1 = tcp_xmit_mp(tcp, tcp->tcp_xmit_head, snd_size,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14366
			    NULL, NULL, tcp->tcp_suna, B_TRUE, &snd_size,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14367
			    B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14368
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14369
			if (mp1 != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14370
				tcp->tcp_xmit_head->b_prev = (mblk_t *)lbolt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14371
				tcp->tcp_csuna = tcp->tcp_snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14372
				BUMP_MIB(&tcp_mib, tcpRetransSegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14373
				UPDATE_MIB(&tcp_mib, tcpRetransBytes, snd_size);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14374
				TCP_RECORD_TRACE(tcp, mp1,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14375
				    TCP_TRACE_SEND_PKT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14376
				tcp_send_data(tcp, tcp->tcp_wq, mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14377
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14378
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14379
		if (flags & TH_NEED_SACK_REXMIT) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14380
			tcp_sack_rxmit(tcp, &flags);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14381
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14382
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14383
		 * For TH_LIMIT_XMIT, tcp_wput_data() is called to send
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14384
		 * out new segment.  Note that tcp_rexmit should not be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14385
		 * set, otherwise TH_LIMIT_XMIT should not be set.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14386
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14387
		if (flags & (TH_XMIT_NEEDED|TH_LIMIT_XMIT)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14388
			if (!tcp->tcp_rexmit) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14389
				tcp_wput_data(tcp, NULL, B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14390
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14391
				tcp_ss_rexmit(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14392
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14393
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14394
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14395
		 * Adjust tcp_cwnd back to normal value after sending
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14396
		 * new data segments.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14397
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14398
		if (flags & TH_LIMIT_XMIT) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14399
			tcp->tcp_cwnd -= mss << (tcp->tcp_dupack_cnt - 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14400
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14401
			 * This will restart the timer.  Restarting the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14402
			 * timer is used to avoid a timeout before the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14403
			 * limited transmitted segment's ACK gets back.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14404
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14405
			if (tcp->tcp_xmit_head != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14406
				tcp->tcp_xmit_head->b_prev = (mblk_t *)lbolt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14407
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14408
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14409
		/* Anything more to do? */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14410
		if ((flags & (TH_ACK_NEEDED|TH_ACK_TIMER_NEEDED|
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14411
		    TH_ORDREL_NEEDED|TH_SEND_URP_MARK)) == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14412
			goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14413
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14414
ack_check:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14415
	if (flags & TH_SEND_URP_MARK) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14416
		ASSERT(tcp->tcp_urp_mark_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14417
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14418
		 * Send up any queued data and then send the mark message
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14419
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14420
		if (tcp->tcp_rcv_list != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14421
			flags |= tcp_rcv_drain(tcp->tcp_rq, tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14422
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14423
		ASSERT(tcp->tcp_rcv_list == NULL || tcp->tcp_fused_sigurg);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14424
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14425
		mp1 = tcp->tcp_urp_mark_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14426
		tcp->tcp_urp_mark_mp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14427
#ifdef DEBUG
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 14428
		(void) strlog(TCP_MOD_ID, 0, 1, SL_TRACE,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14429
		    "tcp_rput: sending zero-length %s %s",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14430
		    ((mp1->b_flag & MSGMARKNEXT) ? "MSGMARKNEXT" :
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14431
		    "MSGNOTMARKNEXT"),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14432
		    tcp_display(tcp, NULL, DISP_PORT_ONLY));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14433
#endif /* DEBUG */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14434
		putnext(tcp->tcp_rq, mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14435
		flags &= ~TH_SEND_URP_MARK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14436
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14437
	if (flags & TH_ACK_NEEDED) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14438
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14439
		 * Time to send an ack for some reason.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14440
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14441
		mp1 = tcp_ack_mp(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14442
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14443
		if (mp1 != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14444
			TCP_RECORD_TRACE(tcp, mp1, TCP_TRACE_SEND_PKT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14445
			tcp_send_data(tcp, tcp->tcp_wq, mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14446
			BUMP_LOCAL(tcp->tcp_obsegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14447
			BUMP_MIB(&tcp_mib, tcpOutAck);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14448
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14449
		if (tcp->tcp_ack_tid != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14450
			(void) TCP_TIMER_CANCEL(tcp, tcp->tcp_ack_tid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14451
			tcp->tcp_ack_tid = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14452
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14453
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14454
	if (flags & TH_ACK_TIMER_NEEDED) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14455
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14456
		 * Arrange for deferred ACK or push wait timeout.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14457
		 * Start timer if it is not already running.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14458
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14459
		if (tcp->tcp_ack_tid == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14460
			tcp->tcp_ack_tid = TCP_TIMER(tcp, tcp_ack_timer,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14461
			    MSEC_TO_TICK(tcp->tcp_localnet ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14462
			    (clock_t)tcp_local_dack_interval :
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14463
			    (clock_t)tcp_deferred_ack_interval));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14464
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14465
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14466
	if (flags & TH_ORDREL_NEEDED) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14467
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14468
		 * Send up the ordrel_ind unless we are an eager guy.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14469
		 * In the eager case tcp_rsrv will do this when run
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14470
		 * after tcp_accept is done.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14471
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14472
		ASSERT(tcp->tcp_listener == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14473
		if (tcp->tcp_rcv_list != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14474
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14475
			 * Push any mblk(s) enqueued from co processing.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14476
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14477
			flags |= tcp_rcv_drain(tcp->tcp_rq, tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14478
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14479
		ASSERT(tcp->tcp_rcv_list == NULL || tcp->tcp_fused_sigurg);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14480
		if ((mp1 = mi_tpi_ordrel_ind()) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14481
			tcp->tcp_ordrel_done = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14482
			putnext(tcp->tcp_rq, mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14483
			if (tcp->tcp_deferred_clean_death) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14484
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14485
				 * tcp_clean_death was deferred
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14486
				 * for T_ORDREL_IND - do it now
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14487
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14488
				(void) tcp_clean_death(tcp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14489
				    tcp->tcp_client_errno, 20);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14490
				tcp->tcp_deferred_clean_death =	B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14491
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14492
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14493
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14494
			 * Run the orderly release in the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14495
			 * service routine.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14496
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14497
			qenable(tcp->tcp_rq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14498
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14499
			 * Caveat(XXX): The machine may be so
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14500
			 * overloaded that tcp_rsrv() is not scheduled
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14501
			 * until after the endpoint has transitioned
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14502
			 * to TCPS_TIME_WAIT
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14503
			 * and tcp_time_wait_interval expires. Then
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14504
			 * tcp_timer() will blow away state in tcp_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14505
			 * and T_ORDREL_IND will never be delivered
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14506
			 * upstream. Unlikely but potentially
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14507
			 * a problem.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14508
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14509
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14510
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14511
done:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14512
	ASSERT(!(flags & TH_MARKNEXT_NEEDED));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14513
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14514
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14515
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14516
 * This function does PAWS protection check. Returns B_TRUE if the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14517
 * segment passes the PAWS test, else returns B_FALSE.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14518
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14519
boolean_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14520
tcp_paws_check(tcp_t *tcp, tcph_t *tcph, tcp_opt_t *tcpoptp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14521
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14522
	uint8_t	flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14523
	int	options;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14524
	uint8_t *up;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14525
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14526
	flags = (unsigned int)tcph->th_flags[0] & 0xFF;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14527
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14528
	 * If timestamp option is aligned nicely, get values inline,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14529
	 * otherwise call general routine to parse.  Only do that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14530
	 * if timestamp is the only option.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14531
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14532
	if (TCP_HDR_LENGTH(tcph) == (uint32_t)TCP_MIN_HEADER_LENGTH +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14533
	    TCPOPT_REAL_TS_LEN &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14534
	    OK_32PTR((up = ((uint8_t *)tcph) +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14535
	    TCP_MIN_HEADER_LENGTH)) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14536
	    *(uint32_t *)up == TCPOPT_NOP_NOP_TSTAMP) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14537
		tcpoptp->tcp_opt_ts_val = ABE32_TO_U32((up+4));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14538
		tcpoptp->tcp_opt_ts_ecr = ABE32_TO_U32((up+8));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14539
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14540
		options = TCP_OPT_TSTAMP_PRESENT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14541
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14542
		if (tcp->tcp_snd_sack_ok) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14543
			tcpoptp->tcp = tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14544
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14545
			tcpoptp->tcp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14546
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14547
		options = tcp_parse_options(tcph, tcpoptp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14548
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14549
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14550
	if (options & TCP_OPT_TSTAMP_PRESENT) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14551
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14552
		 * Do PAWS per RFC 1323 section 4.2.  Accept RST
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14553
		 * regardless of the timestamp, page 18 RFC 1323.bis.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14554
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14555
		if ((flags & TH_RST) == 0 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14556
		    TSTMP_LT(tcpoptp->tcp_opt_ts_val,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14557
		    tcp->tcp_ts_recent)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14558
			if (TSTMP_LT(lbolt64, tcp->tcp_last_rcv_lbolt +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14559
			    PAWS_TIMEOUT)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14560
				/* This segment is not acceptable. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14561
				return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14562
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14563
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14564
				 * Connection has been idle for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14565
				 * too long.  Reset the timestamp
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14566
				 * and assume the segment is valid.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14567
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14568
				tcp->tcp_ts_recent =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14569
				    tcpoptp->tcp_opt_ts_val;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14570
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14571
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14572
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14573
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14574
		 * If we don't get a timestamp on every packet, we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14575
		 * figure we can't really trust 'em, so we stop sending
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14576
		 * and parsing them.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14577
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14578
		tcp->tcp_snd_ts_ok = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14579
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14580
		tcp->tcp_hdr_len -= TCPOPT_REAL_TS_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14581
		tcp->tcp_tcp_hdr_len -= TCPOPT_REAL_TS_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14582
		tcp->tcp_tcph->th_offset_and_rsrvd[0] -= (3 << 4);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14583
		tcp_mss_set(tcp, tcp->tcp_mss + TCPOPT_REAL_TS_LEN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14584
		if (tcp->tcp_snd_sack_ok) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14585
			ASSERT(tcp->tcp_sack_info != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14586
			tcp->tcp_max_sack_blk = 4;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14587
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14588
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14589
	return (B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14590
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14591
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14592
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14593
 * Attach ancillary data to a received TCP segments for the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14594
 * ancillary pieces requested by the application that are
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14595
 * different than they were in the previous data segment.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14596
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14597
 * Save the "current" values once memory allocation is ok so that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14598
 * when memory allocation fails we can just wait for the next data segment.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14599
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14600
static mblk_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14601
tcp_rput_add_ancillary(tcp_t *tcp, mblk_t *mp, ip6_pkt_t *ipp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14602
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14603
	struct T_optdata_ind *todi;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14604
	int optlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14605
	uchar_t *optptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14606
	struct T_opthdr *toh;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14607
	uint_t addflag;	/* Which pieces to add */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14608
	mblk_t *mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14609
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14610
	optlen = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14611
	addflag = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14612
	/* If app asked for pktinfo and the index has changed ... */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14613
	if ((ipp->ipp_fields & IPPF_IFINDEX) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14614
	    ipp->ipp_ifindex != tcp->tcp_recvifindex &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14615
	    (tcp->tcp_ipv6_recvancillary & TCP_IPV6_RECVPKTINFO)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14616
		optlen += sizeof (struct T_opthdr) +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14617
		    sizeof (struct in6_pktinfo);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14618
		addflag |= TCP_IPV6_RECVPKTINFO;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14619
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14620
	/* If app asked for hoplimit and it has changed ... */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14621
	if ((ipp->ipp_fields & IPPF_HOPLIMIT) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14622
	    ipp->ipp_hoplimit != tcp->tcp_recvhops &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14623
	    (tcp->tcp_ipv6_recvancillary & TCP_IPV6_RECVHOPLIMIT)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14624
		optlen += sizeof (struct T_opthdr) + sizeof (uint_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14625
		addflag |= TCP_IPV6_RECVHOPLIMIT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14626
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14627
	/* If app asked for tclass and it has changed ... */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14628
	if ((ipp->ipp_fields & IPPF_TCLASS) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14629
	    ipp->ipp_tclass != tcp->tcp_recvtclass &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14630
	    (tcp->tcp_ipv6_recvancillary & TCP_IPV6_RECVTCLASS)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14631
		optlen += sizeof (struct T_opthdr) + sizeof (uint_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14632
		addflag |= TCP_IPV6_RECVTCLASS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14633
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14634
	/* If app asked for hopbyhop headers and it has changed ... */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14635
	if ((tcp->tcp_ipv6_recvancillary & TCP_IPV6_RECVHOPOPTS) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14636
	    tcp_cmpbuf(tcp->tcp_hopopts, tcp->tcp_hopoptslen,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14637
		(ipp->ipp_fields & IPPF_HOPOPTS),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14638
		ipp->ipp_hopopts, ipp->ipp_hopoptslen)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14639
		optlen += sizeof (struct T_opthdr) + ipp->ipp_hopoptslen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14640
		addflag |= TCP_IPV6_RECVHOPOPTS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14641
		if (!tcp_allocbuf((void **)&tcp->tcp_hopopts,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14642
		    &tcp->tcp_hopoptslen,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14643
		    (ipp->ipp_fields & IPPF_HOPOPTS),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14644
		    ipp->ipp_hopopts, ipp->ipp_hopoptslen))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14645
			return (mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14646
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14647
	/* If app asked for dst headers before routing headers ... */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14648
	if ((tcp->tcp_ipv6_recvancillary & TCP_IPV6_RECVRTDSTOPTS) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14649
	    tcp_cmpbuf(tcp->tcp_rtdstopts, tcp->tcp_rtdstoptslen,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14650
		(ipp->ipp_fields & IPPF_RTDSTOPTS),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14651
		ipp->ipp_rtdstopts, ipp->ipp_rtdstoptslen)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14652
		optlen += sizeof (struct T_opthdr) +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14653
		    ipp->ipp_rtdstoptslen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14654
		addflag |= TCP_IPV6_RECVRTDSTOPTS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14655
		if (!tcp_allocbuf((void **)&tcp->tcp_rtdstopts,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14656
		    &tcp->tcp_rtdstoptslen,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14657
		    (ipp->ipp_fields & IPPF_RTDSTOPTS),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14658
		    ipp->ipp_rtdstopts, ipp->ipp_rtdstoptslen))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14659
			return (mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14660
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14661
	/* If app asked for routing headers and it has changed ... */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14662
	if ((tcp->tcp_ipv6_recvancillary & TCP_IPV6_RECVRTHDR) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14663
	    tcp_cmpbuf(tcp->tcp_rthdr, tcp->tcp_rthdrlen,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14664
		(ipp->ipp_fields & IPPF_RTHDR),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14665
		ipp->ipp_rthdr, ipp->ipp_rthdrlen)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14666
		optlen += sizeof (struct T_opthdr) + ipp->ipp_rthdrlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14667
		addflag |= TCP_IPV6_RECVRTHDR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14668
		if (!tcp_allocbuf((void **)&tcp->tcp_rthdr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14669
		    &tcp->tcp_rthdrlen,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14670
		    (ipp->ipp_fields & IPPF_RTHDR),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14671
		    ipp->ipp_rthdr, ipp->ipp_rthdrlen))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14672
			return (mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14673
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14674
	/* If app asked for dest headers and it has changed ... */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14675
	if ((tcp->tcp_ipv6_recvancillary &
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14676
		(TCP_IPV6_RECVDSTOPTS | TCP_OLD_IPV6_RECVDSTOPTS)) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14677
	    tcp_cmpbuf(tcp->tcp_dstopts, tcp->tcp_dstoptslen,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14678
		(ipp->ipp_fields & IPPF_DSTOPTS),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14679
		ipp->ipp_dstopts, ipp->ipp_dstoptslen)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14680
		optlen += sizeof (struct T_opthdr) + ipp->ipp_dstoptslen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14681
		addflag |= TCP_IPV6_RECVDSTOPTS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14682
		if (!tcp_allocbuf((void **)&tcp->tcp_dstopts,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14683
		    &tcp->tcp_dstoptslen,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14684
		    (ipp->ipp_fields & IPPF_DSTOPTS),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14685
		    ipp->ipp_dstopts, ipp->ipp_dstoptslen))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14686
			return (mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14687
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14688
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14689
	if (optlen == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14690
		/* Nothing to add */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14691
		return (mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14692
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14693
	mp1 = allocb(sizeof (struct T_optdata_ind) + optlen, BPRI_MED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14694
	if (mp1 == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14695
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14696
		 * Defer sending ancillary data until the next TCP segment
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14697
		 * arrives.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14698
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14699
		return (mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14700
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14701
	mp1->b_cont = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14702
	mp = mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14703
	mp->b_wptr += sizeof (*todi) + optlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14704
	mp->b_datap->db_type = M_PROTO;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14705
	todi = (struct T_optdata_ind *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14706
	todi->PRIM_type = T_OPTDATA_IND;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14707
	todi->DATA_flag = 1;	/* MORE data */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14708
	todi->OPT_length = optlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14709
	todi->OPT_offset = sizeof (*todi);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14710
	optptr = (uchar_t *)&todi[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14711
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14712
	 * If app asked for pktinfo and the index has changed ...
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14713
	 * Note that the local address never changes for the connection.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14714
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14715
	if (addflag & TCP_IPV6_RECVPKTINFO) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14716
		struct in6_pktinfo *pkti;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14717
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14718
		toh = (struct T_opthdr *)optptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14719
		toh->level = IPPROTO_IPV6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14720
		toh->name = IPV6_PKTINFO;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14721
		toh->len = sizeof (*toh) + sizeof (*pkti);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14722
		toh->status = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14723
		optptr += sizeof (*toh);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14724
		pkti = (struct in6_pktinfo *)optptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14725
		if (tcp->tcp_ipversion == IPV6_VERSION)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14726
			pkti->ipi6_addr = tcp->tcp_ip6h->ip6_src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14727
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14728
			IN6_IPADDR_TO_V4MAPPED(tcp->tcp_ipha->ipha_src,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14729
			    &pkti->ipi6_addr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14730
		pkti->ipi6_ifindex = ipp->ipp_ifindex;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14731
		optptr += sizeof (*pkti);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14732
		ASSERT(OK_32PTR(optptr));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14733
		/* Save as "last" value */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14734
		tcp->tcp_recvifindex = ipp->ipp_ifindex;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14735
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14736
	/* If app asked for hoplimit and it has changed ... */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14737
	if (addflag & TCP_IPV6_RECVHOPLIMIT) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14738
		toh = (struct T_opthdr *)optptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14739
		toh->level = IPPROTO_IPV6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14740
		toh->name = IPV6_HOPLIMIT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14741
		toh->len = sizeof (*toh) + sizeof (uint_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14742
		toh->status = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14743
		optptr += sizeof (*toh);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14744
		*(uint_t *)optptr = ipp->ipp_hoplimit;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14745
		optptr += sizeof (uint_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14746
		ASSERT(OK_32PTR(optptr));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14747
		/* Save as "last" value */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14748
		tcp->tcp_recvhops = ipp->ipp_hoplimit;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14749
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14750
	/* If app asked for tclass and it has changed ... */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14751
	if (addflag & TCP_IPV6_RECVTCLASS) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14752
		toh = (struct T_opthdr *)optptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14753
		toh->level = IPPROTO_IPV6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14754
		toh->name = IPV6_TCLASS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14755
		toh->len = sizeof (*toh) + sizeof (uint_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14756
		toh->status = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14757
		optptr += sizeof (*toh);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14758
		*(uint_t *)optptr = ipp->ipp_tclass;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14759
		optptr += sizeof (uint_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14760
		ASSERT(OK_32PTR(optptr));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14761
		/* Save as "last" value */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14762
		tcp->tcp_recvtclass = ipp->ipp_tclass;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14763
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14764
	if (addflag & TCP_IPV6_RECVHOPOPTS) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14765
		toh = (struct T_opthdr *)optptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14766
		toh->level = IPPROTO_IPV6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14767
		toh->name = IPV6_HOPOPTS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14768
		toh->len = sizeof (*toh) + ipp->ipp_hopoptslen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14769
		toh->status = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14770
		optptr += sizeof (*toh);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14771
		bcopy(ipp->ipp_hopopts, optptr, ipp->ipp_hopoptslen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14772
		optptr += ipp->ipp_hopoptslen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14773
		ASSERT(OK_32PTR(optptr));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14774
		/* Save as last value */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14775
		tcp_savebuf((void **)&tcp->tcp_hopopts,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14776
		    &tcp->tcp_hopoptslen,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14777
		    (ipp->ipp_fields & IPPF_HOPOPTS),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14778
		    ipp->ipp_hopopts, ipp->ipp_hopoptslen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14779
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14780
	if (addflag & TCP_IPV6_RECVRTDSTOPTS) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14781
		toh = (struct T_opthdr *)optptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14782
		toh->level = IPPROTO_IPV6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14783
		toh->name = IPV6_RTHDRDSTOPTS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14784
		toh->len = sizeof (*toh) + ipp->ipp_rtdstoptslen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14785
		toh->status = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14786
		optptr += sizeof (*toh);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14787
		bcopy(ipp->ipp_rtdstopts, optptr, ipp->ipp_rtdstoptslen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14788
		optptr += ipp->ipp_rtdstoptslen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14789
		ASSERT(OK_32PTR(optptr));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14790
		/* Save as last value */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14791
		tcp_savebuf((void **)&tcp->tcp_rtdstopts,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14792
		    &tcp->tcp_rtdstoptslen,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14793
		    (ipp->ipp_fields & IPPF_RTDSTOPTS),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14794
		    ipp->ipp_rtdstopts, ipp->ipp_rtdstoptslen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14795
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14796
	if (addflag & TCP_IPV6_RECVRTHDR) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14797
		toh = (struct T_opthdr *)optptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14798
		toh->level = IPPROTO_IPV6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14799
		toh->name = IPV6_RTHDR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14800
		toh->len = sizeof (*toh) + ipp->ipp_rthdrlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14801
		toh->status = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14802
		optptr += sizeof (*toh);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14803
		bcopy(ipp->ipp_rthdr, optptr, ipp->ipp_rthdrlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14804
		optptr += ipp->ipp_rthdrlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14805
		ASSERT(OK_32PTR(optptr));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14806
		/* Save as last value */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14807
		tcp_savebuf((void **)&tcp->tcp_rthdr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14808
		    &tcp->tcp_rthdrlen,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14809
		    (ipp->ipp_fields & IPPF_RTHDR),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14810
		    ipp->ipp_rthdr, ipp->ipp_rthdrlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14811
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14812
	if (addflag & (TCP_IPV6_RECVDSTOPTS | TCP_OLD_IPV6_RECVDSTOPTS)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14813
		toh = (struct T_opthdr *)optptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14814
		toh->level = IPPROTO_IPV6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14815
		toh->name = IPV6_DSTOPTS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14816
		toh->len = sizeof (*toh) + ipp->ipp_dstoptslen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14817
		toh->status = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14818
		optptr += sizeof (*toh);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14819
		bcopy(ipp->ipp_dstopts, optptr, ipp->ipp_dstoptslen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14820
		optptr += ipp->ipp_dstoptslen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14821
		ASSERT(OK_32PTR(optptr));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14822
		/* Save as last value */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14823
		tcp_savebuf((void **)&tcp->tcp_dstopts,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14824
		    &tcp->tcp_dstoptslen,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14825
		    (ipp->ipp_fields & IPPF_DSTOPTS),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14826
		    ipp->ipp_dstopts, ipp->ipp_dstoptslen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14827
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14828
	ASSERT(optptr == mp->b_wptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14829
	return (mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14830
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14831
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14832
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14833
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14834
 * Handle a *T_BIND_REQ that has failed either due to a T_ERROR_ACK
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14835
 * or a "bad" IRE detected by tcp_adapt_ire.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14836
 * We can't tell if the failure was due to the laddr or the faddr
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14837
 * thus we clear out all addresses and ports.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14838
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14839
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14840
tcp_bind_failed(tcp_t *tcp, mblk_t *mp, int error)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14841
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14842
	queue_t	*q = tcp->tcp_rq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14843
	tcph_t	*tcph;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14844
	struct T_error_ack *tea;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14845
	conn_t	*connp = tcp->tcp_connp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14846
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14847
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14848
	ASSERT(mp->b_datap->db_type == M_PCPROTO);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14849
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14850
	if (mp->b_cont) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14851
		freemsg(mp->b_cont);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14852
		mp->b_cont = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14853
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14854
	tea = (struct T_error_ack *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14855
	switch (tea->PRIM_type) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14856
	case T_BIND_ACK:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14857
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14858
		 * Need to unbind with classifier since we were just told that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14859
		 * our bind succeeded.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14860
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14861
		tcp->tcp_hard_bound = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14862
		tcp->tcp_hard_binding = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14863
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14864
		ipcl_hash_remove(connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14865
		/* Reuse the mblk if possible */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14866
		ASSERT(mp->b_datap->db_lim - mp->b_datap->db_base >=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14867
			sizeof (*tea));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14868
		mp->b_rptr = mp->b_datap->db_base;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14869
		mp->b_wptr = mp->b_rptr + sizeof (*tea);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14870
		tea = (struct T_error_ack *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14871
		tea->PRIM_type = T_ERROR_ACK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14872
		tea->TLI_error = TSYSERR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14873
		tea->UNIX_error = error;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14874
		if (tcp->tcp_state >= TCPS_SYN_SENT) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14875
			tea->ERROR_prim = T_CONN_REQ;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14876
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14877
			tea->ERROR_prim = O_T_BIND_REQ;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14878
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14879
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14880
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14881
	case T_ERROR_ACK:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14882
		if (tcp->tcp_state >= TCPS_SYN_SENT)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14883
			tea->ERROR_prim = T_CONN_REQ;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14884
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14885
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14886
		panic("tcp_bind_failed: unexpected TPI type");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14887
		/*NOTREACHED*/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14888
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14889
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14890
	tcp->tcp_state = TCPS_IDLE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14891
	if (tcp->tcp_ipversion == IPV4_VERSION)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14892
		tcp->tcp_ipha->ipha_src = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14893
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14894
		V6_SET_ZERO(tcp->tcp_ip6h->ip6_src);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14895
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14896
	 * Copy of the src addr. in tcp_t is needed since
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14897
	 * the lookup funcs. can only look at tcp_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14898
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14899
	V6_SET_ZERO(tcp->tcp_ip_src_v6);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14900
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14901
	tcph = tcp->tcp_tcph;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14902
	tcph->th_lport[0] = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14903
	tcph->th_lport[1] = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14904
	tcp_bind_hash_remove(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14905
	bzero(&connp->u_port, sizeof (connp->u_port));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14906
	/* blow away saved option results if any */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14907
	if (tcp->tcp_conn.tcp_opts_conn_req != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14908
		tcp_close_mpp(&tcp->tcp_conn.tcp_opts_conn_req);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14909
487
511557ecdec8 6174818 Sun-Fire,serengeti system panicked during lckbugs testing in s10_69
rshoaib
parents: 269
diff changeset
 14910
	conn_delete_ire(tcp->tcp_connp, NULL);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14911
	putnext(q, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14912
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14913
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14914
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14915
 * tcp_rput_other is called by tcp_rput to handle everything other than M_DATA
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14916
 * messages.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14917
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14918
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14919
tcp_rput_other(tcp_t *tcp, mblk_t *mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14920
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14921
	mblk_t	*mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14922
	uchar_t	*rptr = mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14923
	queue_t	*q = tcp->tcp_rq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14924
	struct T_error_ack *tea;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14925
	uint32_t mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14926
	mblk_t *syn_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14927
	mblk_t *mdti;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14928
	int	retval;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14929
	mblk_t *ire_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14930
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14931
	switch (mp->b_datap->db_type) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14932
	case M_PROTO:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14933
	case M_PCPROTO:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14934
		ASSERT((uintptr_t)(mp->b_wptr - rptr) <= (uintptr_t)INT_MAX);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14935
		if ((mp->b_wptr - rptr) < sizeof (t_scalar_t))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14936
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14937
		tea = (struct T_error_ack *)rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14938
		switch (tea->PRIM_type) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14939
		case T_BIND_ACK:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14940
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14941
			 * Adapt Multidata information, if any.  The
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14942
			 * following tcp_mdt_update routine will free
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14943
			 * the message.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14944
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14945
			if ((mdti = tcp_mdt_info_mp(mp)) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14946
				tcp_mdt_update(tcp, &((ip_mdt_info_t *)mdti->
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14947
				    b_rptr)->mdt_capab, B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14948
				freemsg(mdti);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14949
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14950
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14951
			/* Get the IRE, if we had requested for it */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14952
			ire_mp = tcp_ire_mp(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14953
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14954
			if (tcp->tcp_hard_binding) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14955
				tcp->tcp_hard_binding = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14956
				tcp->tcp_hard_bound = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14957
				CL_INET_CONNECT(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14958
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14959
				if (ire_mp != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14960
					freeb(ire_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14961
				goto after_syn_sent;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14962
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14963
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14964
			retval = tcp_adapt_ire(tcp, ire_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14965
			if (ire_mp != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14966
				freeb(ire_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14967
			if (retval == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14968
				tcp_bind_failed(tcp, mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14969
				    (int)((tcp->tcp_state >= TCPS_SYN_SENT) ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14970
				    ENETUNREACH : EADDRNOTAVAIL));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14971
				return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14972
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14973
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14974
			 * Don't let an endpoint connect to itself.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14975
			 * Also checked in tcp_connect() but that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14976
			 * check can't handle the case when the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14977
			 * local IP address is INADDR_ANY.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14978
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14979
			if (tcp->tcp_ipversion == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14980
				if ((tcp->tcp_ipha->ipha_dst ==
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14981
				    tcp->tcp_ipha->ipha_src) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14982
				    (BE16_EQL(tcp->tcp_tcph->th_lport,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14983
				    tcp->tcp_tcph->th_fport))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14984
					tcp_bind_failed(tcp, mp, EADDRNOTAVAIL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14985
					return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14986
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14987
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14988
				if (IN6_ARE_ADDR_EQUAL(
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14989
				    &tcp->tcp_ip6h->ip6_dst,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14990
				    &tcp->tcp_ip6h->ip6_src) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14991
				    (BE16_EQL(tcp->tcp_tcph->th_lport,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14992
				    tcp->tcp_tcph->th_fport))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14993
					tcp_bind_failed(tcp, mp, EADDRNOTAVAIL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14994
					return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14995
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14996
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14997
			ASSERT(tcp->tcp_state == TCPS_SYN_SENT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14998
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14999
			 * This should not be possible!  Just for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15000
			 * defensive coding...
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15001
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15002
			if (tcp->tcp_state != TCPS_SYN_SENT)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15003
				goto after_syn_sent;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15004
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15005
			ASSERT(q == tcp->tcp_rq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15006
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15007
			 * tcp_adapt_ire() does not adjust
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15008
			 * for TCP/IP header length.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15009
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15010
			mss = tcp->tcp_mss - tcp->tcp_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15011
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15012
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15013
			 * Just make sure our rwnd is at
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15014
			 * least tcp_recv_hiwat_mss * MSS
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15015
			 * large, and round up to the nearest
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15016
			 * MSS.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15017
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15018
			 * We do the round up here because
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15019
			 * we need to get the interface
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15020
			 * MTU first before we can do the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15021
			 * round up.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15022
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15023
			tcp->tcp_rwnd = MAX(MSS_ROUNDUP(tcp->tcp_rwnd, mss),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15024
			    tcp_recv_hiwat_minmss * mss);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15025
			q->q_hiwat = tcp->tcp_rwnd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15026
			tcp_set_ws_value(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15027
			U32_TO_ABE16((tcp->tcp_rwnd >> tcp->tcp_rcv_ws),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15028
			    tcp->tcp_tcph->th_win);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15029
			if (tcp->tcp_rcv_ws > 0 || tcp_wscale_always)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15030
				tcp->tcp_snd_ws_ok = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15031
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15032
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15033
			 * Set tcp_snd_ts_ok to true
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15034
			 * so that tcp_xmit_mp will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15035
			 * include the timestamp
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15036
			 * option in the SYN segment.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15037
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15038
			if (tcp_tstamp_always ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15039
			    (tcp->tcp_rcv_ws && tcp_tstamp_if_wscale)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15040
				tcp->tcp_snd_ts_ok = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15041
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15042
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15043
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15044
			 * tcp_snd_sack_ok can be set in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15045
			 * tcp_adapt_ire() if the sack metric
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15046
			 * is set.  So check it here also.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15047
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15048
			if (tcp_sack_permitted == 2 ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15049
			    tcp->tcp_snd_sack_ok) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15050
				if (tcp->tcp_sack_info == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15051
					tcp->tcp_sack_info =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15052
					kmem_cache_alloc(tcp_sack_info_cache,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15053
					    KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15054
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15055
				tcp->tcp_snd_sack_ok = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15056
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15057
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15058
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15059
			 * Should we use ECN?  Note that the current
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15060
			 * default value (SunOS 5.9) of tcp_ecn_permitted
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15061
			 * is 1.  The reason for doing this is that there
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15062
			 * are equipments out there that will drop ECN
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15063
			 * enabled IP packets.  Setting it to 1 avoids
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15064
			 * compatibility problems.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15065
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15066
			if (tcp_ecn_permitted == 2)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15067
				tcp->tcp_ecn_ok = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15068
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15069
			TCP_TIMER_RESTART(tcp, tcp->tcp_rto);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15070
			syn_mp = tcp_xmit_mp(tcp, NULL, 0, NULL, NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15071
			    tcp->tcp_iss, B_FALSE, NULL, B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15072
			if (syn_mp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15073
				cred_t *cr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15074
				pid_t pid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15075
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15076
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15077
				 * Obtain the credential from the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15078
				 * thread calling connect(); the credential
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15079
				 * lives on in the second mblk which
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15080
				 * originated from T_CONN_REQ and is echoed
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15081
				 * with the T_BIND_ACK from ip.  If none
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15082
				 * can be found, default to the creator
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15083
				 * of the socket.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15084
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15085
				if (mp->b_cont == NULL ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15086
				    (cr = DB_CRED(mp->b_cont)) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15087
					cr = tcp->tcp_cred;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15088
					pid = tcp->tcp_cpid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15089
				} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15090
					pid = DB_CPID(mp->b_cont);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15091
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15092
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15093
				TCP_RECORD_TRACE(tcp, syn_mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15094
				    TCP_TRACE_SEND_PKT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15095
				mblk_setcred(syn_mp, cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15096
				DB_CPID(syn_mp) = pid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15097
				tcp_send_data(tcp, tcp->tcp_wq, syn_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15098
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15099
		after_syn_sent:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15100
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15101
			 * A trailer mblk indicates a waiting client upstream.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15102
			 * We complete here the processing begun in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15103
			 * either tcp_bind() or tcp_connect() by passing
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15104
			 * upstream the reply message they supplied.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15105
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15106
			mp1 = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15107
			mp = mp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15108
			freeb(mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15109
			if (mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15110
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15111
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15112
		case T_ERROR_ACK:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15113
			if (tcp->tcp_debug) {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15114
				(void) strlog(TCP_MOD_ID, 0, 1,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15115
				    SL_TRACE|SL_ERROR,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15116
				    "tcp_rput_other: case T_ERROR_ACK, "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15117
				    "ERROR_prim == %d",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15118
				    tea->ERROR_prim);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15119
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15120
			switch (tea->ERROR_prim) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15121
			case O_T_BIND_REQ:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15122
			case T_BIND_REQ:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15123
				tcp_bind_failed(tcp, mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15124
				    (int)((tcp->tcp_state >= TCPS_SYN_SENT) ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15125
				    ENETUNREACH : EADDRNOTAVAIL));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15126
				return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15127
			case T_UNBIND_REQ:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15128
				tcp->tcp_hard_binding = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15129
				tcp->tcp_hard_bound = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15130
				if (mp->b_cont) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15131
					freemsg(mp->b_cont);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15132
					mp->b_cont = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15133
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15134
				if (tcp->tcp_unbind_pending)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15135
					tcp->tcp_unbind_pending = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15136
				else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15137
					/* From tcp_ip_unbind() - free */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15138
					freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15139
					return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15140
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15141
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15142
			case T_SVR4_OPTMGMT_REQ:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15143
				if (tcp->tcp_drop_opt_ack_cnt > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15144
					/* T_OPTMGMT_REQ generated by TCP */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15145
					printf("T_SVR4_OPTMGMT_REQ failed "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15146
					    "%d/%d - dropped (cnt %d)\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15147
					    tea->TLI_error, tea->UNIX_error,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15148
					    tcp->tcp_drop_opt_ack_cnt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15149
					freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15150
					tcp->tcp_drop_opt_ack_cnt--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15151
					return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15152
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15153
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15154
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15155
			if (tea->ERROR_prim == T_SVR4_OPTMGMT_REQ &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15156
			    tcp->tcp_drop_opt_ack_cnt > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15157
				printf("T_SVR4_OPTMGMT_REQ failed %d/%d "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15158
				    "- dropped (cnt %d)\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15159
				    tea->TLI_error, tea->UNIX_error,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15160
				    tcp->tcp_drop_opt_ack_cnt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15161
				freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15162
				tcp->tcp_drop_opt_ack_cnt--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15163
				return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15164
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15165
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15166
		case T_OPTMGMT_ACK:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15167
			if (tcp->tcp_drop_opt_ack_cnt > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15168
				/* T_OPTMGMT_REQ generated by TCP */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15169
				freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15170
				tcp->tcp_drop_opt_ack_cnt--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15171
				return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15172
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15173
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15174
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15175
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15176
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15177
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15178
	case M_CTL:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15179
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15180
		 * ICMP messages.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15181
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15182
		tcp_icmp_error(tcp, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15183
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15184
	case M_FLUSH:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15185
		if (*rptr & FLUSHR)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15186
			flushq(q, FLUSHDATA);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15187
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15188
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15189
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15190
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15191
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15192
	 * Make sure we set this bit before sending the ACK for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15193
	 * bind. Otherwise accept could possibly run and free
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15194
	 * this tcp struct.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15195
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15196
	putnext(q, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15197
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15198
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15199
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15200
 * Called as the result of a qbufcall or a qtimeout to remedy a failure
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15201
 * to allocate a T_ordrel_ind in tcp_rsrv().  qenable(q) will make
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15202
 * tcp_rsrv() try again.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15203
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15204
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15205
tcp_ordrel_kick(void *arg)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15206
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15207
	conn_t 	*connp = (conn_t *)arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15208
	tcp_t	*tcp = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15209
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15210
	tcp->tcp_ordrelid = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15211
	tcp->tcp_timeout = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15212
	if (!TCP_IS_DETACHED(tcp) && tcp->tcp_rq != NULL &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15213
	    tcp->tcp_fin_rcvd && !tcp->tcp_ordrel_done) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15214
		qenable(tcp->tcp_rq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15215
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15216
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15217
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15218
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15219
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15220
tcp_rsrv_input(void *arg, mblk_t *mp, void *arg2)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15221
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15222
	conn_t	*connp = (conn_t *)arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15223
	tcp_t	*tcp = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15224
	queue_t	*q = tcp->tcp_rq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15225
	uint_t	thwin;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15226
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15227
	freeb(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15228
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15229
	TCP_STAT(tcp_rsrv_calls);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15230
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15231
	if (TCP_IS_DETACHED(tcp) || q == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15232
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15233
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15234
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15235
	if (tcp->tcp_fused) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15236
		tcp_t *peer_tcp = tcp->tcp_loopback_peer;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15237
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15238
		ASSERT(tcp->tcp_fused);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15239
		ASSERT(peer_tcp != NULL && peer_tcp->tcp_fused);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15240
		ASSERT(peer_tcp->tcp_loopback_peer == tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15241
		ASSERT(!TCP_IS_DETACHED(tcp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15242
		ASSERT(tcp->tcp_connp->conn_sqp ==
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15243
		    peer_tcp->tcp_connp->conn_sqp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15244
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15245
		/*
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15246
		 * Normally we would not get backenabled in synchronous
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15247
		 * streams mode, but in case this happens, we need to stop
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15248
		 * synchronous streams temporarily to prevent a race with
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15249
		 * 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
 15250
		 * tcp_rcv_list here because those entry points will return
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15251
		 * right away when synchronous streams is stopped.
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15252
		 */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15253
		TCP_FUSE_SYNCSTR_STOP(tcp);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15254
		if (tcp->tcp_rcv_list != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15255
			(void) tcp_rcv_drain(tcp->tcp_rq, tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15256
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15257
		tcp_clrqfull(peer_tcp);
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15258
		TCP_FUSE_SYNCSTR_RESUME(tcp);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15259
		TCP_STAT(tcp_fusion_backenabled);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15260
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15261
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15262
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15263
	if (canputnext(q)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15264
		tcp->tcp_rwnd = q->q_hiwat;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15265
		thwin = ((uint_t)BE16_TO_U16(tcp->tcp_tcph->th_win))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15266
		    << tcp->tcp_rcv_ws;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15267
		thwin -= tcp->tcp_rnxt - tcp->tcp_rack;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15268
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15269
		 * Send back a window update immediately if TCP is above
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15270
		 * ESTABLISHED state and the increase of the rcv window
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15271
		 * that the other side knows is at least 1 MSS after flow
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15272
		 * control is lifted.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15273
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15274
		if (tcp->tcp_state >= TCPS_ESTABLISHED &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15275
		    (q->q_hiwat - thwin >= tcp->tcp_mss)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15276
			tcp_xmit_ctl(NULL, tcp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15277
			    (tcp->tcp_swnd == 0) ? tcp->tcp_suna :
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15278
			    tcp->tcp_snxt, tcp->tcp_rnxt, TH_ACK);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15279
			BUMP_MIB(&tcp_mib, tcpOutWinUpdate);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15280
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15281
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15282
	/* Handle a failure to allocate a T_ORDREL_IND here */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15283
	if (tcp->tcp_fin_rcvd && !tcp->tcp_ordrel_done) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15284
		ASSERT(tcp->tcp_listener == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15285
		if (tcp->tcp_rcv_list != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15286
			(void) tcp_rcv_drain(q, tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15287
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15288
		ASSERT(tcp->tcp_rcv_list == NULL || tcp->tcp_fused_sigurg);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15289
		mp = mi_tpi_ordrel_ind();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15290
		if (mp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15291
			tcp->tcp_ordrel_done = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15292
			putnext(q, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15293
			if (tcp->tcp_deferred_clean_death) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15294
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15295
				 * tcp_clean_death was deferred for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15296
				 * T_ORDREL_IND - do it now
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15297
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15298
				tcp->tcp_deferred_clean_death = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15299
				(void) tcp_clean_death(tcp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15300
				    tcp->tcp_client_errno, 22);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15301
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15302
		} else if (!tcp->tcp_timeout && tcp->tcp_ordrelid == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15303
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15304
			 * If there isn't already a timer running
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15305
			 * start one.  Use a 4 second
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15306
			 * timer as a fallback since it can't fail.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15307
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15308
			tcp->tcp_timeout = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15309
			tcp->tcp_ordrelid = TCP_TIMER(tcp, tcp_ordrel_kick,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15310
			    MSEC_TO_TICK(4000));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15311
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15312
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15313
}
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
 * The read side service routine is called mostly when we get back-enabled as a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15317
 * result of flow control relief.  Since we don't actually queue anything in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15318
 * 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
 15319
 * window, and send out a window update.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15320
 * This routine is also called to drive an orderly release message upstream
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15321
 * if the attempt in tcp_rput failed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15322
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15323
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15324
tcp_rsrv(queue_t *q)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15325
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15326
	conn_t *connp = Q_TO_CONN(q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15327
	tcp_t	*tcp = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15328
	mblk_t	*mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15329
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15330
	/* No code does a putq on the read side */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15331
	ASSERT(q->q_first == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15332
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15333
	/* Nothing to do for the default queue */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15334
	if (q == tcp_g_q) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15335
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15336
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15337
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15338
	mp = allocb(0, BPRI_HI);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15339
	if (mp == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15340
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15341
		 * We are under memory pressure. Return for now and we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15342
		 * we will be called again later.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15343
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15344
		if (!tcp->tcp_timeout && tcp->tcp_ordrelid == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15345
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15346
			 * If there isn't already a timer running
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15347
			 * start one.  Use a 4 second
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15348
			 * timer as a fallback since it can't fail.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15349
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15350
			tcp->tcp_timeout = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15351
			tcp->tcp_ordrelid = TCP_TIMER(tcp, tcp_ordrel_kick,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15352
			    MSEC_TO_TICK(4000));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15353
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15354
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15355
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15356
	CONN_INC_REF(connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15357
	squeue_enter(connp->conn_sqp, mp, tcp_rsrv_input, connp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15358
	    SQTAG_TCP_RSRV);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15359
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15360
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15361
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15362
 * tcp_rwnd_set() is called to adjust the receive window to a desired value.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15363
 * We do not allow the receive window to shrink.  After setting rwnd,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15364
 * set the flow control hiwat of the stream.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15365
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15366
 * This function is called in 2 cases:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15367
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15368
 * 1) Before data transfer begins, in tcp_accept_comm() for accepting a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15369
 *    connection (passive open) and in tcp_rput_data() for active connect.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15370
 *    This is called after tcp_mss_set() when the desired MSS value is known.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15371
 *    This makes sure that our window size is a mutiple of the other side's
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15372
 *    MSS.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15373
 * 2) Handling SO_RCVBUF option.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15374
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15375
 * It is ASSUMED that the requested size is a multiple of the current MSS.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15376
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15377
 * XXX - Should allow a lower rwnd than tcp_recv_hiwat_minmss * mss if the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15378
 * user requests so.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15379
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15380
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15381
tcp_rwnd_set(tcp_t *tcp, uint32_t rwnd)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15382
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15383
	uint32_t	mss = tcp->tcp_mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15384
	uint32_t	old_max_rwnd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15385
	uint32_t	max_transmittable_rwnd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15386
	boolean_t	tcp_detached = TCP_IS_DETACHED(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15387
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15388
	if (tcp->tcp_fused) {
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15389
		size_t sth_hiwat;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15390
		tcp_t *peer_tcp = tcp->tcp_loopback_peer;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15391
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15392
		ASSERT(peer_tcp != NULL);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15393
		/*
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15394
		 * Record the stream head's high water mark for
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15395
		 * this endpoint; this is used for flow-control
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15396
		 * purposes in tcp_fuse_output().
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15397
		 */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15398
		sth_hiwat = tcp_fuse_set_rcv_hiwat(tcp, rwnd);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15399
		if (!tcp_detached)
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15400
			(void) mi_set_sth_hiwat(tcp->tcp_rq, sth_hiwat);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15401
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15402
		/*
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15403
		 * In the fusion case, the maxpsz stream head value of
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15404
		 * our peer is set according to its send buffer size
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15405
		 * and our receive buffer size; since the latter may
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15406
		 * have changed we need to update the peer's maxpsz.
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15407
		 */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15408
		(void) tcp_maxpsz_set(peer_tcp, B_TRUE);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15409
		return (rwnd);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15410
	}
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15411
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15412
	if (tcp_detached)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15413
		old_max_rwnd = tcp->tcp_rwnd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15414
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15415
		old_max_rwnd = tcp->tcp_rq->q_hiwat;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15416
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15417
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15418
	 * Insist on a receive window that is at least
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15419
	 * tcp_recv_hiwat_minmss * MSS (default 4 * MSS) to avoid
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15420
	 * funny TCP interactions of Nagle algorithm, SWS avoidance
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15421
	 * and delayed acknowledgement.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15422
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15423
	rwnd = MAX(rwnd, tcp_recv_hiwat_minmss * mss);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15424
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15425
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15426
	 * If window size info has already been exchanged, TCP should not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15427
	 * shrink the window.  Shrinking window is doable if done carefully.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15428
	 * We may add that support later.  But so far there is not a real
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15429
	 * need to do that.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15430
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15431
	if (rwnd < old_max_rwnd && tcp->tcp_state > TCPS_SYN_SENT) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15432
		/* MSS may have changed, do a round up again. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15433
		rwnd = MSS_ROUNDUP(old_max_rwnd, mss);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15434
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15435
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15436
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15437
	 * tcp_rcv_ws starts with TCP_MAX_WINSHIFT so the following check
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15438
	 * can be applied even before the window scale option is decided.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15439
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15440
	max_transmittable_rwnd = TCP_MAXWIN << tcp->tcp_rcv_ws;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15441
	if (rwnd > max_transmittable_rwnd) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15442
		rwnd = max_transmittable_rwnd -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15443
		    (max_transmittable_rwnd % mss);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15444
		if (rwnd < mss)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15445
			rwnd = max_transmittable_rwnd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15446
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15447
		 * If we're over the limit we may have to back down tcp_rwnd.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15448
		 * The increment below won't work for us. So we set all three
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15449
		 * here and the increment below will have no effect.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15450
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15451
		tcp->tcp_rwnd = old_max_rwnd = rwnd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15452
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15453
	if (tcp->tcp_localnet) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15454
		tcp->tcp_rack_abs_max =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15455
		    MIN(tcp_local_dacks_max, rwnd / mss / 2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15456
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15457
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15458
		 * For a remote host on a different subnet (through a router),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15459
		 * we ack every other packet to be conforming to RFC1122.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15460
		 * tcp_deferred_acks_max is default to 2.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15461
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15462
		tcp->tcp_rack_abs_max =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15463
		    MIN(tcp_deferred_acks_max, rwnd / mss / 2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15464
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15465
	if (tcp->tcp_rack_cur_max > tcp->tcp_rack_abs_max)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15466
		tcp->tcp_rack_cur_max = tcp->tcp_rack_abs_max;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15467
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15468
		tcp->tcp_rack_cur_max = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15469
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15470
	 * Increment the current rwnd by the amount the maximum grew (we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15471
	 * can not overwrite it since we might be in the middle of a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15472
	 * connection.)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15473
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15474
	tcp->tcp_rwnd += rwnd - old_max_rwnd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15475
	U32_TO_ABE16(tcp->tcp_rwnd >> tcp->tcp_rcv_ws, tcp->tcp_tcph->th_win);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15476
	if ((tcp->tcp_rcv_ws > 0) && rwnd > tcp->tcp_cwnd_max)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15477
		tcp->tcp_cwnd_max = rwnd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15478
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15479
	if (tcp_detached)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15480
		return (rwnd);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15481
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15482
	 * We set the maximum receive window into rq->q_hiwat.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15483
	 * This is not actually used for flow control.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15484
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15485
	tcp->tcp_rq->q_hiwat = rwnd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15486
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15487
	 * Set the Stream head high water mark. This doesn't have to be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15488
	 * here, since we are simply using default values, but we would
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15489
	 * prefer to choose these values algorithmically, with a likely
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15490
	 * relationship to rwnd.
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15491
	 */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15492
	(void) mi_set_sth_hiwat(tcp->tcp_rq, MAX(rwnd, tcp_sth_rcv_hiwat));
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15493
	return (rwnd);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15494
}
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
 * Return SNMP stuff in buffer in mpdata.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15498
 */
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15499
int
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15500
tcp_snmp_get(queue_t *q, mblk_t *mpctl)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15501
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15502
	mblk_t			*mpdata;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15503
	mblk_t			*mp_conn_ctl = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15504
	mblk_t			*mp_conn_data;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15505
	mblk_t			*mp6_conn_ctl = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15506
	mblk_t			*mp6_conn_data;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15507
	mblk_t			*mp_conn_tail = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15508
	mblk_t			*mp6_conn_tail = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15509
	struct opthdr		*optp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15510
	mib2_tcpConnEntry_t	tce;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15511
	mib2_tcp6ConnEntry_t	tce6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15512
	connf_t			*connfp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15513
	conn_t			*connp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15514
	int			i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15515
	boolean_t 		ispriv;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15516
	zoneid_t 		zoneid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15517
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15518
	if (mpctl == NULL ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15519
	    (mpdata = mpctl->b_cont) == NULL ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15520
	    (mp_conn_ctl = copymsg(mpctl)) == NULL ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15521
	    (mp6_conn_ctl = copymsg(mpctl)) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15522
		if (mp_conn_ctl != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15523
			freemsg(mp_conn_ctl);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15524
		if (mp6_conn_ctl != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15525
			freemsg(mp6_conn_ctl);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15526
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15527
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15528
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15529
	/* build table of connections -- need count in fixed part */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15530
	mp_conn_data = mp_conn_ctl->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15531
	mp6_conn_data = mp6_conn_ctl->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15532
	SET_MIB(tcp_mib.tcpRtoAlgorithm, 4);   /* vanj */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15533
	SET_MIB(tcp_mib.tcpRtoMin, tcp_rexmit_interval_min);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15534
	SET_MIB(tcp_mib.tcpRtoMax, tcp_rexmit_interval_max);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15535
	SET_MIB(tcp_mib.tcpMaxConn, -1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15536
	SET_MIB(tcp_mib.tcpCurrEstab, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15537
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15538
	ispriv =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15539
	    secpolicy_net_config((Q_TO_CONN(q))->conn_cred, B_TRUE) == 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15540
	zoneid = Q_TO_CONN(q)->conn_zoneid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15541
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15542
	for (i = 0; i < CONN_G_HASH_SIZE; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15543
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15544
		connfp = &ipcl_globalhash_fanout[i];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15545
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15546
		connp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15547
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15548
		while ((connp =
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15549
		    ipcl_get_next_conn(connfp, connp, IPCL_TCP)) != NULL) {
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15550
			tcp_t *tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15551
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15552
			if (connp->conn_zoneid != zoneid)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15553
				continue;	/* not in this zone */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15554
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15555
			tcp = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15556
			UPDATE_MIB(&tcp_mib, tcpInSegs, tcp->tcp_ibsegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15557
			tcp->tcp_ibsegs = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15558
			UPDATE_MIB(&tcp_mib, tcpOutSegs, tcp->tcp_obsegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15559
			tcp->tcp_obsegs = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15560
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15561
			tce6.tcp6ConnState = tce.tcpConnState =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15562
			    tcp_snmp_state(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15563
			if (tce.tcpConnState == MIB2_TCP_established ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15564
			    tce.tcpConnState == MIB2_TCP_closeWait)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15565
				BUMP_MIB(&tcp_mib, tcpCurrEstab);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15566
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15567
			/* Create a message to report on IPv6 entries */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15568
			if (tcp->tcp_ipversion == IPV6_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15569
			tce6.tcp6ConnLocalAddress = tcp->tcp_ip_src_v6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15570
			tce6.tcp6ConnRemAddress = tcp->tcp_remote_v6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15571
			tce6.tcp6ConnLocalPort = ntohs(tcp->tcp_lport);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15572
			tce6.tcp6ConnRemPort = ntohs(tcp->tcp_fport);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15573
			tce6.tcp6ConnIfIndex = tcp->tcp_bound_if;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15574
			/* Don't want just anybody seeing these... */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15575
			if (ispriv) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15576
				tce6.tcp6ConnEntryInfo.ce_snxt =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15577
				    tcp->tcp_snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15578
				tce6.tcp6ConnEntryInfo.ce_suna =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15579
				    tcp->tcp_suna;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15580
				tce6.tcp6ConnEntryInfo.ce_rnxt =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15581
				    tcp->tcp_rnxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15582
				tce6.tcp6ConnEntryInfo.ce_rack =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15583
				    tcp->tcp_rack;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15584
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15585
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15586
				 * Netstat, unfortunately, uses this to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15587
				 * get send/receive queue sizes.  How to fix?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15588
				 * Why not compute the difference only?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15589
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15590
				tce6.tcp6ConnEntryInfo.ce_snxt =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15591
				    tcp->tcp_snxt - tcp->tcp_suna;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15592
				tce6.tcp6ConnEntryInfo.ce_suna = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15593
				tce6.tcp6ConnEntryInfo.ce_rnxt =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15594
				    tcp->tcp_rnxt - tcp->tcp_rack;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15595
				tce6.tcp6ConnEntryInfo.ce_rack = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15596
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15597
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15598
			tce6.tcp6ConnEntryInfo.ce_swnd = tcp->tcp_swnd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15599
			tce6.tcp6ConnEntryInfo.ce_rwnd = tcp->tcp_rwnd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15600
			tce6.tcp6ConnEntryInfo.ce_rto =  tcp->tcp_rto;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15601
			tce6.tcp6ConnEntryInfo.ce_mss =  tcp->tcp_mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15602
			tce6.tcp6ConnEntryInfo.ce_state = tcp->tcp_state;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15603
			(void) snmp_append_data2(mp6_conn_data, &mp6_conn_tail,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15604
			    (char *)&tce6, sizeof (tce6));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15605
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15606
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15607
			 * Create an IPv4 table entry for IPv4 entries and also
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15608
			 * for IPv6 entries which are bound to in6addr_any
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15609
			 * but don't have IPV6_V6ONLY set.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15610
			 * (i.e. anything an IPv4 peer could connect to)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15611
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15612
			if (tcp->tcp_ipversion == IPV4_VERSION ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15613
			    (tcp->tcp_state <= TCPS_LISTEN &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15614
			    !tcp->tcp_connp->conn_ipv6_v6only &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15615
			    IN6_IS_ADDR_UNSPECIFIED(&tcp->tcp_ip_src_v6))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15616
				if (tcp->tcp_ipversion == IPV6_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15617
					tce.tcpConnRemAddress = INADDR_ANY;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15618
					tce.tcpConnLocalAddress = INADDR_ANY;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15619
				} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15620
					tce.tcpConnRemAddress =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15621
					    tcp->tcp_remote;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15622
					tce.tcpConnLocalAddress =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15623
					    tcp->tcp_ip_src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15624
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15625
				tce.tcpConnLocalPort = ntohs(tcp->tcp_lport);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15626
				tce.tcpConnRemPort = ntohs(tcp->tcp_fport);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15627
				/* Don't want just anybody seeing these... */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15628
				if (ispriv) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15629
					tce.tcpConnEntryInfo.ce_snxt =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15630
					    tcp->tcp_snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15631
					tce.tcpConnEntryInfo.ce_suna =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15632
					    tcp->tcp_suna;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15633
					tce.tcpConnEntryInfo.ce_rnxt =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15634
					    tcp->tcp_rnxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15635
					tce.tcpConnEntryInfo.ce_rack =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15636
					    tcp->tcp_rack;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15637
				} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15638
					/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15639
					 * Netstat, unfortunately, uses this to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15640
					 * get send/receive queue sizes.  How
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15641
					 * to fix?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15642
					 * Why not compute the difference only?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15643
					 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15644
					tce.tcpConnEntryInfo.ce_snxt =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15645
					    tcp->tcp_snxt - tcp->tcp_suna;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15646
					tce.tcpConnEntryInfo.ce_suna = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15647
					tce.tcpConnEntryInfo.ce_rnxt =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15648
					    tcp->tcp_rnxt - tcp->tcp_rack;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15649
					tce.tcpConnEntryInfo.ce_rack = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15650
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15651
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15652
				tce.tcpConnEntryInfo.ce_swnd = tcp->tcp_swnd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15653
				tce.tcpConnEntryInfo.ce_rwnd = tcp->tcp_rwnd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15654
				tce.tcpConnEntryInfo.ce_rto =  tcp->tcp_rto;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15655
				tce.tcpConnEntryInfo.ce_mss =  tcp->tcp_mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15656
				tce.tcpConnEntryInfo.ce_state =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15657
				    tcp->tcp_state;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15658
				(void) snmp_append_data2(mp_conn_data,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15659
				    &mp_conn_tail, (char *)&tce, sizeof (tce));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15660
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15661
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15662
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15663
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15664
	/* fixed length structure for IPv4 and IPv6 counters */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15665
	SET_MIB(tcp_mib.tcpConnTableSize, sizeof (mib2_tcpConnEntry_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15666
	SET_MIB(tcp_mib.tcp6ConnTableSize, sizeof (mib2_tcp6ConnEntry_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15667
	optp = (struct opthdr *)&mpctl->b_rptr[sizeof (struct T_optmgmt_ack)];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15668
	optp->level = MIB2_TCP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15669
	optp->name = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15670
	(void) snmp_append_data(mpdata, (char *)&tcp_mib, sizeof (tcp_mib));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15671
	optp->len = msgdsize(mpdata);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15672
	qreply(q, mpctl);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15673
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15674
	/* table of connections... */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15675
	optp = (struct opthdr *)&mp_conn_ctl->b_rptr[
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15676
	    sizeof (struct T_optmgmt_ack)];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15677
	optp->level = MIB2_TCP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15678
	optp->name = MIB2_TCP_CONN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15679
	optp->len = msgdsize(mp_conn_data);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15680
	qreply(q, mp_conn_ctl);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15681
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15682
	/* table of IPv6 connections... */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15683
	optp = (struct opthdr *)&mp6_conn_ctl->b_rptr[
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15684
	    sizeof (struct T_optmgmt_ack)];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15685
	optp->level = MIB2_TCP6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15686
	optp->name = MIB2_TCP6_CONN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15687
	optp->len = msgdsize(mp6_conn_data);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15688
	qreply(q, mp6_conn_ctl);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15689
	return (1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15690
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15691
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15692
/* Return 0 if invalid set request, 1 otherwise, including non-tcp requests  */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15693
/* ARGSUSED */
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15694
int
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15695
tcp_snmp_set(queue_t *q, int level, int name, uchar_t *ptr, int len)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15696
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15697
	mib2_tcpConnEntry_t	*tce = (mib2_tcpConnEntry_t *)ptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15698
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15699
	switch (level) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15700
	case MIB2_TCP:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15701
		switch (name) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15702
		case 13:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15703
			if (tce->tcpConnState != MIB2_TCP_deleteTCB)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15704
				return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15705
			/* TODO: delete entry defined by tce */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15706
			return (1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15707
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15708
			return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15709
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15710
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15711
		return (1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15712
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15713
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15714
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15715
/* Translate TCP state to MIB2 TCP state. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15716
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15717
tcp_snmp_state(tcp_t *tcp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15718
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15719
	if (tcp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15720
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15721
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15722
	switch (tcp->tcp_state) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15723
	case TCPS_CLOSED:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15724
	case TCPS_IDLE:	/* RFC1213 doesn't have analogue for IDLE & BOUND */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15725
	case TCPS_BOUND:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15726
		return (MIB2_TCP_closed);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15727
	case TCPS_LISTEN:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15728
		return (MIB2_TCP_listen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15729
	case TCPS_SYN_SENT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15730
		return (MIB2_TCP_synSent);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15731
	case TCPS_SYN_RCVD:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15732
		return (MIB2_TCP_synReceived);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15733
	case TCPS_ESTABLISHED:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15734
		return (MIB2_TCP_established);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15735
	case TCPS_CLOSE_WAIT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15736
		return (MIB2_TCP_closeWait);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15737
	case TCPS_FIN_WAIT_1:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15738
		return (MIB2_TCP_finWait1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15739
	case TCPS_CLOSING:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15740
		return (MIB2_TCP_closing);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15741
	case TCPS_LAST_ACK:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15742
		return (MIB2_TCP_lastAck);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15743
	case TCPS_FIN_WAIT_2:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15744
		return (MIB2_TCP_finWait2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15745
	case TCPS_TIME_WAIT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15746
		return (MIB2_TCP_timeWait);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15747
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15748
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15749
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15750
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15751
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15752
static char tcp_report_header[] =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15753
	"TCP     " MI_COL_HDRPAD_STR
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15754
	"zone dest            snxt     suna     "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15755
	"swnd       rnxt     rack     rwnd       rto   mss   w sw rw t "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15756
	"recent   [lport,fport] state";
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15757
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15758
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15759
 * TCP status report triggered via the Named Dispatch mechanism.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15760
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15761
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15762
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15763
tcp_report_item(mblk_t *mp, tcp_t *tcp, int hashval, tcp_t *thisstream,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15764
    cred_t *cr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15765
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15766
	char hash[10], addrbuf[INET6_ADDRSTRLEN];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15767
	boolean_t ispriv = secpolicy_net_config(cr, B_TRUE) == 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15768
	char cflag;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15769
	in6_addr_t	v6dst;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15770
	char buf[80];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15771
	uint_t print_len, buf_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15772
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15773
	buf_len = mp->b_datap->db_lim - mp->b_wptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15774
	if (buf_len <= 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15775
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15776
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15777
	if (hashval >= 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15778
		(void) sprintf(hash, "%03d ", hashval);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15779
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15780
		hash[0] = '\0';
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15781
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15782
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15783
	 * Note that we use the remote address in the tcp_b  structure.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15784
	 * This means that it will print out the real destination address,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15785
	 * not the next hop's address if source routing is used.  This
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15786
	 * avoid the confusion on the output because user may not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15787
	 * know that source routing is used for a connection.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15788
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15789
	if (tcp->tcp_ipversion == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15790
		IN6_IPADDR_TO_V4MAPPED(tcp->tcp_remote, &v6dst);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15791
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15792
		v6dst = tcp->tcp_remote_v6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15793
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15794
	(void) inet_ntop(AF_INET6, &v6dst, addrbuf, sizeof (addrbuf));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15795
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15796
	 * the ispriv checks are so that normal users cannot determine
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15797
	 * sequence number information using NDD.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15798
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15799
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15800
	if (TCP_IS_DETACHED(tcp))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15801
		cflag = '*';
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15802
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15803
		cflag = ' ';
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15804
	print_len = snprintf((char *)mp->b_wptr, buf_len,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15805
	    "%s " MI_COL_PTRFMT_STR "%d %s %08x %08x %010d %08x %08x "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15806
	    "%010d %05ld %05d %1d %02d %02d %1d %08x %s%c\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15807
	    hash,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15808
	    (void *)tcp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15809
	    tcp->tcp_connp->conn_zoneid,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15810
	    addrbuf,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15811
	    (ispriv) ? tcp->tcp_snxt : 0,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15812
	    (ispriv) ? tcp->tcp_suna : 0,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15813
	    tcp->tcp_swnd,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15814
	    (ispriv) ? tcp->tcp_rnxt : 0,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15815
	    (ispriv) ? tcp->tcp_rack : 0,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15816
	    tcp->tcp_rwnd,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15817
	    tcp->tcp_rto,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15818
	    tcp->tcp_mss,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15819
	    tcp->tcp_snd_ws_ok,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15820
	    tcp->tcp_snd_ws,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15821
	    tcp->tcp_rcv_ws,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15822
	    tcp->tcp_snd_ts_ok,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15823
	    tcp->tcp_ts_recent,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15824
	    tcp_display(tcp, buf, DISP_PORT_ONLY), cflag);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15825
	if (print_len < buf_len) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15826
		((mblk_t *)mp)->b_wptr += print_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15827
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15828
		((mblk_t *)mp)->b_wptr += buf_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15829
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15830
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15831
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15832
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15833
 * TCP status report (for listeners only) triggered via the Named Dispatch
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15834
 * mechanism.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15835
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15836
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15837
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15838
tcp_report_listener(mblk_t *mp, tcp_t *tcp, int hashval)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15839
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15840
	char addrbuf[INET6_ADDRSTRLEN];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15841
	in6_addr_t	v6dst;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15842
	uint_t print_len, buf_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15843
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15844
	buf_len = mp->b_datap->db_lim - mp->b_wptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15845
	if (buf_len <= 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15846
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15847
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15848
	if (tcp->tcp_ipversion == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15849
		IN6_IPADDR_TO_V4MAPPED(tcp->tcp_ipha->ipha_src, &v6dst);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15850
		(void) inet_ntop(AF_INET6, &v6dst, addrbuf, sizeof (addrbuf));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15851
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15852
		(void) inet_ntop(AF_INET6, &tcp->tcp_ip6h->ip6_src,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15853
		    addrbuf, sizeof (addrbuf));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15854
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15855
	print_len = snprintf((char *)mp->b_wptr, buf_len,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15856
	    "%03d "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15857
	    MI_COL_PTRFMT_STR
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15858
	    "%d %s %05u %08u %d/%d/%d%c\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15859
	    hashval, (void *)tcp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15860
	    tcp->tcp_connp->conn_zoneid,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15861
	    addrbuf,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15862
	    (uint_t)BE16_TO_U16(tcp->tcp_tcph->th_lport),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15863
	    tcp->tcp_conn_req_seqnum,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15864
	    tcp->tcp_conn_req_cnt_q0, tcp->tcp_conn_req_cnt_q,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15865
	    tcp->tcp_conn_req_max,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15866
	    tcp->tcp_syn_defense ? '*' : ' ');
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15867
	if (print_len < buf_len) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15868
		((mblk_t *)mp)->b_wptr += print_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15869
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15870
		((mblk_t *)mp)->b_wptr += buf_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15871
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15872
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15873
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15874
/* TCP status report triggered via the Named Dispatch mechanism. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15875
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15876
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15877
tcp_status_report(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *cr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15878
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15879
	tcp_t	*tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15880
	int	i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15881
	conn_t	*connp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15882
	connf_t	*connfp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15883
	zoneid_t zoneid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15884
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15885
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15886
	 * Because of the ndd constraint, at most we can have 64K buffer
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15887
	 * to put in all TCP info.  So to be more efficient, just
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15888
	 * allocate a 64K buffer here, assuming we need that large buffer.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15889
	 * This may be a problem as any user can read tcp_status.  Therefore
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15890
	 * we limit the rate of doing this using tcp_ndd_get_info_interval.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15891
	 * This should be OK as normal users should not do this too often.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15892
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15893
	if (cr == NULL || secpolicy_net_config(cr, B_TRUE) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15894
		if (ddi_get_lbolt() - tcp_last_ndd_get_info_time <
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15895
		    drv_usectohz(tcp_ndd_get_info_interval * 1000)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15896
			(void) mi_mpprintf(mp, NDD_TOO_QUICK_MSG);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15897
			return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15898
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15899
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15900
	if ((mp->b_cont = allocb(ND_MAX_BUF_LEN, BPRI_HI)) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15901
		/* The following may work even if we cannot get a large buf. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15902
		(void) mi_mpprintf(mp, NDD_OUT_OF_BUF_MSG);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15903
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15904
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15905
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15906
	(void) mi_mpprintf(mp, "%s", tcp_report_header);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15907
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15908
	zoneid = Q_TO_CONN(q)->conn_zoneid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15909
	for (i = 0; i < CONN_G_HASH_SIZE; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15910
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15911
		connfp = &ipcl_globalhash_fanout[i];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15912
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15913
		connp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15914
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15915
		while ((connp =
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15916
		    ipcl_get_next_conn(connfp, connp, IPCL_TCP)) != NULL) {
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15917
			tcp = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15918
			if (zoneid != GLOBAL_ZONEID &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15919
			    zoneid != connp->conn_zoneid)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15920
				continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15921
			tcp_report_item(mp->b_cont, tcp, -1, tcp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15922
			    cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15923
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15924
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15925
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15926
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15927
	tcp_last_ndd_get_info_time = ddi_get_lbolt();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15928
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15929
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15930
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15931
/* TCP status report triggered via the Named Dispatch mechanism. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15932
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15933
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15934
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
 15935
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15936
	tf_t	*tbf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15937
	tcp_t	*tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15938
	int	i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15939
	zoneid_t zoneid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15940
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15941
	/* Refer to comments in tcp_status_report(). */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15942
	if (cr == NULL || secpolicy_net_config(cr, B_TRUE) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15943
		if (ddi_get_lbolt() - tcp_last_ndd_get_info_time <
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15944
		    drv_usectohz(tcp_ndd_get_info_interval * 1000)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15945
			(void) mi_mpprintf(mp, NDD_TOO_QUICK_MSG);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15946
			return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15947
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15948
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15949
	if ((mp->b_cont = allocb(ND_MAX_BUF_LEN, BPRI_HI)) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15950
		/* The following may work even if we cannot get a large buf. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15951
		(void) mi_mpprintf(mp, NDD_OUT_OF_BUF_MSG);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15952
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15953
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15954
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15955
	(void) mi_mpprintf(mp, "    %s", tcp_report_header);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15956
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15957
	zoneid = Q_TO_CONN(q)->conn_zoneid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15958
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15959
	for (i = 0; i < A_CNT(tcp_bind_fanout); i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15960
		tbf = &tcp_bind_fanout[i];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15961
		mutex_enter(&tbf->tf_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15962
		for (tcp = tbf->tf_tcp; tcp != NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15963
		    tcp = tcp->tcp_bind_hash) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15964
			if (zoneid != GLOBAL_ZONEID &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15965
			    zoneid != tcp->tcp_connp->conn_zoneid)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15966
				continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15967
			CONN_INC_REF(tcp->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15968
			tcp_report_item(mp->b_cont, tcp, i,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15969
			    Q_TO_TCP(q), cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15970
			CONN_DEC_REF(tcp->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15971
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15972
		mutex_exit(&tbf->tf_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15973
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15974
	tcp_last_ndd_get_info_time = ddi_get_lbolt();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15975
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15976
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15977
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15978
/* TCP status report triggered via the Named Dispatch mechanism. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15979
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15980
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15981
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
 15982
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15983
	connf_t	*connfp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15984
	conn_t	*connp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15985
	tcp_t	*tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15986
	int	i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15987
	zoneid_t zoneid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15988
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15989
	/* Refer to comments in tcp_status_report(). */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15990
	if (cr == NULL || secpolicy_net_config(cr, B_TRUE) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15991
		if (ddi_get_lbolt() - tcp_last_ndd_get_info_time <
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15992
		    drv_usectohz(tcp_ndd_get_info_interval * 1000)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15993
			(void) mi_mpprintf(mp, NDD_TOO_QUICK_MSG);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15994
			return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15995
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15996
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15997
	if ((mp->b_cont = allocb(ND_MAX_BUF_LEN, BPRI_HI)) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15998
		/* The following may work even if we cannot get a large buf. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15999
		(void) mi_mpprintf(mp, NDD_OUT_OF_BUF_MSG);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16000
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16001
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16002
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16003
	(void) mi_mpprintf(mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16004
	    "    TCP    " MI_COL_HDRPAD_STR
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16005
	    "zone IP addr         port  seqnum   backlog (q0/q/max)");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16006
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16007
	zoneid = Q_TO_CONN(q)->conn_zoneid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16008
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16009
	for (i = 0; i < ipcl_bind_fanout_size; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16010
		connfp =  &ipcl_bind_fanout[i];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16011
		connp = NULL;
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 16012
		while ((connp =
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 16013
		    ipcl_get_next_conn(connfp, connp, IPCL_TCP)) != NULL) {
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16014
			tcp = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16015
			if (zoneid != GLOBAL_ZONEID &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16016
			    zoneid != connp->conn_zoneid)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16017
				continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16018
			tcp_report_listener(mp->b_cont, tcp, i);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16019
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16020
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16021
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16022
	tcp_last_ndd_get_info_time = ddi_get_lbolt();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16023
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16024
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16025
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16026
/* TCP status report triggered via the Named Dispatch mechanism. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16027
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16028
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16029
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
 16030
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16031
	connf_t	*connfp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16032
	conn_t	*connp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16033
	tcp_t	*tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16034
	int	i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16035
	zoneid_t zoneid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16036
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16037
	/* Refer to comments in tcp_status_report(). */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16038
	if (cr == NULL || secpolicy_net_config(cr, B_TRUE) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16039
		if (ddi_get_lbolt() - tcp_last_ndd_get_info_time <
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16040
		    drv_usectohz(tcp_ndd_get_info_interval * 1000)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16041
			(void) mi_mpprintf(mp, NDD_TOO_QUICK_MSG);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16042
			return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16043
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16044
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16045
	if ((mp->b_cont = allocb(ND_MAX_BUF_LEN, BPRI_HI)) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16046
		/* The following may work even if we cannot get a large buf. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16047
		(void) mi_mpprintf(mp, NDD_OUT_OF_BUF_MSG);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16048
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16049
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16050
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16051
	(void) mi_mpprintf(mp, "tcp_conn_hash_size = %d",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16052
	    ipcl_conn_fanout_size);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16053
	(void) mi_mpprintf(mp, "    %s", tcp_report_header);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16054
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16055
	zoneid = Q_TO_CONN(q)->conn_zoneid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16056
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16057
	for (i = 0; i < ipcl_conn_fanout_size; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16058
		connfp =  &ipcl_conn_fanout[i];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16059
		connp = NULL;
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 16060
		while ((connp =
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 16061
		    ipcl_get_next_conn(connfp, connp, IPCL_TCP)) != NULL) {
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16062
			tcp = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16063
			if (zoneid != GLOBAL_ZONEID &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16064
			    zoneid != connp->conn_zoneid)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16065
				continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16066
			tcp_report_item(mp->b_cont, tcp, i,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16067
			    Q_TO_TCP(q), cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16068
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16069
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16070
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16071
	tcp_last_ndd_get_info_time = ddi_get_lbolt();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16072
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16073
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16074
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16075
/* TCP status report triggered via the Named Dispatch mechanism. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16076
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16077
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16078
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
 16079
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16080
	tf_t	*tf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16081
	tcp_t	*tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16082
	int	i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16083
	zoneid_t zoneid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16084
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16085
	/* Refer to comments in tcp_status_report(). */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16086
	if (cr == NULL || secpolicy_net_config(cr, B_TRUE) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16087
		if (ddi_get_lbolt() - tcp_last_ndd_get_info_time <
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16088
		    drv_usectohz(tcp_ndd_get_info_interval * 1000)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16089
			(void) mi_mpprintf(mp, NDD_TOO_QUICK_MSG);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16090
			return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16091
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16092
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16093
	if ((mp->b_cont = allocb(ND_MAX_BUF_LEN, BPRI_HI)) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16094
		/* The following may work even if we cannot get a large buf. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16095
		(void) mi_mpprintf(mp, NDD_OUT_OF_BUF_MSG);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16096
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16097
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16098
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16099
	(void) mi_mpprintf(mp, "    %s", tcp_report_header);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16100
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16101
	zoneid = Q_TO_CONN(q)->conn_zoneid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16102
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16103
	for (i = 0; i < A_CNT(tcp_acceptor_fanout); i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16104
		tf = &tcp_acceptor_fanout[i];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16105
		mutex_enter(&tf->tf_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16106
		for (tcp = tf->tf_tcp; tcp != NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16107
		    tcp = tcp->tcp_acceptor_hash) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16108
			if (zoneid != GLOBAL_ZONEID &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16109
			    zoneid != tcp->tcp_connp->conn_zoneid)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16110
				continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16111
			tcp_report_item(mp->b_cont, tcp, i,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16112
			    Q_TO_TCP(q), cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16113
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16114
		mutex_exit(&tf->tf_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16115
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16116
	tcp_last_ndd_get_info_time = ddi_get_lbolt();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16117
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16118
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16119
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16120
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16121
 * tcp_timer is the timer service routine.  It handles the retransmission,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16122
 * FIN_WAIT_2 flush, and zero window probe timeout events.  It figures out
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16123
 * from the state of the tcp instance what kind of action needs to be done
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16124
 * at the time it is called.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16125
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16126
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16127
tcp_timer(void *arg)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16128
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16129
	mblk_t		*mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16130
	clock_t		first_threshold;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16131
	clock_t		second_threshold;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16132
	clock_t		ms;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16133
	uint32_t	mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16134
	conn_t		*connp = (conn_t *)arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16135
	tcp_t		*tcp = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16136
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16137
	tcp->tcp_timer_tid = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16138
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16139
	if (tcp->tcp_fused)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16140
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16141
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16142
	first_threshold =  tcp->tcp_first_timer_threshold;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16143
	second_threshold = tcp->tcp_second_timer_threshold;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16144
	switch (tcp->tcp_state) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16145
	case TCPS_IDLE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16146
	case TCPS_BOUND:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16147
	case TCPS_LISTEN:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16148
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16149
	case TCPS_SYN_RCVD: {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16150
		tcp_t	*listener = tcp->tcp_listener;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16151
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16152
		if (tcp->tcp_syn_rcvd_timeout == 0 && (listener != NULL)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16153
			ASSERT(tcp->tcp_rq == listener->tcp_rq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16154
			/* it's our first timeout */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16155
			tcp->tcp_syn_rcvd_timeout = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16156
			mutex_enter(&listener->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16157
			listener->tcp_syn_rcvd_timeout++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16158
			if (!listener->tcp_syn_defense &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16159
			    (listener->tcp_syn_rcvd_timeout >
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16160
			    (tcp_conn_req_max_q0 >> 2)) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16161
			    (tcp_conn_req_max_q0 > 200)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16162
				/* We may be under attack. Put on a defense. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16163
				listener->tcp_syn_defense = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16164
				cmn_err(CE_WARN, "High TCP connect timeout "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16165
				    "rate! System (port %d) may be under a "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16166
				    "SYN flood attack!",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16167
				    BE16_TO_U16(listener->tcp_tcph->th_lport));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16168
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16169
				listener->tcp_ip_addr_cache = kmem_zalloc(
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16170
				    IP_ADDR_CACHE_SIZE * sizeof (ipaddr_t),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16171
				    KM_NOSLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16172
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16173
			mutex_exit(&listener->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16174
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16175
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16176
		/* FALLTHRU */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16177
	case TCPS_SYN_SENT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16178
		first_threshold =  tcp->tcp_first_ctimer_threshold;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16179
		second_threshold = tcp->tcp_second_ctimer_threshold;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16180
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16181
	case TCPS_ESTABLISHED:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16182
	case TCPS_FIN_WAIT_1:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16183
	case TCPS_CLOSING:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16184
	case TCPS_CLOSE_WAIT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16185
	case TCPS_LAST_ACK:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16186
		/* If we have data to rexmit */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16187
		if (tcp->tcp_suna != tcp->tcp_snxt) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16188
			clock_t	time_to_wait;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16189
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16190
			BUMP_MIB(&tcp_mib, tcpTimRetrans);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16191
			if (!tcp->tcp_xmit_head)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16192
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16193
			time_to_wait = lbolt -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16194
			    (clock_t)tcp->tcp_xmit_head->b_prev;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16195
			time_to_wait = tcp->tcp_rto -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16196
			    TICK_TO_MSEC(time_to_wait);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16197
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16198
			 * If the timer fires too early, 1 clock tick earlier,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16199
			 * restart the timer.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16200
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16201
			if (time_to_wait > msec_per_tick) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16202
				TCP_STAT(tcp_timer_fire_early);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16203
				TCP_TIMER_RESTART(tcp, time_to_wait);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16204
				return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16205
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16206
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16207
			 * When we probe zero windows, we force the swnd open.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16208
			 * If our peer acks with a closed window swnd will be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16209
			 * set to zero by tcp_rput(). As long as we are
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16210
			 * receiving acks tcp_rput will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16211
			 * reset 'tcp_ms_we_have_waited' so as not to trip the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16212
			 * first and second interval actions.  NOTE: the timer
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16213
			 * interval is allowed to continue its exponential
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16214
			 * backoff.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16215
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16216
			if (tcp->tcp_swnd == 0 || tcp->tcp_zero_win_probe) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16217
				if (tcp->tcp_debug) {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 16218
					(void) strlog(TCP_MOD_ID, 0, 1,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16219
					    SL_TRACE, "tcp_timer: zero win");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16220
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16221
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16222
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16223
				 * After retransmission, we need to do
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16224
				 * slow start.  Set the ssthresh to one
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16225
				 * half of current effective window and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16226
				 * cwnd to one MSS.  Also reset
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16227
				 * tcp_cwnd_cnt.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16228
				 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16229
				 * Note that if tcp_ssthresh is reduced because
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16230
				 * of ECN, do not reduce it again unless it is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16231
				 * already one window of data away (tcp_cwr
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16232
				 * should then be cleared) or this is a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16233
				 * timeout for a retransmitted segment.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16234
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16235
				uint32_t npkt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16236
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16237
				if (!tcp->tcp_cwr || tcp->tcp_rexmit) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16238
					npkt = ((tcp->tcp_timer_backoff ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16239
					    tcp->tcp_cwnd_ssthresh :
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16240
					    tcp->tcp_snxt -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16241
					    tcp->tcp_suna) >> 1) / tcp->tcp_mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16242
					tcp->tcp_cwnd_ssthresh = MAX(npkt, 2) *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16243
					    tcp->tcp_mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16244
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16245
				tcp->tcp_cwnd = tcp->tcp_mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16246
				tcp->tcp_cwnd_cnt = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16247
				if (tcp->tcp_ecn_ok) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16248
					tcp->tcp_cwr = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16249
					tcp->tcp_cwr_snd_max = tcp->tcp_snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16250
					tcp->tcp_ecn_cwr_sent = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16251
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16252
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16253
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16254
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16255
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16256
		 * We have something to send yet we cannot send.  The
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16257
		 * reason can be:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16258
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16259
		 * 1. Zero send window: we need to do zero window probe.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16260
		 * 2. Zero cwnd: because of ECN, we need to "clock out
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16261
		 * segments.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16262
		 * 3. SWS avoidance: receiver may have shrunk window,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16263
		 * reset our knowledge.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16264
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16265
		 * Note that condition 2 can happen with either 1 or
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16266
		 * 3.  But 1 and 3 are exclusive.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16267
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16268
		if (tcp->tcp_unsent != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16269
			if (tcp->tcp_cwnd == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16270
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16271
				 * Set tcp_cwnd to 1 MSS so that a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16272
				 * new segment can be sent out.  We
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16273
				 * are "clocking out" new data when
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16274
				 * the network is really congested.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16275
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16276
				ASSERT(tcp->tcp_ecn_ok);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16277
				tcp->tcp_cwnd = tcp->tcp_mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16278
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16279
			if (tcp->tcp_swnd == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16280
				/* Extend window for zero window probe */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16281
				tcp->tcp_swnd++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16282
				tcp->tcp_zero_win_probe = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16283
				BUMP_MIB(&tcp_mib, tcpOutWinProbe);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16284
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16285
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16286
				 * Handle timeout from sender SWS avoidance.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16287
				 * Reset our knowledge of the max send window
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16288
				 * since the receiver might have reduced its
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16289
				 * receive buffer.  Avoid setting tcp_max_swnd
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16290
				 * to one since that will essentially disable
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16291
				 * the SWS checks.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16292
				 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16293
				 * Note that since we don't have a SWS
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16294
				 * state variable, if the timeout is set
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16295
				 * for ECN but not for SWS, this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16296
				 * code will also be executed.  This is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16297
				 * fine as tcp_max_swnd is updated
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16298
				 * constantly and it will not affect
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16299
				 * anything.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16300
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16301
				tcp->tcp_max_swnd = MAX(tcp->tcp_swnd, 2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16302
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16303
			tcp_wput_data(tcp, NULL, B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16304
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16305
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16306
		/* Is there a FIN that needs to be to re retransmitted? */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16307
		if ((tcp->tcp_valid_bits & TCP_FSS_VALID) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16308
		    !tcp->tcp_fin_acked)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16309
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16310
		/* Nothing to do, return without restarting timer. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16311
		TCP_STAT(tcp_timer_fire_miss);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16312
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16313
	case TCPS_FIN_WAIT_2:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16314
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16315
		 * User closed the TCP endpoint and peer ACK'ed our FIN.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16316
		 * We waited some time for for peer's FIN, but it hasn't
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16317
		 * arrived.  We flush the connection now to avoid
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16318
		 * case where the peer has rebooted.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16319
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16320
		if (TCP_IS_DETACHED(tcp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16321
			(void) tcp_clean_death(tcp, 0, 23);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16322
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16323
			TCP_TIMER_RESTART(tcp, tcp_fin_wait_2_flush_interval);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16324
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16325
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16326
	case TCPS_TIME_WAIT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16327
		(void) tcp_clean_death(tcp, 0, 24);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16328
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16329
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16330
		if (tcp->tcp_debug) {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 16331
			(void) strlog(TCP_MOD_ID, 0, 1, SL_TRACE|SL_ERROR,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16332
			    "tcp_timer: strange state (%d) %s",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16333
			    tcp->tcp_state, tcp_display(tcp, NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16334
			    DISP_PORT_ONLY));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16335
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16336
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16337
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16338
	if ((ms = tcp->tcp_ms_we_have_waited) > second_threshold) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16339
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16340
		 * For zero window probe, we need to send indefinitely,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16341
		 * unless we have not heard from the other side for some
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16342
		 * time...
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16343
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16344
		if ((tcp->tcp_zero_win_probe == 0) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16345
		    (TICK_TO_MSEC(lbolt - tcp->tcp_last_recv_time) >
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16346
		    second_threshold)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16347
			BUMP_MIB(&tcp_mib, tcpTimRetransDrop);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16348
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16349
			 * If TCP is in SYN_RCVD state, send back a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16350
			 * RST|ACK as BSD does.  Note that tcp_zero_win_probe
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16351
			 * should be zero in TCPS_SYN_RCVD state.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16352
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16353
			if (tcp->tcp_state == TCPS_SYN_RCVD) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16354
				tcp_xmit_ctl("tcp_timer: RST sent on timeout "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16355
				    "in SYN_RCVD",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16356
				    tcp, tcp->tcp_snxt,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16357
				    tcp->tcp_rnxt, TH_RST | TH_ACK);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16358
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16359
			(void) tcp_clean_death(tcp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16360
			    tcp->tcp_client_errno ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16361
			    tcp->tcp_client_errno : ETIMEDOUT, 25);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16362
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16363
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16364
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16365
			 * Set tcp_ms_we_have_waited to second_threshold
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16366
			 * so that in next timeout, we will do the above
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16367
			 * check (lbolt - tcp_last_recv_time).  This is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16368
			 * also to avoid overflow.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16369
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16370
			 * We don't need to decrement tcp_timer_backoff
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16371
			 * to avoid overflow because it will be decremented
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16372
			 * later if new timeout value is greater than
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16373
			 * tcp_rexmit_interval_max.  In the case when
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16374
			 * tcp_rexmit_interval_max is greater than
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16375
			 * second_threshold, it means that we will wait
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16376
			 * longer than second_threshold to send the next
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16377
			 * window probe.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16378
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16379
			tcp->tcp_ms_we_have_waited = second_threshold;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16380
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16381
	} else if (ms > first_threshold) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16382
		if (tcp->tcp_snd_zcopy_aware && (!tcp->tcp_xmit_zc_clean) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16383
		    tcp->tcp_xmit_head != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16384
			tcp->tcp_xmit_head =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16385
			    tcp_zcopy_backoff(tcp, tcp->tcp_xmit_head, 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16386
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16387
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16388
		 * We have been retransmitting for too long...  The RTT
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16389
		 * we calculated is probably incorrect.  Reinitialize it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16390
		 * Need to compensate for 0 tcp_rtt_sa.  Reset
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16391
		 * tcp_rtt_update so that we won't accidentally cache a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16392
		 * bad value.  But only do this if this is not a zero
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16393
		 * window probe.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16394
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16395
		if (tcp->tcp_rtt_sa != 0 && tcp->tcp_zero_win_probe == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16396
			tcp->tcp_rtt_sd += (tcp->tcp_rtt_sa >> 3) +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16397
			    (tcp->tcp_rtt_sa >> 5);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16398
			tcp->tcp_rtt_sa = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16399
			tcp_ip_notify(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16400
			tcp->tcp_rtt_update = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16401
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16402
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16403
	tcp->tcp_timer_backoff++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16404
	if ((ms = (tcp->tcp_rtt_sa >> 3) + tcp->tcp_rtt_sd +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16405
	    tcp_rexmit_interval_extra + (tcp->tcp_rtt_sa >> 5)) <
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16406
	    tcp_rexmit_interval_min) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16407
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16408
		 * This means the original RTO is tcp_rexmit_interval_min.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16409
		 * So we will use tcp_rexmit_interval_min as the RTO value
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16410
		 * and do the backoff.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16411
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16412
		ms = tcp_rexmit_interval_min << tcp->tcp_timer_backoff;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16413
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16414
		ms <<= tcp->tcp_timer_backoff;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16415
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16416
	if (ms > tcp_rexmit_interval_max) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16417
		ms = tcp_rexmit_interval_max;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16418
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16419
		 * ms is at max, decrement tcp_timer_backoff to avoid
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16420
		 * overflow.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16421
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16422
		tcp->tcp_timer_backoff--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16423
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16424
	tcp->tcp_ms_we_have_waited += ms;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16425
	if (tcp->tcp_zero_win_probe == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16426
		tcp->tcp_rto = ms;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16427
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16428
	TCP_TIMER_RESTART(tcp, ms);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16429
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16430
	 * This is after a timeout and tcp_rto is backed off.  Set
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16431
	 * tcp_set_timer to 1 so that next time RTO is updated, we will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16432
	 * restart the timer with a correct value.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16433
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16434
	tcp->tcp_set_timer = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16435
	mss = tcp->tcp_snxt - tcp->tcp_suna;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16436
	if (mss > tcp->tcp_mss)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16437
		mss = tcp->tcp_mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16438
	if (mss > tcp->tcp_swnd && tcp->tcp_swnd != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16439
		mss = tcp->tcp_swnd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16440
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16441
	if ((mp = tcp->tcp_xmit_head) != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16442
		mp->b_prev = (mblk_t *)lbolt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16443
	mp = tcp_xmit_mp(tcp, mp, mss, NULL, NULL, tcp->tcp_suna, B_TRUE, &mss,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16444
	    B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16445
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16446
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16447
	 * When slow start after retransmission begins, start with
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16448
	 * this seq no.  tcp_rexmit_max marks the end of special slow
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16449
	 * start phase.  tcp_snd_burst controls how many segments
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16450
	 * can be sent because of an ack.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16451
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16452
	tcp->tcp_rexmit_nxt = tcp->tcp_suna;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16453
	tcp->tcp_snd_burst = TCP_CWND_SS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16454
	if ((tcp->tcp_valid_bits & TCP_FSS_VALID) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16455
	    (tcp->tcp_unsent == 0)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16456
		tcp->tcp_rexmit_max = tcp->tcp_fss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16457
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16458
		tcp->tcp_rexmit_max = tcp->tcp_snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16459
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16460
	tcp->tcp_rexmit = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16461
	tcp->tcp_dupack_cnt = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16462
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16463
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16464
	 * Remove all rexmit SACK blk to start from fresh.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16465
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16466
	if (tcp->tcp_snd_sack_ok && tcp->tcp_notsack_list != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16467
		TCP_NOTSACK_REMOVE_ALL(tcp->tcp_notsack_list);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16468
		tcp->tcp_num_notsack_blk = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16469
		tcp->tcp_cnt_notsack_list = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16470
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16471
	if (mp == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16472
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16473
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16474
	/* Attach credentials to retransmitted initial SYNs. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16475
	if (tcp->tcp_state == TCPS_SYN_SENT) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16476
		mblk_setcred(mp, tcp->tcp_cred);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16477
		DB_CPID(mp) = tcp->tcp_cpid;
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
	tcp->tcp_csuna = tcp->tcp_snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16481
	BUMP_MIB(&tcp_mib, tcpRetransSegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16482
	UPDATE_MIB(&tcp_mib, tcpRetransBytes, mss);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16483
	TCP_RECORD_TRACE(tcp, mp, TCP_TRACE_SEND_PKT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16484
	tcp_send_data(tcp, tcp->tcp_wq, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16485
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16486
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16487
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16488
/* tcp_unbind is called by tcp_wput_proto to handle T_UNBIND_REQ messages. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16489
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16490
tcp_unbind(tcp_t *tcp, mblk_t *mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16491
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16492
	conn_t	*connp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16493
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16494
	switch (tcp->tcp_state) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16495
	case TCPS_BOUND:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16496
	case TCPS_LISTEN:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16497
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16498
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16499
		tcp_err_ack(tcp, mp, TOUTSTATE, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16500
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16501
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16502
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16503
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16504
	 * Need to clean up all the eagers since after the unbind, segments
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16505
	 * will no longer be delivered to this listener stream.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16506
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16507
	mutex_enter(&tcp->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16508
	if (tcp->tcp_conn_req_cnt_q0 != 0 || tcp->tcp_conn_req_cnt_q != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16509
		tcp_eager_cleanup(tcp, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16510
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16511
	mutex_exit(&tcp->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16512
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16513
	if (tcp->tcp_ipversion == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16514
		tcp->tcp_ipha->ipha_src = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16515
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16516
		V6_SET_ZERO(tcp->tcp_ip6h->ip6_src);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16517
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16518
	V6_SET_ZERO(tcp->tcp_ip_src_v6);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16519
	bzero(tcp->tcp_tcph->th_lport, sizeof (tcp->tcp_tcph->th_lport));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16520
	tcp_bind_hash_remove(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16521
	tcp->tcp_state = TCPS_IDLE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16522
	tcp->tcp_mdt = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16523
	/* Send M_FLUSH according to TPI */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16524
	(void) putnextctl1(tcp->tcp_rq, M_FLUSH, FLUSHRW);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16525
	connp = tcp->tcp_connp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16526
	connp->conn_mdt_ok = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16527
	ipcl_hash_remove(connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16528
	bzero(&connp->conn_ports, sizeof (connp->conn_ports));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16529
	mp = mi_tpi_ok_ack_alloc(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16530
	putnext(tcp->tcp_rq, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16531
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16532
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16533
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16534
 * Don't let port fall into the privileged range.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16535
 * Since the extra privileged ports can be arbitrary we also
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16536
 * ensure that we exclude those from consideration.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16537
 * tcp_g_epriv_ports is not sorted thus we loop over it until
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16538
 * there are no changes.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16539
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16540
 * Note: No locks are held when inspecting tcp_g_*epriv_ports
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16541
 * but instead the code relies on:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16542
 * - the fact that the address of the array and its size never changes
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16543
 * - the atomic assignment of the elements of the array
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16544
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16545
static in_port_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16546
tcp_update_next_port(in_port_t port, boolean_t random)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16547
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16548
	int i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16549
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16550
	if (random && tcp_random_anon_port != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16551
		(void) random_get_pseudo_bytes((uint8_t *)&port,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16552
		    sizeof (in_port_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16553
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16554
		 * Unless changed by a sys admin, the smallest anon port
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16555
		 * is 32768 and the largest anon port is 65535.  It is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16556
		 * very likely (50%) for the random port to be smaller
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16557
		 * than the smallest anon port.  When that happens,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16558
		 * add port % (anon port range) to the smallest anon
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16559
		 * port to get the random port.  It should fall into the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16560
		 * valid anon port range.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16561
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16562
		if (port < tcp_smallest_anon_port) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16563
			port = tcp_smallest_anon_port +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16564
			    port % (tcp_largest_anon_port -
646
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
 16565
				tcp_smallest_anon_port);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16566
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16567
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16568
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16569
retry:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16570
	if (port < tcp_smallest_anon_port || port > tcp_largest_anon_port)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16571
		port = (in_port_t)tcp_smallest_anon_port;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16572
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16573
	if (port < tcp_smallest_nonpriv_port)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16574
		port = (in_port_t)tcp_smallest_nonpriv_port;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16575
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16576
	for (i = 0; i < tcp_g_num_epriv_ports; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16577
		if (port == tcp_g_epriv_ports[i]) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16578
			port++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16579
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16580
			 * Make sure whether the port is in the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16581
			 * valid range.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16582
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16583
			 * XXX Note that if tcp_g_epriv_ports contains
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16584
			 * all the anonymous ports this will be an
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16585
			 * infinite loop.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16586
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16587
			goto retry;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16588
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16589
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16590
	return (port);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16591
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16592
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16593
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16594
 * Return the next anonymous port in the priviledged port range for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16595
 * bind checking.  It starts at IPPORT_RESERVED - 1 and goes
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16596
 * downwards.  This is the same behavior as documented in the userland
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16597
 * library call rresvport(3N).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16598
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16599
static in_port_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16600
tcp_get_next_priv_port(void)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16601
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16602
	static in_port_t next_priv_port = IPPORT_RESERVED - 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16603
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16604
	if (next_priv_port < tcp_min_anonpriv_port) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16605
		next_priv_port = IPPORT_RESERVED - 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16606
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16607
	return (next_priv_port--);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16608
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16609
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16610
/* The write side r/w procedure. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16611
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16612
#if CCS_STATS
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16613
struct {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16614
	struct {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16615
		int64_t count, bytes;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16616
	} tot, hit;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16617
} wrw_stats;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16618
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16619
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16620
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16621
 * Call by tcp_wput() to handle all non data, except M_PROTO and M_PCPROTO,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16622
 * messages.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16623
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16624
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16625
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16626
tcp_wput_nondata(void *arg, mblk_t *mp, void *arg2)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16627
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16628
	conn_t	*connp = (conn_t *)arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16629
	tcp_t	*tcp = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16630
	queue_t	*q = tcp->tcp_wq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16631
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16632
	ASSERT(DB_TYPE(mp) != M_IOCTL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16633
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16634
	 * TCP is D_MP and qprocsoff() is done towards the end of the tcp_close.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16635
	 * Once the close starts, streamhead and sockfs will not let any data
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16636
	 * packets come down (close ensures that there are no threads using the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16637
	 * queue and no new threads will come down) but since qprocsoff()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16638
	 * hasn't happened yet, a M_FLUSH or some non data message might
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16639
	 * get reflected back (in response to our own FLUSHRW) and get
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16640
	 * processed after tcp_close() is done. The conn would still be valid
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16641
	 * because a ref would have added but we need to check the state
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16642
	 * before actually processing the packet.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16643
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16644
	if (TCP_IS_DETACHED(tcp) || (tcp->tcp_state == TCPS_CLOSED)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16645
		freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16646
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16647
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16648
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16649
	switch (DB_TYPE(mp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16650
	case M_IOCDATA:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16651
		tcp_wput_iocdata(tcp, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16652
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16653
	case M_FLUSH:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16654
		tcp_wput_flush(tcp, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16655
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16656
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16657
		CALL_IP_WPUT(connp, q, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16658
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16659
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16660
}
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
 * The TCP fast path write put procedure.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16664
 * NOTE: the logic of the fast path is duplicated from tcp_wput_data()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16665
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16666
/* ARGSUSED */
898
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 16667
void
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16668
tcp_output(void *arg, mblk_t *mp, void *arg2)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16669
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16670
	int		len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16671
	int		hdrlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16672
	int		plen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16673
	mblk_t		*mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16674
	uchar_t		*rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16675
	uint32_t	snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16676
	tcph_t		*tcph;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16677
	struct datab	*db;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16678
	uint32_t	suna;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16679
	uint32_t	mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16680
	ipaddr_t	*dst;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16681
	ipaddr_t	*src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16682
	uint32_t	sum;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16683
	int		usable;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16684
	conn_t		*connp = (conn_t *)arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16685
	tcp_t		*tcp = connp->conn_tcp;
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 16686
	uint32_t	msize;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16687
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16688
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16689
	 * Try and ASSERT the minimum possible references on the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16690
	 * conn early enough. Since we are executing on write side,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16691
	 * the connection is obviously not detached and that means
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16692
	 * there is a ref each for TCP and IP. Since we are behind
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16693
	 * the squeue, the minimum references needed are 3. If the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16694
	 * conn is in classifier hash list, there should be an
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16695
	 * extra ref for that (we check both the possibilities).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16696
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16697
	ASSERT((connp->conn_fanout != NULL && connp->conn_ref >= 4) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16698
	    (connp->conn_fanout == NULL && connp->conn_ref >= 3));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16699
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16700
	/* Bypass tcp protocol for fused tcp loopback */
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 16701
	if (tcp->tcp_fused) {
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 16702
		msize = msgdsize(mp);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 16703
		mutex_enter(&connp->conn_lock);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 16704
		tcp->tcp_squeue_bytes -= msize;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 16705
		mutex_exit(&connp->conn_lock);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 16706
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 16707
		if (tcp_fuse_output(tcp, mp, msize))
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 16708
			return;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 16709
	}
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16710
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16711
	mss = tcp->tcp_mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16712
	if (tcp->tcp_xmit_zc_clean)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16713
		mp = tcp_zcopy_backoff(tcp, mp, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16714
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16715
	ASSERT((uintptr_t)(mp->b_wptr - mp->b_rptr) <= (uintptr_t)INT_MAX);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16716
	len = (int)(mp->b_wptr - mp->b_rptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16717
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16718
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16719
	 * Criteria for fast path:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16720
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16721
	 *   1. no unsent data
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16722
	 *   2. single mblk in request
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16723
	 *   3. connection established
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16724
	 *   4. data in mblk
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16725
	 *   5. len <= mss
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16726
	 *   6. no tcp_valid bits
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16727
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16728
	if ((tcp->tcp_unsent != 0) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16729
	    (tcp->tcp_cork) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16730
	    (mp->b_cont != NULL) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16731
	    (tcp->tcp_state != TCPS_ESTABLISHED) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16732
	    (len == 0) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16733
	    (len > mss) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16734
	    (tcp->tcp_valid_bits != 0)) {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 16735
		msize = msgdsize(mp);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 16736
		mutex_enter(&connp->conn_lock);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 16737
		tcp->tcp_squeue_bytes -= msize;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 16738
		mutex_exit(&connp->conn_lock);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 16739
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16740
		tcp_wput_data(tcp, mp, B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16741
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16742
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16743
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16744
	ASSERT(tcp->tcp_xmit_tail_unsent == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16745
	ASSERT(tcp->tcp_fin_sent == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16746
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 16747
	mutex_enter(&connp->conn_lock);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 16748
	tcp->tcp_squeue_bytes -= len;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 16749
	mutex_exit(&connp->conn_lock);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 16750
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16751
	/* queue new packet onto retransmission queue */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16752
	if (tcp->tcp_xmit_head == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16753
		tcp->tcp_xmit_head = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16754
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16755
		tcp->tcp_xmit_last->b_cont = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16756
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16757
	tcp->tcp_xmit_last = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16758
	tcp->tcp_xmit_tail = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16759
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16760
	/* find out how much we can send */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16761
	/* BEGIN CSTYLED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16762
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16763
	 *    un-acked           usable
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16764
	 *  |--------------|-----------------|
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16765
	 *  tcp_suna       tcp_snxt          tcp_suna+tcp_swnd
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16766
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16767
	/* END CSTYLED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16768
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16769
	/* start sending from tcp_snxt */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16770
	snxt = tcp->tcp_snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16771
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16772
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16773
	 * Check to see if this connection has been idled for some
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16774
	 * time and no ACK is expected.  If it is, we need to slow
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16775
	 * start again to get back the connection's "self-clock" as
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16776
	 * described in VJ's paper.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16777
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16778
	 * Refer to the comment in tcp_mss_set() for the calculation
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16779
	 * of tcp_cwnd after idle.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16780
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16781
	if ((tcp->tcp_suna == snxt) && !tcp->tcp_localnet &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16782
	    (TICK_TO_MSEC(lbolt - tcp->tcp_last_recv_time) >= tcp->tcp_rto)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16783
		SET_TCP_INIT_CWND(tcp, mss, tcp_slow_start_after_idle);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16784
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16785
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16786
	usable = tcp->tcp_swnd;		/* tcp window size */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16787
	if (usable > tcp->tcp_cwnd)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16788
		usable = tcp->tcp_cwnd;	/* congestion window smaller */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16789
	usable -= snxt;		/* subtract stuff already sent */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16790
	suna = tcp->tcp_suna;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16791
	usable += suna;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16792
	/* usable can be < 0 if the congestion window is smaller */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16793
	if (len > usable) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16794
		/* Can't send complete M_DATA in one shot */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16795
		goto slow;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16796
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16797
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 16798
	if (tcp->tcp_flow_stopped &&
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 16799
	    TCP_UNSENT_BYTES(tcp) <= tcp->tcp_xmit_lowater) {
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 16800
		tcp_clrqfull(tcp);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 16801
	}
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 16802
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16803
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16804
	 * determine if anything to send (Nagle).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16805
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16806
	 *   1. len < tcp_mss (i.e. small)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16807
	 *   2. unacknowledged data present
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16808
	 *   3. len < nagle limit
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16809
	 *   4. last packet sent < nagle limit (previous packet sent)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16810
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16811
	if ((len < mss) && (snxt != suna) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16812
	    (len < (int)tcp->tcp_naglim) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16813
	    (tcp->tcp_last_sent_len < tcp->tcp_naglim)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16814
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16815
		 * This was the first unsent packet and normally
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16816
		 * mss < xmit_hiwater so there is no need to worry
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16817
		 * about flow control. The next packet will go
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16818
		 * through the flow control check in tcp_wput_data().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16819
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16820
		/* leftover work from above */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16821
		tcp->tcp_unsent = len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16822
		tcp->tcp_xmit_tail_unsent = len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16823
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16824
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16825
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16826
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16827
	/* len <= tcp->tcp_mss && len == unsent so no silly window */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16828
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16829
	if (snxt == suna) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16830
		TCP_TIMER_RESTART(tcp, tcp->tcp_rto);
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
	/* we have always sent something */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16834
	tcp->tcp_rack_cnt = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16835
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16836
	tcp->tcp_snxt = snxt + len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16837
	tcp->tcp_rack = tcp->tcp_rnxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16838
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16839
	if ((mp1 = dupb(mp)) == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16840
		goto no_memory;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16841
	mp->b_prev = (mblk_t *)(uintptr_t)lbolt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16842
	mp->b_next = (mblk_t *)(uintptr_t)snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16843
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16844
	/* adjust tcp header information */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16845
	tcph = tcp->tcp_tcph;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16846
	tcph->th_flags[0] = (TH_ACK|TH_PUSH);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16847
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16848
	sum = len + tcp->tcp_tcp_hdr_len + tcp->tcp_sum;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16849
	sum = (sum >> 16) + (sum & 0xFFFF);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16850
	U16_TO_ABE16(sum, tcph->th_sum);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16851
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16852
	U32_TO_ABE32(snxt, tcph->th_seq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16853
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16854
	BUMP_MIB(&tcp_mib, tcpOutDataSegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16855
	UPDATE_MIB(&tcp_mib, tcpOutDataBytes, len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16856
	BUMP_LOCAL(tcp->tcp_obsegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16857
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16858
	/* Update the latest receive window size in TCP header. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16859
	U32_TO_ABE16(tcp->tcp_rwnd >> tcp->tcp_rcv_ws,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16860
	    tcph->th_win);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16861
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16862
	tcp->tcp_last_sent_len = (ushort_t)len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16863
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16864
	plen = len + tcp->tcp_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16865
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16866
	if (tcp->tcp_ipversion == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16867
		tcp->tcp_ipha->ipha_length = htons(plen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16868
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16869
		tcp->tcp_ip6h->ip6_plen = htons(plen -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16870
		    ((char *)&tcp->tcp_ip6h[1] - tcp->tcp_iphc));
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
	/* see if we need to allocate a mblk for the headers */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16874
	hdrlen = tcp->tcp_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16875
	rptr = mp1->b_rptr - hdrlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16876
	db = mp1->b_datap;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16877
	if ((db->db_ref != 2) || rptr < db->db_base ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16878
	    (!OK_32PTR(rptr))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16879
		/* NOTE: we assume allocb returns an OK_32PTR */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16880
		mp = allocb(tcp->tcp_ip_hdr_len + TCP_MAX_HDR_LENGTH +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16881
		    tcp_wroff_xtra, BPRI_MED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16882
		if (!mp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16883
			freemsg(mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16884
			goto no_memory;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16885
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16886
		mp->b_cont = mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16887
		mp1 = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16888
		/* Leave room for Link Level header */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16889
		/* hdrlen = tcp->tcp_hdr_len; */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16890
		rptr = &mp1->b_rptr[tcp_wroff_xtra];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16891
		mp1->b_wptr = &rptr[hdrlen];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16892
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16893
	mp1->b_rptr = rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16894
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16895
	/* Fill in the timestamp option. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16896
	if (tcp->tcp_snd_ts_ok) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16897
		U32_TO_BE32((uint32_t)lbolt,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16898
		    (char *)tcph+TCP_MIN_HEADER_LENGTH+4);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16899
		U32_TO_BE32(tcp->tcp_ts_recent,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16900
		    (char *)tcph+TCP_MIN_HEADER_LENGTH+8);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16901
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16902
		ASSERT(tcp->tcp_tcp_hdr_len == TCP_MIN_HEADER_LENGTH);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16903
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16904
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16905
	/* copy header into outgoing packet */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16906
	dst = (ipaddr_t *)rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16907
	src = (ipaddr_t *)tcp->tcp_iphc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16908
	dst[0] = src[0];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16909
	dst[1] = src[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16910
	dst[2] = src[2];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16911
	dst[3] = src[3];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16912
	dst[4] = src[4];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16913
	dst[5] = src[5];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16914
	dst[6] = src[6];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16915
	dst[7] = src[7];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16916
	dst[8] = src[8];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16917
	dst[9] = src[9];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16918
	if (hdrlen -= 40) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16919
		hdrlen >>= 2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16920
		dst += 10;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16921
		src += 10;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16922
		do {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16923
			*dst++ = *src++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16924
		} while (--hdrlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16925
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16926
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16927
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16928
	 * Set the ECN info in the TCP header.  Note that this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16929
	 * is not the template header.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16930
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16931
	if (tcp->tcp_ecn_ok) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16932
		SET_ECT(tcp, rptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16933
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16934
		tcph = (tcph_t *)(rptr + tcp->tcp_ip_hdr_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16935
		if (tcp->tcp_ecn_echo_on)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16936
			tcph->th_flags[0] |= TH_ECE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16937
		if (tcp->tcp_cwr && !tcp->tcp_ecn_cwr_sent) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16938
			tcph->th_flags[0] |= TH_CWR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16939
			tcp->tcp_ecn_cwr_sent = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16940
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16941
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16942
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16943
	if (tcp->tcp_ip_forward_progress) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16944
		ASSERT(tcp->tcp_ipversion == IPV6_VERSION);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16945
		*(uint32_t *)mp1->b_rptr  |= IP_FORWARD_PROG;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16946
		tcp->tcp_ip_forward_progress = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16947
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16948
	TCP_RECORD_TRACE(tcp, mp1, TCP_TRACE_SEND_PKT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16949
	tcp_send_data(tcp, tcp->tcp_wq, mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16950
	return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16951
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16952
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16953
	 * If we ran out of memory, we pretend to have sent the packet
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16954
	 * and that it was lost on the wire.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16955
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16956
no_memory:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16957
	return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16958
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16959
slow:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16960
	/* leftover work from above */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16961
	tcp->tcp_unsent = len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16962
	tcp->tcp_xmit_tail_unsent = len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16963
	tcp_wput_data(tcp, NULL, B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16964
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16965
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16966
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16967
 * The function called through squeue to get behind eager's perimeter to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16968
 * finish the accept processing.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16969
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16970
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16971
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16972
tcp_accept_finish(void *arg, mblk_t *mp, void *arg2)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16973
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16974
	conn_t			*connp = (conn_t *)arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16975
	tcp_t			*tcp = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16976
	queue_t			*q = tcp->tcp_rq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16977
	mblk_t			*mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16978
	mblk_t			*stropt_mp = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16979
	struct  stroptions	*stropt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16980
	uint_t			thwin;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16981
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16982
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16983
	 * Drop the eager's ref on the listener, that was placed when
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16984
	 * this eager began life in tcp_conn_request.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16985
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16986
	CONN_DEC_REF(tcp->tcp_saved_listener->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16987
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16988
	if (tcp->tcp_state <= TCPS_BOUND || tcp->tcp_accept_error) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16989
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16990
		 * Someone blewoff the eager before we could finish
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16991
		 * the accept.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16992
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16993
		 * The only reason eager exists it because we put in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16994
		 * a ref on it when conn ind went up. We need to send
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16995
		 * a disconnect indication up while the last reference
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16996
		 * on the eager will be dropped by the squeue when we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16997
		 * return.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16998
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16999
		ASSERT(tcp->tcp_listener == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17000
		if (tcp->tcp_issocket || tcp->tcp_send_discon_ind) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17001
			struct	T_discon_ind	*tdi;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17002
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17003
			(void) putnextctl1(q, M_FLUSH, FLUSHRW);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17004
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17005
			 * Let us reuse the incoming mblk to avoid memory
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17006
			 * allocation failure problems. We know that the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17007
			 * size of the incoming mblk i.e. stroptions is greater
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17008
			 * than sizeof T_discon_ind. So the reallocb below
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17009
			 * can't fail.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17010
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17011
			freemsg(mp->b_cont);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17012
			mp->b_cont = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17013
			ASSERT(DB_REF(mp) == 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17014
			mp = reallocb(mp, sizeof (struct T_discon_ind),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17015
			    B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17016
			ASSERT(mp != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17017
			DB_TYPE(mp) = M_PROTO;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17018
			((union T_primitives *)mp->b_rptr)->type = T_DISCON_IND;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17019
			tdi = (struct T_discon_ind *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17020
			if (tcp->tcp_issocket) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17021
				tdi->DISCON_reason = ECONNREFUSED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17022
				tdi->SEQ_number = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17023
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17024
				tdi->DISCON_reason = ENOPROTOOPT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17025
				tdi->SEQ_number =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17026
				    tcp->tcp_conn_req_seqnum;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17027
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17028
			mp->b_wptr = mp->b_rptr + sizeof (struct T_discon_ind);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17029
			putnext(q, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17030
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17031
			freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17032
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17033
		if (tcp->tcp_hard_binding) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17034
			tcp->tcp_hard_binding = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17035
			tcp->tcp_hard_bound = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17036
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17037
		tcp->tcp_detached = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17038
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17039
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17040
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17041
	mp1 = stropt_mp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17042
	stropt_mp->b_cont = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17043
	ASSERT(DB_TYPE(stropt_mp) == M_SETOPTS);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17044
	stropt = (struct stroptions *)stropt_mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17045
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17046
	while (mp1 != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17047
		mp = mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17048
		mp1 = mp1->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17049
		mp->b_cont = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17050
		tcp->tcp_drop_opt_ack_cnt++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17051
		CALL_IP_WPUT(connp, tcp->tcp_wq, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17052
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17053
	mp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17054
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17055
	/*
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17056
	 * For a loopback connection with tcp_direct_sockfs on, note that
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17057
	 * 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
 17058
	 * streams has not yet been enabled and tcp_fuse_rrw() cannot
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17059
	 * possibly race with us.
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17060
	 */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17061
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17062
	/*
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17063
	 * Set the max window size (tcp_rq->q_hiwat) of the acceptor
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17064
	 * properly.  This is the first time we know of the acceptor'
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17065
	 * queue.  So we do it here.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17066
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17067
	if (tcp->tcp_rcv_list == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17068
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17069
		 * Recv queue is empty, tcp_rwnd should not have changed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17070
		 * That means it should be equal to the listener's tcp_rwnd.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17071
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17072
		tcp->tcp_rq->q_hiwat = tcp->tcp_rwnd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17073
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17074
#ifdef DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17075
		uint_t cnt = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17076
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17077
		mp1 = tcp->tcp_rcv_list;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17078
		while ((mp = mp1) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17079
			mp1 = mp->b_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17080
			cnt += msgdsize(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17081
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17082
		ASSERT(cnt != 0 && tcp->tcp_rcv_cnt == cnt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17083
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17084
		/* There is some data, add them back to get the max. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17085
		tcp->tcp_rq->q_hiwat = tcp->tcp_rwnd + tcp->tcp_rcv_cnt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17086
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17087
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17088
	stropt->so_flags = SO_HIWAT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17089
	stropt->so_hiwat = MAX(q->q_hiwat, tcp_sth_rcv_hiwat);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17090
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17091
	stropt->so_flags |= SO_MAXBLK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17092
	stropt->so_maxblk = tcp_maxpsz_set(tcp, B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17093
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17094
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17095
	 * This is the first time we run on the correct
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17096
	 * queue after tcp_accept. So fix all the q parameters
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17097
	 * here.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17098
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17099
	/* Allocate room for SACK options if needed. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17100
	stropt->so_flags |= SO_WROFF;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17101
	if (tcp->tcp_fused) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17102
		ASSERT(tcp->tcp_loopback);
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17103
		ASSERT(tcp->tcp_loopback_peer != NULL);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17104
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17105
		 * For fused tcp loopback, set the stream head's write
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17106
		 * offset value to zero since we won't be needing any room
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17107
		 * for TCP/IP headers.  This would also improve performance
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17108
		 * since it would reduce the amount of work done by kmem.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17109
		 * Non-fused tcp loopback case is handled separately below.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17110
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17111
		stropt->so_wroff = 0;
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17112
		/*
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17113
		 * Record the stream head's high water mark for this endpoint;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17114
		 * this is used for flow-control purposes in tcp_fuse_output().
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17115
		 */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17116
		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
 17117
		/*
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17118
		 * Update the peer's transmit parameters according to
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17119
		 * our recently calculated high water mark value.
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17120
		 */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17121
		(void) tcp_maxpsz_set(tcp->tcp_loopback_peer, B_TRUE);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17122
	} else if (tcp->tcp_snd_sack_ok) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17123
		stropt->so_wroff = tcp->tcp_hdr_len + TCPOPT_MAX_SACK_LEN +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17124
		    (tcp->tcp_loopback ? 0 : tcp_wroff_xtra);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17125
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17126
		stropt->so_wroff = tcp->tcp_hdr_len + (tcp->tcp_loopback ? 0 :
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17127
		    tcp_wroff_xtra);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17128
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17129
898
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 17130
	/*
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 17131
	 * If this is endpoint is handling SSL, then reserve extra
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 17132
	 * offset and space at the end.
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 17133
	 * Also have the stream head allocate SSL3_MAX_RECORD_LEN packets,
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 17134
	 * overriding the previous setting. The extra cost of signing and
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 17135
	 * encrypting multiple MSS-size records (12 of them with Ethernet),
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 17136
	 * instead of a single contiguous one by the stream head
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 17137
	 * largely outweighs the statistical reduction of ACKs, when
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 17138
	 * applicable. The peer will also save on decyption and verification
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 17139
	 * costs.
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 17140
	 */
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 17141
	if (tcp->tcp_kssl_ctx != NULL) {
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 17142
		stropt->so_wroff += SSL3_WROFFSET;
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 17143
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 17144
		stropt->so_flags |= SO_TAIL;
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 17145
		stropt->so_tail = SSL3_MAX_TAIL_LEN;
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 17146
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 17147
		stropt->so_maxblk = SSL3_MAX_RECORD_LEN;
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 17148
	}
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 17149
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17150
	/* Send the options up */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17151
	putnext(q, stropt_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17152
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17153
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17154
	 * Pass up any data and/or a fin that has been received.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17155
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17156
	 * Adjust receive window in case it had decreased
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17157
	 * (because there is data <=> tcp_rcv_list != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17158
	 * while the connection was detached. Note that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17159
	 * in case the eager was flow-controlled, w/o this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17160
	 * code, the rwnd may never open up again!
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17161
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17162
	if (tcp->tcp_rcv_list != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17163
		/* We drain directly in case of fused tcp loopback */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17164
		if (!tcp->tcp_fused && canputnext(q)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17165
			tcp->tcp_rwnd = q->q_hiwat;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17166
			thwin = ((uint_t)BE16_TO_U16(tcp->tcp_tcph->th_win))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17167
			    << tcp->tcp_rcv_ws;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17168
			thwin -= tcp->tcp_rnxt - tcp->tcp_rack;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17169
			if (tcp->tcp_state >= TCPS_ESTABLISHED &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17170
			    (q->q_hiwat - thwin >= tcp->tcp_mss)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17171
				tcp_xmit_ctl(NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17172
				    tcp, (tcp->tcp_swnd == 0) ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17173
				    tcp->tcp_suna : tcp->tcp_snxt,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17174
				    tcp->tcp_rnxt, TH_ACK);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17175
				BUMP_MIB(&tcp_mib, tcpOutWinUpdate);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17176
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17177
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17178
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17179
		(void) tcp_rcv_drain(q, tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17180
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17181
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17182
		 * For fused tcp loopback, back-enable peer endpoint
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17183
		 * if it's currently flow-controlled.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17184
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17185
		if (tcp->tcp_fused &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17186
		    tcp->tcp_loopback_peer->tcp_flow_stopped) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17187
			tcp_t *peer_tcp = tcp->tcp_loopback_peer;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17188
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17189
			ASSERT(peer_tcp != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17190
			ASSERT(peer_tcp->tcp_fused);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17191
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17192
			tcp_clrqfull(peer_tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17193
			TCP_STAT(tcp_fusion_backenabled);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17194
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17195
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17196
	ASSERT(tcp->tcp_rcv_list == NULL || tcp->tcp_fused_sigurg);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17197
	if (tcp->tcp_fin_rcvd && !tcp->tcp_ordrel_done) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17198
		mp = mi_tpi_ordrel_ind();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17199
		if (mp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17200
			tcp->tcp_ordrel_done = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17201
			putnext(q, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17202
			if (tcp->tcp_deferred_clean_death) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17203
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17204
				 * tcp_clean_death was deferred
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17205
				 * for T_ORDREL_IND - do it now
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17206
				 */
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17207
				(void) tcp_clean_death(tcp,
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17208
				    tcp->tcp_client_errno, 21);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17209
				tcp->tcp_deferred_clean_death = B_FALSE;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17210
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17211
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17212
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17213
			 * Run the orderly release in the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17214
			 * service routine.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17215
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17216
			qenable(q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17217
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17218
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17219
	if (tcp->tcp_hard_binding) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17220
		tcp->tcp_hard_binding = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17221
		tcp->tcp_hard_bound = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17222
	}
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17223
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17224
	tcp->tcp_detached = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17225
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17226
	/* We can enable synchronous streams now */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17227
	if (tcp->tcp_fused) {
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17228
		tcp_fuse_syncstr_enable_pair(tcp);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17229
	}
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17230
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17231
	if (tcp->tcp_ka_enabled) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17232
		tcp->tcp_ka_last_intrvl = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17233
		tcp->tcp_ka_tid = TCP_TIMER(tcp, tcp_keepalive_killer,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17234
		    MSEC_TO_TICK(tcp->tcp_ka_interval));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17235
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17236
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17237
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17238
	 * At this point, eager is fully established and will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17239
	 * have the following references -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17240
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17241
	 * 2 references for connection to exist (1 for TCP and 1 for IP).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17242
	 * 1 reference for the squeue which will be dropped by the squeue as
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17243
	 *	soon as this function returns.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17244
	 * There will be 1 additonal reference for being in classifier
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17245
	 *	hash list provided something bad hasn't happened.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17246
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17247
	ASSERT((connp->conn_fanout != NULL && connp->conn_ref >= 4) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17248
	    (connp->conn_fanout == NULL && connp->conn_ref >= 3));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17249
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17250
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17251
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17252
 * The function called through squeue to get behind listener's perimeter to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17253
 * send a deffered conn_ind.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17254
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17255
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17256
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17257
tcp_send_pending(void *arg, mblk_t *mp, void *arg2)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17258
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17259
	conn_t	*connp = (conn_t *)arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17260
	tcp_t *listener = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17261
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17262
	if (listener->tcp_state == TCPS_CLOSED ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17263
	    TCP_IS_DETACHED(listener)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17264
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17265
		 * If listener has closed, it would have caused a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17266
		 * a cleanup/blowoff to happen for the eager.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17267
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17268
		tcp_t *tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17269
		struct T_conn_ind	*conn_ind;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17270
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17271
		conn_ind = (struct T_conn_ind *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17272
		bcopy(mp->b_rptr + conn_ind->OPT_offset, &tcp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17273
		    conn_ind->OPT_length);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17274
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17275
		 * We need to drop the ref on eager that was put
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17276
		 * tcp_rput_data() before trying to send the conn_ind
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17277
		 * to listener. The conn_ind was deferred in tcp_send_conn_ind
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17278
		 * and tcp_wput_accept() is sending this deferred conn_ind but
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17279
		 * listener is closed so we drop the ref.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17280
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17281
		CONN_DEC_REF(tcp->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17282
		freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17283
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17284
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17285
	putnext(listener->tcp_rq, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17286
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17287
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17288
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17289
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17290
 * This is the STREAMS entry point for T_CONN_RES coming down on
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17291
 * Acceptor STREAM when  sockfs listener does accept processing.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17292
 * Read the block comment on top pf tcp_conn_request().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17293
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17294
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17295
tcp_wput_accept(queue_t *q, mblk_t *mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17296
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17297
	queue_t *rq = RD(q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17298
	struct T_conn_res *conn_res;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17299
	tcp_t *eager;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17300
	tcp_t *listener;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17301
	struct T_ok_ack *ok;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17302
	t_scalar_t PRIM_type;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17303
	mblk_t *opt_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17304
	conn_t *econnp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17305
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17306
	ASSERT(DB_TYPE(mp) == M_PROTO);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17307
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17308
	conn_res = (struct T_conn_res *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17309
	ASSERT((uintptr_t)(mp->b_wptr - mp->b_rptr) <= (uintptr_t)INT_MAX);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17310
	if ((mp->b_wptr - mp->b_rptr) < sizeof (struct T_conn_res)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17311
		mp = mi_tpi_err_ack_alloc(mp, TPROTO, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17312
		if (mp != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17313
			putnext(rq, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17314
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17315
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17316
	switch (conn_res->PRIM_type) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17317
	case O_T_CONN_RES:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17318
	case T_CONN_RES:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17319
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17320
		 * We pass up an err ack if allocb fails. This will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17321
		 * cause sockfs to issue a T_DISCON_REQ which will cause
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17322
		 * tcp_eager_blowoff to be called. sockfs will then call
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17323
		 * rq->q_qinfo->qi_qclose to cleanup the acceptor stream.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17324
		 * we need to do the allocb up here because we have to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17325
		 * make sure rq->q_qinfo->qi_qclose still points to the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17326
		 * correct function (tcpclose_accept) in case allocb
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17327
		 * fails.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17328
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17329
		opt_mp = allocb(sizeof (struct stroptions), BPRI_HI);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17330
		if (opt_mp == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17331
			mp = mi_tpi_err_ack_alloc(mp, TPROTO, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17332
			if (mp != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17333
				putnext(rq, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17334
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17335
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17336
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17337
		bcopy(mp->b_rptr + conn_res->OPT_offset,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17338
		    &eager, conn_res->OPT_length);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17339
		PRIM_type = conn_res->PRIM_type;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17340
		mp->b_datap->db_type = M_PCPROTO;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17341
		mp->b_wptr = mp->b_rptr + sizeof (struct T_ok_ack);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17342
		ok = (struct T_ok_ack *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17343
		ok->PRIM_type = T_OK_ACK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17344
		ok->CORRECT_prim = PRIM_type;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17345
		econnp = eager->tcp_connp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17346
		econnp->conn_dev = (dev_t)q->q_ptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17347
		eager->tcp_rq = rq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17348
		eager->tcp_wq = q;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17349
		rq->q_ptr = econnp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17350
		rq->q_qinfo = &tcp_rinit;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17351
		q->q_ptr = econnp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17352
		q->q_qinfo = &tcp_winit;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17353
		listener = eager->tcp_listener;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17354
		eager->tcp_issocket = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17355
		eager->tcp_cred = econnp->conn_cred =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17356
		    listener->tcp_connp->conn_cred;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17357
		crhold(econnp->conn_cred);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17358
		econnp->conn_zoneid = listener->tcp_connp->conn_zoneid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17359
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17360
		/* Put the ref for IP */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17361
		CONN_INC_REF(econnp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17362
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17363
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17364
		 * We should have minimum of 3 references on the conn
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17365
		 * at this point. One each for TCP and IP and one for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17366
		 * the T_conn_ind that was sent up when the 3-way handshake
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17367
		 * completed. In the normal case we would also have another
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17368
		 * reference (making a total of 4) for the conn being in the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17369
		 * classifier hash list. However the eager could have received
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17370
		 * an RST subsequently and tcp_closei_local could have removed
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17371
		 * the eager from the classifier hash list, hence we can't
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17372
		 * assert that reference.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17373
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17374
		ASSERT(econnp->conn_ref >= 3);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17375
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17376
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17377
		 * Send the new local address also up to sockfs. There
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17378
		 * should already be enough space in the mp that came
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17379
		 * down from soaccept().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17380
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17381
		if (eager->tcp_family == AF_INET) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17382
			sin_t *sin;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17383
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17384
			ASSERT((mp->b_datap->db_lim - mp->b_datap->db_base) >=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17385
			    (sizeof (struct T_ok_ack) + sizeof (sin_t)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17386
			sin = (sin_t *)mp->b_wptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17387
			mp->b_wptr += sizeof (sin_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17388
			sin->sin_family = AF_INET;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17389
			sin->sin_port = eager->tcp_lport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17390
			sin->sin_addr.s_addr = eager->tcp_ipha->ipha_src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17391
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17392
			sin6_t *sin6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17393
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17394
			ASSERT((mp->b_datap->db_lim - mp->b_datap->db_base) >=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17395
			    sizeof (struct T_ok_ack) + sizeof (sin6_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17396
			sin6 = (sin6_t *)mp->b_wptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17397
			mp->b_wptr += sizeof (sin6_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17398
			sin6->sin6_family = AF_INET6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17399
			sin6->sin6_port = eager->tcp_lport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17400
			if (eager->tcp_ipversion == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17401
				sin6->sin6_flowinfo = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17402
				IN6_IPADDR_TO_V4MAPPED(
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17403
					eager->tcp_ipha->ipha_src,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17404
					    &sin6->sin6_addr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17405
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17406
				ASSERT(eager->tcp_ip6h != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17407
				sin6->sin6_flowinfo =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17408
				    eager->tcp_ip6h->ip6_vcf &
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17409
				    ~IPV6_VERS_AND_FLOW_MASK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17410
				sin6->sin6_addr = eager->tcp_ip6h->ip6_src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17411
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17412
			sin6->sin6_scope_id = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17413
			sin6->__sin6_src_id = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17414
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17415
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17416
		putnext(rq, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17417
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17418
		opt_mp->b_datap->db_type = M_SETOPTS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17419
		opt_mp->b_wptr += sizeof (struct stroptions);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17420
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17421
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17422
		 * Prepare for inheriting IPV6_BOUND_IF and IPV6_RECVPKTINFO
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17423
		 * from listener to acceptor. The message is chained on the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17424
		 * bind_mp which tcp_rput_other will send down to IP.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17425
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17426
		if (listener->tcp_bound_if != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17427
			/* allocate optmgmt req */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17428
			mp = tcp_setsockopt_mp(IPPROTO_IPV6,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17429
			    IPV6_BOUND_IF, (char *)&listener->tcp_bound_if,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17430
			    sizeof (int));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17431
			if (mp != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17432
				linkb(opt_mp, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17433
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17434
		if (listener->tcp_ipv6_recvancillary & TCP_IPV6_RECVPKTINFO) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17435
			uint_t on = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17436
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17437
			/* allocate optmgmt req */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17438
			mp = tcp_setsockopt_mp(IPPROTO_IPV6,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17439
			    IPV6_RECVPKTINFO, (char *)&on, sizeof (on));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17440
			if (mp != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17441
				linkb(opt_mp, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17442
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17443
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17444
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17445
		mutex_enter(&listener->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17446
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17447
		if (listener->tcp_eager_prev_q0->tcp_conn_def_q0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17448
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17449
			tcp_t *tail;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17450
			tcp_t *tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17451
			mblk_t *mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17452
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17453
			tcp = listener->tcp_eager_prev_q0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17454
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17455
			 * listener->tcp_eager_prev_q0 points to the TAIL of the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17456
			 * deferred T_conn_ind queue. We need to get to the head
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17457
			 * of the queue in order to send up T_conn_ind the same
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17458
			 * order as how the 3WHS is completed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17459
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17460
			while (tcp != listener) {
898
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 17461
				if (!tcp->tcp_eager_prev_q0->tcp_conn_def_q0 &&
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 17462
				    !tcp->tcp_kssl_pending)
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17463
					break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17464
				else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17465
					tcp = tcp->tcp_eager_prev_q0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17466
			}
898
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 17467
			/* None of the pending eagers can be sent up now */
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 17468
			if (tcp == listener)
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 17469
				goto no_more_eagers;
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 17470
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17471
			mp1 = tcp->tcp_conn.tcp_eager_conn_ind;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17472
			tcp->tcp_conn.tcp_eager_conn_ind = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17473
			/* Move from q0 to q */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17474
			ASSERT(listener->tcp_conn_req_cnt_q0 > 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17475
			listener->tcp_conn_req_cnt_q0--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17476
			listener->tcp_conn_req_cnt_q++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17477
			tcp->tcp_eager_next_q0->tcp_eager_prev_q0 =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17478
			    tcp->tcp_eager_prev_q0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17479
			tcp->tcp_eager_prev_q0->tcp_eager_next_q0 =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17480
			    tcp->tcp_eager_next_q0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17481
			tcp->tcp_eager_prev_q0 = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17482
			tcp->tcp_eager_next_q0 = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17483
			tcp->tcp_conn_def_q0 = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17484
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17485
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17486
			 * Insert at end of the queue because sockfs sends
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17487
			 * down T_CONN_RES in chronological order. Leaving
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17488
			 * the older conn indications at front of the queue
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17489
			 * helps reducing search time.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17490
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17491
			tail = listener->tcp_eager_last_q;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17492
			if (tail != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17493
				tail->tcp_eager_next_q = tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17494
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17495
				listener->tcp_eager_next_q = tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17496
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17497
			listener->tcp_eager_last_q = tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17498
			tcp->tcp_eager_next_q = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17499
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17500
			/* Need to get inside the listener perimeter */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17501
			CONN_INC_REF(listener->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17502
			squeue_fill(listener->tcp_connp->conn_sqp, mp1,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17503
			    tcp_send_pending, listener->tcp_connp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17504
			    SQTAG_TCP_SEND_PENDING);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17505
		}
898
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 17506
no_more_eagers:
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17507
		tcp_eager_unlink(eager);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17508
		mutex_exit(&listener->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17509
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17510
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17511
		 * At this point, the eager is detached from the listener
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17512
		 * but we still have an extra refs on eager (apart from the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17513
		 * usual tcp references). The ref was placed in tcp_rput_data
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17514
		 * before sending the conn_ind in tcp_send_conn_ind.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17515
		 * The ref will be dropped in tcp_accept_finish().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17516
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17517
		squeue_enter_nodrain(econnp->conn_sqp, opt_mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17518
		    tcp_accept_finish, econnp, SQTAG_TCP_ACCEPT_FINISH_Q0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17519
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17520
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17521
		mp = mi_tpi_err_ack_alloc(mp, TNOTSUPPORT, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17522
		if (mp != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17523
			putnext(rq, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17524
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17525
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17526
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17527
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17528
void
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17529
tcp_wput(queue_t *q, mblk_t *mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17530
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17531
	conn_t	*connp = Q_TO_CONN(q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17532
	tcp_t	*tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17533
	void (*output_proc)();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17534
	t_scalar_t type;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17535
	uchar_t *rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17536
	struct iocblk	*iocp;
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17537
	uint32_t	msize;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17538
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17539
	ASSERT(connp->conn_ref >= 2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17540
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17541
	switch (DB_TYPE(mp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17542
	case M_DATA:
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17543
		tcp = connp->conn_tcp;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17544
		ASSERT(tcp != NULL);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17545
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17546
		msize = msgdsize(mp);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17547
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17548
		mutex_enter(&connp->conn_lock);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17549
		CONN_INC_REF_LOCKED(connp);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17550
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17551
		tcp->tcp_squeue_bytes += msize;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17552
		if (TCP_UNSENT_BYTES(tcp) > tcp->tcp_xmit_hiwater) {
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17553
			mutex_exit(&connp->conn_lock);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17554
			tcp_setqfull(tcp);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17555
		} else
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17556
			mutex_exit(&connp->conn_lock);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17557
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17558
		(*tcp_squeue_wput_proc)(connp->conn_sqp, mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17559
		    tcp_output, connp, SQTAG_TCP_OUTPUT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17560
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17561
	case M_PROTO:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17562
	case M_PCPROTO:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17563
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17564
		 * if it is a snmp message, don't get behind the squeue
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17565
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17566
		tcp = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17567
		rptr = mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17568
		if ((mp->b_wptr - rptr) >= sizeof (t_scalar_t)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17569
			type = ((union T_primitives *)rptr)->type;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17570
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17571
			if (tcp->tcp_debug) {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17572
				(void) strlog(TCP_MOD_ID, 0, 1,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17573
				    SL_ERROR|SL_TRACE,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17574
				    "tcp_wput_proto, dropping one...");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17575
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17576
			freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17577
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17578
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17579
		if (type == T_SVR4_OPTMGMT_REQ) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17580
			cred_t	*cr = DB_CREDDEF(mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17581
			    tcp->tcp_cred);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17582
			if (snmpcom_req(q, mp, tcp_snmp_set, tcp_snmp_get,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17583
			    cr)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17584
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17585
				 * This was a SNMP request
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17586
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17587
				return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17588
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17589
				output_proc = tcp_wput_proto;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17590
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17591
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17592
			output_proc = tcp_wput_proto;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17593
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17594
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17595
	case M_IOCTL:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17596
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17597
		 * Most ioctls can be processed right away without going via
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17598
		 * squeues - process them right here. Those that do require
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17599
		 * squeue (currently TCP_IOC_DEFAULT_Q and _SIOCSOCKFALLBACK)
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17600
		 * are processed by tcp_wput_ioctl().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17601
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17602
		iocp = (struct iocblk *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17603
		tcp = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17604
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17605
		switch (iocp->ioc_cmd) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17606
		case TCP_IOC_ABORT_CONN:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17607
			tcp_ioctl_abort_conn(q, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17608
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17609
		case TI_GETPEERNAME:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17610
			if (tcp->tcp_state < TCPS_SYN_RCVD) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17611
				iocp->ioc_error = ENOTCONN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17612
				iocp->ioc_count = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17613
				mp->b_datap->db_type = M_IOCACK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17614
				qreply(q, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17615
				return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17616
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17617
			/* FALLTHRU */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17618
		case TI_GETMYNAME:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17619
			mi_copyin(q, mp, NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17620
			    SIZEOF_STRUCT(strbuf, iocp->ioc_flag));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17621
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17622
		case ND_SET:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17623
			/* nd_getset does the necessary checks */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17624
		case ND_GET:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17625
			if (!nd_getset(q, tcp_g_nd, mp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17626
				CALL_IP_WPUT(connp, q, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17627
				return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17628
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17629
			qreply(q, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17630
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17631
		case TCP_IOC_DEFAULT_Q:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17632
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17633
			 * Wants to be the default wq. Check the credentials
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17634
			 * first, the rest is executed via squeue.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17635
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17636
			if (secpolicy_net_config(iocp->ioc_cr, B_FALSE) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17637
				iocp->ioc_error = EPERM;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17638
				iocp->ioc_count = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17639
				mp->b_datap->db_type = M_IOCACK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17640
				qreply(q, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17641
				return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17642
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17643
			output_proc = tcp_wput_ioctl;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17644
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17645
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17646
			output_proc = tcp_wput_ioctl;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17647
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17648
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17649
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17650
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17651
		output_proc = tcp_wput_nondata;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17652
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17653
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17654
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17655
	CONN_INC_REF(connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17656
	(*tcp_squeue_wput_proc)(connp->conn_sqp, mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17657
	    output_proc, connp, SQTAG_TCP_WPUT_OTHER);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17658
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17659
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17660
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17661
 * Initial STREAMS write side put() procedure for sockets. It tries to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17662
 * handle the T_CAPABILITY_REQ which sockfs sends down while setting
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17663
 * up the socket without using the squeue. Non T_CAPABILITY_REQ messages
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17664
 * are handled by tcp_wput() as usual.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17665
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17666
 * All further messages will also be handled by tcp_wput() because we cannot
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17667
 * be sure that the above short cut is safe later.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17668
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17669
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17670
tcp_wput_sock(queue_t *wq, mblk_t *mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17671
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17672
	conn_t			*connp = Q_TO_CONN(wq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17673
	tcp_t			*tcp = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17674
	struct T_capability_req	*car = (struct T_capability_req *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17675
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17676
	ASSERT(wq->q_qinfo == &tcp_sock_winit);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17677
	wq->q_qinfo = &tcp_winit;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17678
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17679
	ASSERT(IPCL_IS_TCP(connp));
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17680
	ASSERT(TCP_IS_SOCKET(tcp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17681
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17682
	if (DB_TYPE(mp) == M_PCPROTO &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17683
	    MBLKL(mp) == sizeof (struct T_capability_req) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17684
	    car->PRIM_type == T_CAPABILITY_REQ) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17685
		tcp_capability_req(tcp, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17686
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17687
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17688
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17689
	tcp_wput(wq, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17690
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17691
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17692
static boolean_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17693
tcp_zcopy_check(tcp_t *tcp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17694
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17695
	conn_t	*connp = tcp->tcp_connp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17696
	ire_t	*ire;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17697
	boolean_t	zc_enabled = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17698
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17699
	if (do_tcpzcopy == 2)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17700
		zc_enabled = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17701
	else if (tcp->tcp_ipversion == IPV4_VERSION &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17702
	    IPCL_IS_CONNECTED(connp) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17703
	    (connp->conn_flags & IPCL_CHECK_POLICY) == 0 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17704
	    connp->conn_dontroute == 0 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17705
	    connp->conn_xmit_if_ill == NULL &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17706
	    connp->conn_nofailover_ill == NULL &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17707
	    do_tcpzcopy == 1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17708
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17709
		 * the checks above  closely resemble the fast path checks
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17710
		 * in tcp_send_data().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17711
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17712
		mutex_enter(&connp->conn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17713
		ire = connp->conn_ire_cache;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17714
		ASSERT(!(connp->conn_state_flags & CONN_INCIPIENT));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17715
		if (ire != NULL && !(ire->ire_marks & IRE_MARK_CONDEMNED)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17716
			IRE_REFHOLD(ire);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17717
			if (ire->ire_stq != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17718
				ill_t	*ill = (ill_t *)ire->ire_stq->q_ptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17719
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17720
				zc_enabled = ill && (ill->ill_capabilities &
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17721
				    ILL_CAPAB_ZEROCOPY) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17722
				    (ill->ill_zerocopy_capab->
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17723
				    ill_zerocopy_flags != 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17724
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17725
			IRE_REFRELE(ire);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17726
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17727
		mutex_exit(&connp->conn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17728
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17729
	tcp->tcp_snd_zcopy_on = zc_enabled;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17730
	if (!TCP_IS_DETACHED(tcp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17731
		if (zc_enabled) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17732
			(void) mi_set_sth_copyopt(tcp->tcp_rq, ZCVMSAFE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17733
			TCP_STAT(tcp_zcopy_on);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17734
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17735
			(void) mi_set_sth_copyopt(tcp->tcp_rq, ZCVMUNSAFE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17736
			TCP_STAT(tcp_zcopy_off);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17737
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17738
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17739
	return (zc_enabled);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17740
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17741
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17742
static mblk_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17743
tcp_zcopy_disable(tcp_t *tcp, mblk_t *bp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17744
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17745
	if (do_tcpzcopy == 2)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17746
		return (bp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17747
	else if (tcp->tcp_snd_zcopy_on) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17748
		tcp->tcp_snd_zcopy_on = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17749
		if (!TCP_IS_DETACHED(tcp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17750
			(void) mi_set_sth_copyopt(tcp->tcp_rq, ZCVMUNSAFE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17751
			TCP_STAT(tcp_zcopy_disable);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17752
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17753
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17754
	return (tcp_zcopy_backoff(tcp, bp, 0));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17755
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17756
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17757
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17758
 * Backoff from a zero-copy mblk by copying data to a new mblk and freeing
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17759
 * the original desballoca'ed segmapped mblk.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17760
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17761
static mblk_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17762
tcp_zcopy_backoff(tcp_t *tcp, mblk_t *bp, int fix_xmitlist)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17763
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17764
	mblk_t *head, *tail, *nbp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17765
	if (IS_VMLOANED_MBLK(bp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17766
		TCP_STAT(tcp_zcopy_backoff);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17767
		if ((head = copyb(bp)) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17768
			/* fail to backoff; leave it for the next backoff */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17769
			tcp->tcp_xmit_zc_clean = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17770
			return (bp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17771
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17772
		if (bp->b_datap->db_struioflag & STRUIO_ZCNOTIFY) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17773
			if (fix_xmitlist)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17774
				tcp_zcopy_notify(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17775
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17776
				head->b_datap->db_struioflag |= STRUIO_ZCNOTIFY;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17777
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17778
		nbp = bp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17779
		if (fix_xmitlist) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17780
			head->b_prev = bp->b_prev;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17781
			head->b_next = bp->b_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17782
			if (tcp->tcp_xmit_tail == bp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17783
				tcp->tcp_xmit_tail = head;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17784
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17785
		bp->b_next = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17786
		bp->b_prev = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17787
		freeb(bp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17788
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17789
		head = bp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17790
		nbp = bp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17791
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17792
	tail = head;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17793
	while (nbp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17794
		if (IS_VMLOANED_MBLK(nbp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17795
			TCP_STAT(tcp_zcopy_backoff);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17796
			if ((tail->b_cont = copyb(nbp)) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17797
				tcp->tcp_xmit_zc_clean = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17798
				tail->b_cont = nbp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17799
				return (head);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17800
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17801
			tail = tail->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17802
			if (nbp->b_datap->db_struioflag & STRUIO_ZCNOTIFY) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17803
				if (fix_xmitlist)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17804
					tcp_zcopy_notify(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17805
				else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17806
					tail->b_datap->db_struioflag |=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17807
					    STRUIO_ZCNOTIFY;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17808
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17809
			bp = nbp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17810
			nbp = nbp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17811
			if (fix_xmitlist) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17812
				tail->b_prev = bp->b_prev;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17813
				tail->b_next = bp->b_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17814
				if (tcp->tcp_xmit_tail == bp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17815
					tcp->tcp_xmit_tail = tail;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17816
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17817
			bp->b_next = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17818
			bp->b_prev = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17819
			freeb(bp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17820
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17821
			tail->b_cont = nbp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17822
			tail = nbp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17823
			nbp = nbp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17824
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17825
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17826
	if (fix_xmitlist) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17827
		tcp->tcp_xmit_last = tail;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17828
		tcp->tcp_xmit_zc_clean = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17829
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17830
	return (head);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17831
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17832
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17833
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17834
tcp_zcopy_notify(tcp_t *tcp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17835
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17836
	struct stdata	*stp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17837
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17838
	if (tcp->tcp_detached)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17839
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17840
	stp = STREAM(tcp->tcp_rq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17841
	mutex_enter(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17842
	stp->sd_flag |= STZCNOTIFY;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17843
	cv_broadcast(&stp->sd_zcopy_wait);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17844
	mutex_exit(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17845
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17846
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17847
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17848
tcp_send_data(tcp_t *tcp, queue_t *q, mblk_t *mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17849
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17850
	ipha_t		*ipha;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17851
	ipaddr_t	src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17852
	ipaddr_t	dst;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17853
	uint32_t	cksum;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17854
	ire_t		*ire;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17855
	uint16_t	*up;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17856
	ill_t		*ill;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17857
	conn_t		*connp = tcp->tcp_connp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17858
	uint32_t	hcksum_txflags = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17859
	mblk_t		*ire_fp_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17860
	uint_t		ire_fp_mp_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17861
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17862
	ASSERT(DB_TYPE(mp) == M_DATA);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17863
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17864
	ipha = (ipha_t *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17865
	src = ipha->ipha_src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17866
	dst = ipha->ipha_dst;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17867
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17868
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17869
	 * Drop off slow path for IPv6 and also if options are present.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17870
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17871
	if (tcp->tcp_ipversion != IPV4_VERSION ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17872
	    !IPCL_IS_CONNECTED(connp) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17873
	    (connp->conn_flags & IPCL_CHECK_POLICY) != 0 ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17874
	    connp->conn_dontroute ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17875
	    connp->conn_xmit_if_ill != NULL ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17876
	    connp->conn_nofailover_ill != NULL ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17877
	    ipha->ipha_ident == IP_HDR_INCLUDED ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17878
	    ipha->ipha_version_and_hdr_length != IP_SIMPLE_HDR_VERSION ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17879
	    IPP_ENABLED(IPP_LOCAL_OUT)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17880
		if (tcp->tcp_snd_zcopy_aware)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17881
			mp = tcp_zcopy_disable(tcp, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17882
		TCP_STAT(tcp_ip_send);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17883
		CALL_IP_WPUT(connp, q, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17884
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17885
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17886
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17887
	mutex_enter(&connp->conn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17888
	ire = connp->conn_ire_cache;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17889
	ASSERT(!(connp->conn_state_flags & CONN_INCIPIENT));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17890
	if (ire != NULL && ire->ire_addr == dst &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17891
	    !(ire->ire_marks & IRE_MARK_CONDEMNED)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17892
		IRE_REFHOLD(ire);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17893
		mutex_exit(&connp->conn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17894
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17895
		boolean_t cached = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17896
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17897
		/* force a recheck later on */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17898
		tcp->tcp_ire_ill_check_done = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17899
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17900
		TCP_DBGSTAT(tcp_ire_null1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17901
		connp->conn_ire_cache = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17902
		mutex_exit(&connp->conn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17903
		if (ire != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17904
			IRE_REFRELE_NOTR(ire);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17905
		ire = ire_cache_lookup(dst, connp->conn_zoneid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17906
		if (ire == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17907
			if (tcp->tcp_snd_zcopy_aware)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17908
				mp = tcp_zcopy_backoff(tcp, mp, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17909
			TCP_STAT(tcp_ire_null);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17910
			CALL_IP_WPUT(connp, q, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17911
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17912
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17913
		IRE_REFHOLD_NOTR(ire);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17914
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17915
		 * Since we are inside the squeue, there cannot be another
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17916
		 * thread in TCP trying to set the conn_ire_cache now.  The
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17917
		 * check for IRE_MARK_CONDEMNED ensures that an interface
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17918
		 * unplumb thread has not yet started cleaning up the conns.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17919
		 * Hence we don't need to grab the conn lock.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17920
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17921
		if (!(connp->conn_state_flags & CONN_CLOSING)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17922
			rw_enter(&ire->ire_bucket->irb_lock, RW_READER);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17923
			if (!(ire->ire_marks & IRE_MARK_CONDEMNED)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17924
				connp->conn_ire_cache = ire;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17925
				cached = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17926
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17927
			rw_exit(&ire->ire_bucket->irb_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17928
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17929
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17930
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17931
		 * We can continue to use the ire but since it was
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17932
		 * not cached, we should drop the extra reference.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17933
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17934
		if (!cached)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17935
			IRE_REFRELE_NOTR(ire);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17936
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17937
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17938
	if (ire->ire_flags & RTF_MULTIRT ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17939
	    ire->ire_stq == NULL ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17940
	    ire->ire_max_frag < ntohs(ipha->ipha_length) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17941
	    (ire_fp_mp = ire->ire_fp_mp) == NULL ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17942
	    (ire_fp_mp_len = MBLKL(ire_fp_mp)) > MBLKHEAD(mp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17943
		if (tcp->tcp_snd_zcopy_aware)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17944
			mp = tcp_zcopy_disable(tcp, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17945
		TCP_STAT(tcp_ip_ire_send);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17946
		IRE_REFRELE(ire);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17947
		CALL_IP_WPUT(connp, q, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17948
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17949
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17950
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17951
	ill = ire_to_ill(ire);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17952
	if (connp->conn_outgoing_ill != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17953
		ill_t *conn_outgoing_ill = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17954
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17955
		 * Choose a good ill in the group to send the packets on.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17956
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17957
		ire = conn_set_outgoing_ill(connp, ire, &conn_outgoing_ill);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17958
		ill = ire_to_ill(ire);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17959
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17960
	ASSERT(ill != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17961
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17962
	if (!tcp->tcp_ire_ill_check_done) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17963
		tcp_ire_ill_check(tcp, ire, ill, B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17964
		tcp->tcp_ire_ill_check_done = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17965
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17966
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17967
	ASSERT(ipha->ipha_ident == 0 || ipha->ipha_ident == IP_HDR_INCLUDED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17968
	ipha->ipha_ident = (uint16_t)atomic_add_32_nv(&ire->ire_ident, 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17969
#ifndef _BIG_ENDIAN
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17970
	ipha->ipha_ident = (ipha->ipha_ident << 8) | (ipha->ipha_ident >> 8);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17971
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17972
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17973
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17974
	 * Check to see if we need to re-enable MDT for this connection
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17975
	 * because it was previously disabled due to changes in the ill;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17976
	 * note that by doing it here, this re-enabling only applies when
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17977
	 * the packet is not dispatched through CALL_IP_WPUT().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17978
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17979
	 * That means for IPv4, it is worth re-enabling MDT for the fastpath
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17980
	 * case, since that's how we ended up here.  For IPv6, we do the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17981
	 * re-enabling work in ip_xmit_v6(), albeit indirectly via squeue.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17982
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17983
	if (connp->conn_mdt_ok && !tcp->tcp_mdt && ILL_MDT_USABLE(ill)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17984
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17985
		 * Restore MDT for this connection, so that next time around
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17986
		 * it is eligible to go through tcp_multisend() path again.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17987
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17988
		TCP_STAT(tcp_mdt_conn_resumed1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17989
		tcp->tcp_mdt = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17990
		ip1dbg(("tcp_send_data: reenabling MDT for connp %p on "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17991
		    "interface %s\n", (void *)connp, ill->ill_name));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17992
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17993
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17994
	if (tcp->tcp_snd_zcopy_aware) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17995
		if ((ill->ill_capabilities & ILL_CAPAB_ZEROCOPY) == 0 ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17996
		    (ill->ill_zerocopy_capab->ill_zerocopy_flags == 0))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17997
			mp = tcp_zcopy_disable(tcp, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17998
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17999
		 * we shouldn't need to reset ipha as the mp containing
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18000
		 * ipha should never be a zero-copy mp.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18001
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18002
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18003
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 18004
	if (ILL_HCKSUM_CAPABLE(ill) && dohwcksum) {
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18005
		ASSERT(ill->ill_hcksum_capab != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18006
		hcksum_txflags = ill->ill_hcksum_capab->ill_hcksum_txflags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18007
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18008
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18009
	/* pseudo-header checksum (do it in parts for IP header checksum) */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18010
	cksum = (dst >> 16) + (dst & 0xFFFF) + (src >> 16) + (src & 0xFFFF);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18011
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18012
	ASSERT(ipha->ipha_version_and_hdr_length == IP_SIMPLE_HDR_VERSION);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18013
	up = IPH_TCPH_CHECKSUMP(ipha, IP_SIMPLE_HDR_LENGTH);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18014
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 18015
	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
 18016
	    IPPROTO_TCP, IP_SIMPLE_HDR_LENGTH, ntohs(ipha->ipha_length), cksum);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 18017
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 18018
	/* Software checksum? */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 18019
	if (DB_CKSUMFLAGS(mp) == 0) {
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18020
		TCP_STAT(tcp_out_sw_cksum);
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 18021
		TCP_STAT_UPDATE(tcp_out_sw_cksum_bytes,
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 18022
		    ntohs(ipha->ipha_length) - IP_SIMPLE_HDR_LENGTH);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18023
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18024
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18025
	ipha->ipha_fragment_offset_and_flags |=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18026
	    (uint32_t)htons(ire->ire_frag_flag);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18027
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 18028
	/* Calculate IP header checksum if hardware isn't capable */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 18029
	if (!(DB_CKSUMFLAGS(mp) & HCK_IPV4_HDRCKSUM)) {
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18030
		IP_HDR_CKSUM(ipha, cksum, ((uint32_t *)ipha)[0],
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18031
		    ((uint16_t *)ipha)[4]);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18032
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18033
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18034
	ASSERT(DB_TYPE(ire_fp_mp) == M_DATA);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18035
	mp->b_rptr = (uchar_t *)ipha - ire_fp_mp_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18036
	bcopy(ire_fp_mp->b_rptr, mp->b_rptr, ire_fp_mp_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18037
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18038
	UPDATE_OB_PKT_COUNT(ire);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18039
	ire->ire_last_used_time = lbolt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18040
	BUMP_MIB(&ip_mib, ipOutRequests);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18041
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 18042
	if (ILL_POLL_CAPABLE(ill)) {
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 18043
		/*
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 18044
		 * Send the packet directly to DLD, where it may be queued
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 18045
		 * depending on the availability of transmit resources at
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 18046
		 * the media layer.
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 18047
		 */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 18048
		IP_POLL_ILL_TX(ill, mp);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18049
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18050
		putnext(ire->ire_stq, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18051
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18052
	IRE_REFRELE(ire);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18053
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18054
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18055
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18056
 * This handles the case when the receiver has shrunk its win. Per RFC 1122
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18057
 * if the receiver shrinks the window, i.e. moves the right window to the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18058
 * left, the we should not send new data, but should retransmit normally the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18059
 * old unacked data between suna and suna + swnd. We might has sent data
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18060
 * that is now outside the new window, pretend that we didn't send  it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18061
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18062
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18063
tcp_process_shrunk_swnd(tcp_t *tcp, uint32_t shrunk_count)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18064
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18065
	uint32_t	snxt = tcp->tcp_snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18066
	mblk_t		*xmit_tail;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18067
	int32_t		offset;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18068
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18069
	ASSERT(shrunk_count > 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18070
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18071
	/* Pretend we didn't send the data outside the window */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18072
	snxt -= shrunk_count;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18073
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18074
	/* Get the mblk and the offset in it per the shrunk window */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18075
	xmit_tail = tcp_get_seg_mp(tcp, snxt, &offset);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18076
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18077
	ASSERT(xmit_tail != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18078
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18079
	/* Reset all the values per the now shrunk window */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18080
	tcp->tcp_snxt = snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18081
	tcp->tcp_xmit_tail = xmit_tail;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18082
	tcp->tcp_xmit_tail_unsent = xmit_tail->b_wptr - xmit_tail->b_rptr -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18083
	    offset;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18084
	tcp->tcp_unsent += shrunk_count;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18085
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18086
	if (tcp->tcp_suna == tcp->tcp_snxt && tcp->tcp_swnd == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18087
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18088
		 * Make sure the timer is running so that we will probe a zero
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18089
		 * window.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18090
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18091
		TCP_TIMER_RESTART(tcp, tcp->tcp_rto);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18092
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18093
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18094
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18095
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18096
 * The TCP normal data output path.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18097
 * NOTE: the logic of the fast path is duplicated from this function.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18098
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18099
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18100
tcp_wput_data(tcp_t *tcp, mblk_t *mp, boolean_t urgent)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18101
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18102
	int		len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18103
	mblk_t		*local_time;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18104
	mblk_t		*mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18105
	uint32_t	snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18106
	int		tail_unsent;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18107
	int		tcpstate;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18108
	int		usable = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18109
	mblk_t		*xmit_tail;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18110
	queue_t		*q = tcp->tcp_wq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18111
	int32_t		mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18112
	int32_t		num_sack_blk = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18113
	int32_t		tcp_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18114
	int32_t		tcp_tcp_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18115
	int		mdt_thres;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18116
	int		rc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18117
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18118
	tcpstate = tcp->tcp_state;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18119
	if (mp == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18120
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18121
		 * tcp_wput_data() with NULL mp should only be called when
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18122
		 * there is unsent data.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18123
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18124
		ASSERT(tcp->tcp_unsent > 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18125
		/* Really tacky... but we need this for detached closes. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18126
		len = tcp->tcp_unsent;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18127
		goto data_null;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18128
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18129
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18130
#if CCS_STATS
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18131
	wrw_stats.tot.count++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18132
	wrw_stats.tot.bytes += msgdsize(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18133
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18134
	ASSERT(mp->b_datap->db_type == M_DATA);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18135
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18136
	 * Don't allow data after T_ORDREL_REQ or T_DISCON_REQ,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18137
	 * or before a connection attempt has begun.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18138
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18139
	if (tcpstate < TCPS_SYN_SENT || tcpstate > TCPS_CLOSE_WAIT ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18140
	    (tcp->tcp_valid_bits & TCP_FSS_VALID) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18141
		if ((tcp->tcp_valid_bits & TCP_FSS_VALID) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18142
#ifdef DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18143
			cmn_err(CE_WARN,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18144
			    "tcp_wput_data: data after ordrel, %s",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18145
			    tcp_display(tcp, NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18146
			    DISP_ADDR_AND_PORT));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18147
#else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18148
			if (tcp->tcp_debug) {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 18149
				(void) strlog(TCP_MOD_ID, 0, 1,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18150
				    SL_TRACE|SL_ERROR,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18151
				    "tcp_wput_data: data after ordrel, %s\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18152
				    tcp_display(tcp, NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18153
				    DISP_ADDR_AND_PORT));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18154
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18155
#endif /* DEBUG */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18156
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18157
		if (tcp->tcp_snd_zcopy_aware &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18158
		    (mp->b_datap->db_struioflag & STRUIO_ZCNOTIFY) != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18159
			tcp_zcopy_notify(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18160
		freemsg(mp);
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 18161
		if (tcp->tcp_flow_stopped &&
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 18162
		    TCP_UNSENT_BYTES(tcp) <= tcp->tcp_xmit_lowater) {
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 18163
			tcp_clrqfull(tcp);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 18164
		}
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18165
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18166
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18167
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18168
	/* Strip empties */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18169
	for (;;) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18170
		ASSERT((uintptr_t)(mp->b_wptr - mp->b_rptr) <=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18171
		    (uintptr_t)INT_MAX);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18172
		len = (int)(mp->b_wptr - mp->b_rptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18173
		if (len > 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18174
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18175
		mp1 = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18176
		mp = mp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18177
		freeb(mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18178
		if (!mp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18179
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18180
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18181
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18182
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18183
	/* If we are the first on the list ... */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18184
	if (tcp->tcp_xmit_head == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18185
		tcp->tcp_xmit_head = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18186
		tcp->tcp_xmit_tail = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18187
		tcp->tcp_xmit_tail_unsent = len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18188
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18189
		/* If tiny tx and room in txq tail, pullup to save mblks. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18190
		struct datab *dp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18191
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18192
		mp1 = tcp->tcp_xmit_last;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18193
		if (len < tcp_tx_pull_len &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18194
		    (dp = mp1->b_datap)->db_ref == 1 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18195
		    dp->db_lim - mp1->b_wptr >= len) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18196
			ASSERT(len > 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18197
			ASSERT(!mp1->b_cont);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18198
			if (len == 1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18199
				*mp1->b_wptr++ = *mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18200
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18201
				bcopy(mp->b_rptr, mp1->b_wptr, len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18202
				mp1->b_wptr += len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18203
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18204
			if (mp1 == tcp->tcp_xmit_tail)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18205
				tcp->tcp_xmit_tail_unsent += len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18206
			mp1->b_cont = mp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18207
			if (tcp->tcp_snd_zcopy_aware &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18208
			    (mp->b_datap->db_struioflag & STRUIO_ZCNOTIFY))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18209
				mp1->b_datap->db_struioflag |= STRUIO_ZCNOTIFY;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18210
			freeb(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18211
			mp = mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18212
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18213
			tcp->tcp_xmit_last->b_cont = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18214
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18215
		len += tcp->tcp_unsent;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18216
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18217
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18218
	/* Tack on however many more positive length mblks we have */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18219
	if ((mp1 = mp->b_cont) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18220
		do {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18221
			int tlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18222
			ASSERT((uintptr_t)(mp1->b_wptr - mp1->b_rptr) <=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18223
			    (uintptr_t)INT_MAX);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18224
			tlen = (int)(mp1->b_wptr - mp1->b_rptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18225
			if (tlen <= 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18226
				mp->b_cont = mp1->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18227
				freeb(mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18228
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18229
				len += tlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18230
				mp = mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18231
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18232
		} while ((mp1 = mp->b_cont) != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18233
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18234
	tcp->tcp_xmit_last = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18235
	tcp->tcp_unsent = len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18236
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18237
	if (urgent)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18238
		usable = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18239
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18240
data_null:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18241
	snxt = tcp->tcp_snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18242
	xmit_tail = tcp->tcp_xmit_tail;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18243
	tail_unsent = tcp->tcp_xmit_tail_unsent;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18244
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18245
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18246
	 * Note that tcp_mss has been adjusted to take into account the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18247
	 * timestamp option if applicable.  Because SACK options do not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18248
	 * appear in every TCP segments and they are of variable lengths,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18249
	 * they cannot be included in tcp_mss.  Thus we need to calculate
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18250
	 * the actual segment length when we need to send a segment which
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18251
	 * includes SACK options.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18252
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18253
	if (tcp->tcp_snd_sack_ok && tcp->tcp_num_sack_blk > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18254
		int32_t	opt_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18255
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18256
		num_sack_blk = MIN(tcp->tcp_max_sack_blk,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18257
		    tcp->tcp_num_sack_blk);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18258
		opt_len = num_sack_blk * sizeof (sack_blk_t) + TCPOPT_NOP_LEN *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18259
		    2 + TCPOPT_HEADER_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18260
		mss = tcp->tcp_mss - opt_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18261
		tcp_hdr_len = tcp->tcp_hdr_len + opt_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18262
		tcp_tcp_hdr_len = tcp->tcp_tcp_hdr_len + opt_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18263
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18264
		mss = tcp->tcp_mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18265
		tcp_hdr_len = tcp->tcp_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18266
		tcp_tcp_hdr_len = tcp->tcp_tcp_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18267
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18268
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18269
	if ((tcp->tcp_suna == snxt) && !tcp->tcp_localnet &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18270
	    (TICK_TO_MSEC(lbolt - tcp->tcp_last_recv_time) >= tcp->tcp_rto)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18271
		SET_TCP_INIT_CWND(tcp, mss, tcp_slow_start_after_idle);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18272
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18273
	if (tcpstate == TCPS_SYN_RCVD) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18274
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18275
		 * The three-way connection establishment handshake is not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18276
		 * complete yet. We want to queue the data for transmission
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18277
		 * after entering ESTABLISHED state (RFC793). A jump to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18278
		 * "done" label effectively leaves data on the queue.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18279
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18280
		goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18281
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18282
		int usable_r = tcp->tcp_swnd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18283
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18284
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18285
		 * In the special case when cwnd is zero, which can only
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18286
		 * happen if the connection is ECN capable, return now.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18287
		 * New segments is sent using tcp_timer().  The timer
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18288
		 * is set in tcp_rput_data().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18289
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18290
		if (tcp->tcp_cwnd == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18291
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18292
			 * Note that tcp_cwnd is 0 before 3-way handshake is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18293
			 * finished.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18294
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18295
			ASSERT(tcp->tcp_ecn_ok ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18296
			    tcp->tcp_state < TCPS_ESTABLISHED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18297
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18298
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18299
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18300
		/* NOTE: trouble if xmitting while SYN not acked? */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18301
		usable_r -= snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18302
		usable_r += tcp->tcp_suna;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18303
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18304
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18305
		 * Check if the receiver has shrunk the window.  If
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18306
		 * tcp_wput_data() with NULL mp is called, tcp_fin_sent
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18307
		 * cannot be set as there is unsent data, so FIN cannot
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18308
		 * be sent out.  Otherwise, we need to take into account
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18309
		 * of FIN as it consumes an "invisible" sequence number.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18310
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18311
		ASSERT(tcp->tcp_fin_sent == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18312
		if (usable_r < 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18313
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18314
			 * The receiver has shrunk the window and we have sent
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18315
			 * -usable_r date beyond the window, re-adjust.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18316
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18317
			 * If TCP window scaling is enabled, there can be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18318
			 * round down error as the advertised receive window
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18319
			 * is actually right shifted n bits.  This means that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18320
			 * the lower n bits info is wiped out.  It will look
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18321
			 * like the window is shrunk.  Do a check here to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18322
			 * see if the shrunk amount is actually within the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18323
			 * error in window calculation.  If it is, just
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18324
			 * return.  Note that this check is inside the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18325
			 * shrunk window check.  This makes sure that even
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18326
			 * though tcp_process_shrunk_swnd() is not called,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18327
			 * we will stop further processing.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18328
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18329
			if ((-usable_r >> tcp->tcp_snd_ws) > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18330
				tcp_process_shrunk_swnd(tcp, -usable_r);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18331
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18332
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18333
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18334
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18335
		/* usable = MIN(swnd, cwnd) - unacked_bytes */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18336
		if (tcp->tcp_swnd > tcp->tcp_cwnd)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18337
			usable_r -= tcp->tcp_swnd - tcp->tcp_cwnd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18338
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18339
		/* usable = MIN(usable, unsent) */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18340
		if (usable_r > len)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18341
			usable_r = len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18342
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18343
		/* usable = MAX(usable, {1 for urgent, 0 for data}) */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18344
		if (usable_r > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18345
			usable = usable_r;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18346
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18347
			/* Bypass all other unnecessary processing. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18348
			goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18349
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18350
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18351
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18352
	local_time = (mblk_t *)lbolt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18353
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18354
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18355
	 * "Our" Nagle Algorithm.  This is not the same as in the old
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18356
	 * BSD.  This is more in line with the true intent of Nagle.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18357
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18358
	 * The conditions are:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18359
	 * 1. The amount of unsent data (or amount of data which can be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18360
	 *    sent, whichever is smaller) is less than Nagle limit.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18361
	 * 2. The last sent size is also less than Nagle limit.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18362
	 * 3. There is unack'ed data.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18363
	 * 4. Urgent pointer is not set.  Send urgent data ignoring the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18364
	 *    Nagle algorithm.  This reduces the probability that urgent
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18365
	 *    bytes get "merged" together.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18366
	 * 5. The app has not closed the connection.  This eliminates the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18367
	 *    wait time of the receiving side waiting for the last piece of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18368
	 *    (small) data.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18369
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18370
	 * If all are satisified, exit without sending anything.  Note
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18371
	 * that Nagle limit can be smaller than 1 MSS.  Nagle limit is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18372
	 * the smaller of 1 MSS and global tcp_naglim_def (default to be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18373
	 * 4095).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18374
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18375
	if (usable < (int)tcp->tcp_naglim &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18376
	    tcp->tcp_naglim > tcp->tcp_last_sent_len &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18377
	    snxt != tcp->tcp_suna &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18378
	    !(tcp->tcp_valid_bits & TCP_URG_VALID) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18379
	    !(tcp->tcp_valid_bits & TCP_FSS_VALID)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18380
		goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18381
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18382
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18383
	if (tcp->tcp_cork) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18384
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18385
		 * if the tcp->tcp_cork option is set, then we have to force
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18386
		 * TCP not to send partial segment (smaller than MSS bytes).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18387
		 * We are calculating the usable now based on full mss and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18388
		 * will save the rest of remaining data for later.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18389
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18390
		if (usable < mss)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18391
			goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18392
		usable = (usable / mss) * mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18393
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18394
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18395
	/* Update the latest receive window size in TCP header. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18396
	U32_TO_ABE16(tcp->tcp_rwnd >> tcp->tcp_rcv_ws,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18397
	    tcp->tcp_tcph->th_win);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18398
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18399
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18400
	 * Determine if it's worthwhile to attempt MDT, based on:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18401
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18402
	 * 1. Simple TCP/IP{v4,v6} (no options).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18403
	 * 2. IPSEC/IPQoS processing is not needed for the TCP connection.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18404
	 * 3. If the TCP connection is in ESTABLISHED state.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18405
	 * 4. The TCP is not detached.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18406
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18407
	 * If any of the above conditions have changed during the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18408
	 * connection, stop using MDT and restore the stream head
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18409
	 * parameters accordingly.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18410
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18411
	if (tcp->tcp_mdt &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18412
	    ((tcp->tcp_ipversion == IPV4_VERSION &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18413
	    tcp->tcp_ip_hdr_len != IP_SIMPLE_HDR_LENGTH) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18414
	    (tcp->tcp_ipversion == IPV6_VERSION &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18415
	    tcp->tcp_ip_hdr_len != IPV6_HDR_LEN) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18416
	    tcp->tcp_state != TCPS_ESTABLISHED ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18417
	    TCP_IS_DETACHED(tcp) || !CONN_IS_MD_FASTPATH(tcp->tcp_connp) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18418
	    CONN_IPSEC_OUT_ENCAPSULATED(tcp->tcp_connp) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18419
	    IPP_ENABLED(IPP_LOCAL_OUT))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18420
		tcp->tcp_connp->conn_mdt_ok = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18421
		tcp->tcp_mdt = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18422
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18423
		/* Anything other than detached is considered pathological */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18424
		if (!TCP_IS_DETACHED(tcp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18425
			TCP_STAT(tcp_mdt_conn_halted1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18426
			(void) tcp_maxpsz_set(tcp, B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18427
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18428
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18429
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18430
	/* Use MDT if sendable amount is greater than the threshold */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18431
	if (tcp->tcp_mdt &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18432
	    (mdt_thres = mss << tcp_mdt_smss_threshold, usable > mdt_thres) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18433
	    (tail_unsent > mdt_thres || (xmit_tail->b_cont != NULL &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18434
	    MBLKL(xmit_tail->b_cont) > mdt_thres)) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18435
	    (tcp->tcp_valid_bits == 0 ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18436
	    tcp->tcp_valid_bits == TCP_FSS_VALID)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18437
		ASSERT(tcp->tcp_connp->conn_mdt_ok);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18438
		rc = tcp_multisend(q, tcp, mss, tcp_hdr_len, tcp_tcp_hdr_len,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18439
		    num_sack_blk, &usable, &snxt, &tail_unsent, &xmit_tail,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18440
		    local_time, mdt_thres);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18441
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18442
		rc = tcp_send(q, tcp, mss, tcp_hdr_len, tcp_tcp_hdr_len,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18443
		    num_sack_blk, &usable, &snxt, &tail_unsent, &xmit_tail,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18444
		    local_time, INT_MAX);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18445
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18446
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18447
	/* Pretend that all we were trying to send really got sent */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18448
	if (rc < 0 && tail_unsent < 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18449
		do {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18450
			xmit_tail = xmit_tail->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18451
			xmit_tail->b_prev = local_time;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18452
			ASSERT((uintptr_t)(xmit_tail->b_wptr -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18453
			    xmit_tail->b_rptr) <= (uintptr_t)INT_MAX);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18454
			tail_unsent += (int)(xmit_tail->b_wptr -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18455
			    xmit_tail->b_rptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18456
		} while (tail_unsent < 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18457
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18458
done:;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18459
	tcp->tcp_xmit_tail = xmit_tail;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18460
	tcp->tcp_xmit_tail_unsent = tail_unsent;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18461
	len = tcp->tcp_snxt - snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18462
	if (len) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18463
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18464
		 * If new data was sent, need to update the notsack
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18465
		 * list, which is, afterall, data blocks that have
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18466
		 * not been sack'ed by the receiver.  New data is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18467
		 * not sack'ed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18468
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18469
		if (tcp->tcp_snd_sack_ok && tcp->tcp_notsack_list != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18470
			/* len is a negative value. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18471
			tcp->tcp_pipe -= len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18472
			tcp_notsack_update(&(tcp->tcp_notsack_list),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18473
			    tcp->tcp_snxt, snxt,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18474
			    &(tcp->tcp_num_notsack_blk),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18475
			    &(tcp->tcp_cnt_notsack_list));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18476
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18477
		tcp->tcp_snxt = snxt + tcp->tcp_fin_sent;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18478
		tcp->tcp_rack = tcp->tcp_rnxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18479
		tcp->tcp_rack_cnt = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18480
		if ((snxt + len) == tcp->tcp_suna) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18481
			TCP_TIMER_RESTART(tcp, tcp->tcp_rto);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18482
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18483
	} else if (snxt == tcp->tcp_suna && tcp->tcp_swnd == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18484
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18485
		 * Didn't send anything. Make sure the timer is running
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18486
		 * so that we will probe a zero window.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18487
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18488
		TCP_TIMER_RESTART(tcp, tcp->tcp_rto);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18489
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18490
	/* 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
 18491
	tcp->tcp_unsent += len;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18492
	if (tcp->tcp_flow_stopped) {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 18493
		if (TCP_UNSENT_BYTES(tcp) <= tcp->tcp_xmit_lowater) {
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18494
			tcp_clrqfull(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18495
		}
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 18496
	} else if (TCP_UNSENT_BYTES(tcp) >= tcp->tcp_xmit_hiwater) {
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18497
		tcp_setqfull(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18498
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18499
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18500
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18501
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18502
 * tcp_fill_header is called by tcp_send() and tcp_multisend() to fill the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18503
 * outgoing TCP header with the template header, as well as other
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18504
 * options such as time-stamp, ECN and/or SACK.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18505
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18506
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18507
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
 18508
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18509
	tcph_t *tcp_tmpl, *tcp_h;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18510
	uint32_t *dst, *src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18511
	int hdrlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18512
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18513
	ASSERT(OK_32PTR(rptr));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18514
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18515
	/* Template header */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18516
	tcp_tmpl = tcp->tcp_tcph;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18517
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18518
	/* Header of outgoing packet */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18519
	tcp_h = (tcph_t *)(rptr + tcp->tcp_ip_hdr_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18520
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18521
	/* dst and src are opaque 32-bit fields, used for copying */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18522
	dst = (uint32_t *)rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18523
	src = (uint32_t *)tcp->tcp_iphc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18524
	hdrlen = tcp->tcp_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18525
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18526
	/* Fill time-stamp option if needed */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18527
	if (tcp->tcp_snd_ts_ok) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18528
		U32_TO_BE32((uint32_t)now,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18529
		    (char *)tcp_tmpl + TCP_MIN_HEADER_LENGTH + 4);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18530
		U32_TO_BE32(tcp->tcp_ts_recent,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18531
		    (char *)tcp_tmpl + TCP_MIN_HEADER_LENGTH + 8);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18532
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18533
		ASSERT(tcp->tcp_tcp_hdr_len == TCP_MIN_HEADER_LENGTH);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18534
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18535
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18536
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18537
	 * Copy the template header; is this really more efficient than
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18538
	 * calling bcopy()?  For simple IPv4/TCP, it may be the case,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18539
	 * but perhaps not for other scenarios.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18540
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18541
	dst[0] = src[0];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18542
	dst[1] = src[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18543
	dst[2] = src[2];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18544
	dst[3] = src[3];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18545
	dst[4] = src[4];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18546
	dst[5] = src[5];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18547
	dst[6] = src[6];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18548
	dst[7] = src[7];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18549
	dst[8] = src[8];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18550
	dst[9] = src[9];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18551
	if (hdrlen -= 40) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18552
		hdrlen >>= 2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18553
		dst += 10;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18554
		src += 10;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18555
		do {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18556
			*dst++ = *src++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18557
		} while (--hdrlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18558
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18559
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18560
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18561
	 * Set the ECN info in the TCP header if it is not a zero
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18562
	 * window probe.  Zero window probe is only sent in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18563
	 * tcp_wput_data() and tcp_timer().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18564
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18565
	if (tcp->tcp_ecn_ok && !tcp->tcp_zero_win_probe) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18566
		SET_ECT(tcp, rptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18567
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18568
		if (tcp->tcp_ecn_echo_on)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18569
			tcp_h->th_flags[0] |= TH_ECE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18570
		if (tcp->tcp_cwr && !tcp->tcp_ecn_cwr_sent) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18571
			tcp_h->th_flags[0] |= TH_CWR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18572
			tcp->tcp_ecn_cwr_sent = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18573
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18574
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18575
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18576
	/* Fill in SACK options */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18577
	if (num_sack_blk > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18578
		uchar_t *wptr = rptr + tcp->tcp_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18579
		sack_blk_t *tmp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18580
		int32_t	i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18581
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18582
		wptr[0] = TCPOPT_NOP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18583
		wptr[1] = TCPOPT_NOP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18584
		wptr[2] = TCPOPT_SACK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18585
		wptr[3] = TCPOPT_HEADER_LEN + num_sack_blk *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18586
		    sizeof (sack_blk_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18587
		wptr += TCPOPT_REAL_SACK_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18588
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18589
		tmp = tcp->tcp_sack_list;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18590
		for (i = 0; i < num_sack_blk; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18591
			U32_TO_BE32(tmp[i].begin, wptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18592
			wptr += sizeof (tcp_seq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18593
			U32_TO_BE32(tmp[i].end, wptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18594
			wptr += sizeof (tcp_seq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18595
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18596
		tcp_h->th_offset_and_rsrvd[0] +=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18597
		    ((num_sack_blk * 2 + 1) << 4);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18598
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18599
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18600
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18601
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18602
 * tcp_mdt_add_attrs() is called by tcp_multisend() in order to attach
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18603
 * the destination address and SAP attribute, and if necessary, the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18604
 * hardware checksum offload attribute to a Multidata message.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18605
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18606
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18607
tcp_mdt_add_attrs(multidata_t *mmd, const mblk_t *dlmp, const boolean_t hwcksum,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18608
    const uint32_t start, const uint32_t stuff, const uint32_t end,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18609
    const uint32_t flags)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18610
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18611
	/* Add global destination address & SAP attribute */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18612
	if (dlmp == NULL || !ip_md_addr_attr(mmd, NULL, dlmp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18613
		ip1dbg(("tcp_mdt_add_attrs: can't add global physical "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18614
		    "destination address+SAP\n"));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18615
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18616
		if (dlmp != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18617
			TCP_STAT(tcp_mdt_allocfail);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18618
		return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18619
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18620
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18621
	/* Add global hwcksum attribute */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18622
	if (hwcksum &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18623
	    !ip_md_hcksum_attr(mmd, NULL, start, stuff, end, flags)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18624
		ip1dbg(("tcp_mdt_add_attrs: can't add global hardware "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18625
		    "checksum attribute\n"));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18626
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18627
		TCP_STAT(tcp_mdt_allocfail);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18628
		return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18629
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18630
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18631
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18632
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18633
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18634
/*
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 18635
 * Smaller and private version of pdescinfo_t used specifically for TCP,
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 18636
 * which allows for only two payload spans per packet.
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 18637
 */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 18638
typedef struct tcp_pdescinfo_s PDESCINFO_STRUCT(2) tcp_pdescinfo_t;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 18639
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 18640
/*
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18641
 * tcp_multisend() is called by tcp_wput_data() for Multidata Transmit
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18642
 * scheme, and returns one the following:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18643
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18644
 * -1 = failed allocation.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18645
 *  0 = success; burst count reached, or usable send window is too small,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18646
 *      and that we'd rather wait until later before sending again.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18647
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18648
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18649
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
 18650
    const int tcp_tcp_hdr_len, const int num_sack_blk, int *usable,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18651
    uint_t *snxt, int *tail_unsent, mblk_t **xmit_tail, mblk_t *local_time,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18652
    const int mdt_thres)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18653
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18654
	mblk_t		*md_mp_head, *md_mp, *md_pbuf, *md_pbuf_nxt, *md_hbuf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18655
	multidata_t	*mmd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18656
	uint_t		obsegs, obbytes, hdr_frag_sz;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18657
	uint_t		cur_hdr_off, cur_pld_off, base_pld_off, first_snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18658
	int		num_burst_seg, max_pld;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18659
	pdesc_t		*pkt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18660
	tcp_pdescinfo_t	tcp_pkt_info;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18661
	pdescinfo_t	*pkt_info;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18662
	int		pbuf_idx, pbuf_idx_nxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18663
	int		seg_len, len, spill, af;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18664
	boolean_t	add_buffer, zcopy, clusterwide;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18665
	boolean_t	rconfirm = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18666
	boolean_t	done = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18667
	uint32_t	cksum;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18668
	uint32_t	hwcksum_flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18669
	ire_t		*ire;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18670
	ill_t		*ill;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18671
	ipha_t		*ipha;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18672
	ip6_t		*ip6h;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18673
	ipaddr_t	src, dst;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18674
	ill_zerocopy_capab_t *zc_cap = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18675
	uint16_t	*up;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18676
	int		err;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18677
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18678
#ifdef	_BIG_ENDIAN
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18679
#define	IPVER(ip6h)	((((uint32_t *)ip6h)[0] >> 28) & 0x7)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18680
#else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18681
#define	IPVER(ip6h)	((((uint32_t *)ip6h)[0] >> 4) & 0x7)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18682
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18683
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18684
#define	PREP_NEW_MULTIDATA() {			\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18685
	mmd = NULL;				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18686
	md_mp = md_hbuf = NULL;			\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18687
	cur_hdr_off = 0;			\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18688
	max_pld = tcp->tcp_mdt_max_pld;		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18689
	pbuf_idx = pbuf_idx_nxt = -1;		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18690
	add_buffer = B_TRUE;			\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18691
	zcopy = B_FALSE;			\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18692
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18693
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18694
#define	PREP_NEW_PBUF() {			\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18695
	md_pbuf = md_pbuf_nxt = NULL;		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18696
	pbuf_idx = pbuf_idx_nxt = -1;		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18697
	cur_pld_off = 0;			\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18698
	first_snxt = *snxt;			\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18699
	ASSERT(*tail_unsent > 0);		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18700
	base_pld_off = MBLKL(*xmit_tail) - *tail_unsent; \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18701
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18702
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18703
	ASSERT(mdt_thres >= mss);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18704
	ASSERT(*usable > 0 && *usable > mdt_thres);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18705
	ASSERT(tcp->tcp_state == TCPS_ESTABLISHED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18706
	ASSERT(!TCP_IS_DETACHED(tcp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18707
	ASSERT(tcp->tcp_valid_bits == 0 ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18708
	    tcp->tcp_valid_bits == TCP_FSS_VALID);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18709
	ASSERT((tcp->tcp_ipversion == IPV4_VERSION &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18710
	    tcp->tcp_ip_hdr_len == IP_SIMPLE_HDR_LENGTH) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18711
	    (tcp->tcp_ipversion == IPV6_VERSION &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18712
	    tcp->tcp_ip_hdr_len == IPV6_HDR_LEN));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18713
	ASSERT(tcp->tcp_connp != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18714
	ASSERT(CONN_IS_MD_FASTPATH(tcp->tcp_connp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18715
	ASSERT(!CONN_IPSEC_OUT_ENCAPSULATED(tcp->tcp_connp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18716
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18717
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18718
	 * Note that tcp will only declare at most 2 payload spans per
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18719
	 * packet, which is much lower than the maximum allowable number
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18720
	 * of packet spans per Multidata.  For this reason, we use the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18721
	 * privately declared and smaller descriptor info structure, in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18722
	 * order to save some stack space.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18723
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18724
	pkt_info = (pdescinfo_t *)&tcp_pkt_info;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18725
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18726
	af = (tcp->tcp_ipversion == IPV4_VERSION) ? AF_INET : AF_INET6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18727
	if (af == AF_INET) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18728
		dst = tcp->tcp_ipha->ipha_dst;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18729
		src = tcp->tcp_ipha->ipha_src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18730
		ASSERT(!CLASSD(dst));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18731
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18732
	ASSERT(af == AF_INET ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18733
	    !IN6_IS_ADDR_MULTICAST(&tcp->tcp_ip6h->ip6_dst));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18734
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18735
	obsegs = obbytes = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18736
	num_burst_seg = tcp->tcp_snd_burst;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18737
	md_mp_head = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18738
	PREP_NEW_MULTIDATA();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18739
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18740
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18741
	 * Before we go on further, make sure there is an IRE that we can
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18742
	 * use, and that the ILL supports MDT.  Otherwise, there's no point
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18743
	 * in proceeding any further, and we should just hand everything
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18744
	 * off to the legacy path.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18745
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18746
	mutex_enter(&tcp->tcp_connp->conn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18747
	ire = tcp->tcp_connp->conn_ire_cache;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18748
	ASSERT(!(tcp->tcp_connp->conn_state_flags & CONN_INCIPIENT));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18749
	if (ire != NULL && ((af == AF_INET && ire->ire_addr == dst) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18750
	    (af == AF_INET6 && IN6_ARE_ADDR_EQUAL(&ire->ire_addr_v6,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18751
	    &tcp->tcp_ip6h->ip6_dst))) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18752
	    !(ire->ire_marks & IRE_MARK_CONDEMNED)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18753
		IRE_REFHOLD(ire);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18754
		mutex_exit(&tcp->tcp_connp->conn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18755
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18756
		boolean_t cached = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18757
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18758
		/* force a recheck later on */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18759
		tcp->tcp_ire_ill_check_done = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18760
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18761
		TCP_DBGSTAT(tcp_ire_null1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18762
		tcp->tcp_connp->conn_ire_cache = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18763
		mutex_exit(&tcp->tcp_connp->conn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18764
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18765
		/* Release the old ire */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18766
		if (ire != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18767
			IRE_REFRELE_NOTR(ire);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18768
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18769
		ire = (af == AF_INET) ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18770
		    ire_cache_lookup(dst, tcp->tcp_connp->conn_zoneid) :
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18771
		    ire_cache_lookup_v6(&tcp->tcp_ip6h->ip6_dst,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18772
		    tcp->tcp_connp->conn_zoneid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18773
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18774
		if (ire == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18775
			TCP_STAT(tcp_ire_null);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18776
			goto legacy_send_no_md;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18777
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18778
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18779
		IRE_REFHOLD_NOTR(ire);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18780
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18781
		 * Since we are inside the squeue, there cannot be another
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18782
		 * thread in TCP trying to set the conn_ire_cache now. The
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18783
		 * check for IRE_MARK_CONDEMNED ensures that an interface
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18784
		 * unplumb thread has not yet started cleaning up the conns.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18785
		 * Hence we don't need to grab the conn lock.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18786
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18787
		if (!(tcp->tcp_connp->conn_state_flags & CONN_CLOSING)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18788
			rw_enter(&ire->ire_bucket->irb_lock, RW_READER);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18789
			if (!(ire->ire_marks & IRE_MARK_CONDEMNED)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18790
				tcp->tcp_connp->conn_ire_cache = ire;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18791
				cached = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18792
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18793
			rw_exit(&ire->ire_bucket->irb_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18794
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18795
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18796
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18797
		 * We can continue to use the ire but since it was not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18798
		 * cached, we should drop the extra reference.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18799
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18800
		if (!cached)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18801
			IRE_REFRELE_NOTR(ire);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18802
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18803
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18804
	ASSERT(ire != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18805
	ASSERT(af != AF_INET || ire->ire_ipversion == IPV4_VERSION);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18806
	ASSERT(af == AF_INET || !IN6_IS_ADDR_V4MAPPED(&(ire->ire_addr_v6)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18807
	ASSERT(af == AF_INET || ire->ire_nce != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18808
	ASSERT(!(ire->ire_type & IRE_BROADCAST));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18809
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18810
	 * If we do support loopback for MDT (which requires modifications
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18811
	 * to the receiving paths), the following assertions should go away,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18812
	 * and we would be sending the Multidata to loopback conn later on.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18813
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18814
	ASSERT(!IRE_IS_LOCAL(ire));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18815
	ASSERT(ire->ire_stq != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18816
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18817
	ill = ire_to_ill(ire);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18818
	ASSERT(ill != NULL);
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 18819
	ASSERT(!ILL_MDT_CAPABLE(ill) || ill->ill_mdt_capab != NULL);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18820
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18821
	if (!tcp->tcp_ire_ill_check_done) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18822
		tcp_ire_ill_check(tcp, ire, ill, B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18823
		tcp->tcp_ire_ill_check_done = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18824
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18825
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18826
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18827
	 * If the underlying interface conditions have changed, or if the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18828
	 * new interface does not support MDT, go back to legacy path.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18829
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18830
	if (!ILL_MDT_USABLE(ill) || (ire->ire_flags & RTF_MULTIRT) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18831
		/* don't go through this path anymore for this connection */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18832
		TCP_STAT(tcp_mdt_conn_halted2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18833
		tcp->tcp_mdt = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18834
		ip1dbg(("tcp_multisend: disabling MDT for connp %p on "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18835
		    "interface %s\n", (void *)tcp->tcp_connp, ill->ill_name));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18836
		/* IRE will be released prior to returning */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18837
		goto legacy_send_no_md;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18838
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18839
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18840
	if (ill->ill_capabilities & ILL_CAPAB_ZEROCOPY)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18841
		zc_cap = ill->ill_zerocopy_capab;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18842
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18843
	/* go to legacy path if interface doesn't support zerocopy */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18844
	if (tcp->tcp_snd_zcopy_aware && do_tcpzcopy != 2 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18845
	    (zc_cap == NULL || zc_cap->ill_zerocopy_flags == 0)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18846
		/* IRE will be released prior to returning */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18847
		goto legacy_send_no_md;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18848
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18849
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18850
	/* does the interface support hardware checksum offload? */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18851
	hwcksum_flags = 0;
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 18852
	if (ILL_HCKSUM_CAPABLE(ill) &&
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18853
	    (ill->ill_hcksum_capab->ill_hcksum_txflags &
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 18854
	    (HCKSUM_INET_FULL_V4 | HCKSUM_INET_FULL_V6 | HCKSUM_INET_PARTIAL |
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 18855
	    HCKSUM_IPHDRCKSUM)) && dohwcksum) {
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18856
		if (ill->ill_hcksum_capab->ill_hcksum_txflags &
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18857
		    HCKSUM_IPHDRCKSUM)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18858
			hwcksum_flags = HCK_IPV4_HDRCKSUM;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18859
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18860
		if (ill->ill_hcksum_capab->ill_hcksum_txflags &
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 18861
		    (HCKSUM_INET_FULL_V4 | HCKSUM_INET_FULL_V6))
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18862
			hwcksum_flags |= HCK_FULLCKSUM;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18863
		else if (ill->ill_hcksum_capab->ill_hcksum_txflags &
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18864
		    HCKSUM_INET_PARTIAL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18865
			hwcksum_flags |= HCK_PARTIALCKSUM;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18866
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18867
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18868
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18869
	 * Each header fragment consists of the leading extra space,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18870
	 * followed by the TCP/IP header, and the trailing extra space.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18871
	 * We make sure that each header fragment begins on a 32-bit
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18872
	 * aligned memory address (tcp_mdt_hdr_head is already 32-bit
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18873
	 * aligned in tcp_mdt_update).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18874
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18875
	hdr_frag_sz = roundup((tcp->tcp_mdt_hdr_head + tcp_hdr_len +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18876
	    tcp->tcp_mdt_hdr_tail), 4);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18877
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18878
	/* are we starting from the beginning of data block? */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18879
	if (*tail_unsent == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18880
		*xmit_tail = (*xmit_tail)->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18881
		ASSERT((uintptr_t)MBLKL(*xmit_tail) <= (uintptr_t)INT_MAX);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18882
		*tail_unsent = (int)MBLKL(*xmit_tail);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18883
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18884
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18885
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18886
	 * Here we create one or more Multidata messages, each made up of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18887
	 * one header buffer and up to N payload buffers.  This entire
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18888
	 * operation is done within two loops:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18889
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18890
	 * The outer loop mostly deals with creating the Multidata message,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18891
	 * as well as the header buffer that gets added to it.  It also
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18892
	 * links the Multidata messages together such that all of them can
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18893
	 * be sent down to the lower layer in a single putnext call; this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18894
	 * linking behavior depends on the tcp_mdt_chain tunable.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18895
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18896
	 * The inner loop takes an existing Multidata message, and adds
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18897
	 * one or more (up to tcp_mdt_max_pld) payload buffers to it.  It
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18898
	 * packetizes those buffers by filling up the corresponding header
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18899
	 * buffer fragments with the proper IP and TCP headers, and by
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18900
	 * describing the layout of each packet in the packet descriptors
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18901
	 * that get added to the Multidata.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18902
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18903
	do {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18904
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18905
		 * If usable send window is too small, or data blocks in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18906
		 * transmit list are smaller than our threshold (i.e. app
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18907
		 * performs large writes followed by small ones), we hand
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18908
		 * off the control over to the legacy path.  Note that we'll
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18909
		 * get back the control once it encounters a large block.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18910
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18911
		if (*usable < mss || (*tail_unsent <= mdt_thres &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18912
		    (*xmit_tail)->b_cont != NULL &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18913
		    MBLKL((*xmit_tail)->b_cont) <= mdt_thres)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18914
			/* send down what we've got so far */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18915
			if (md_mp_head != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18916
				tcp_multisend_data(tcp, ire, ill, md_mp_head,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18917
				    obsegs, obbytes, &rconfirm);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18918
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18919
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18920
			 * Pass control over to tcp_send(), but tell it to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18921
			 * return to us once a large-size transmission is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18922
			 * possible.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18923
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18924
			TCP_STAT(tcp_mdt_legacy_small);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18925
			if ((err = tcp_send(q, tcp, mss, tcp_hdr_len,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18926
			    tcp_tcp_hdr_len, num_sack_blk, usable, snxt,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18927
			    tail_unsent, xmit_tail, local_time,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18928
			    mdt_thres)) <= 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18929
				/* burst count reached, or alloc failed */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18930
				IRE_REFRELE(ire);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18931
				return (err);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18932
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18933
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18934
			/* tcp_send() may have sent everything, so check */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18935
			if (*usable <= 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18936
				IRE_REFRELE(ire);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18937
				return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18938
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18939
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18940
			TCP_STAT(tcp_mdt_legacy_ret);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18941
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18942
			 * We may have delivered the Multidata, so make sure
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18943
			 * to re-initialize before the next round.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18944
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18945
			md_mp_head = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18946
			obsegs = obbytes = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18947
			num_burst_seg = tcp->tcp_snd_burst;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18948
			PREP_NEW_MULTIDATA();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18949
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18950
			/* are we starting from the beginning of data block? */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18951
			if (*tail_unsent == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18952
				*xmit_tail = (*xmit_tail)->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18953
				ASSERT((uintptr_t)MBLKL(*xmit_tail) <=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18954
				    (uintptr_t)INT_MAX);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18955
				*tail_unsent = (int)MBLKL(*xmit_tail);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18956
			}
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
		 * max_pld limits the number of mblks in tcp's transmit
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18961
		 * queue that can be added to a Multidata message.  Once
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18962
		 * this counter reaches zero, no more additional mblks
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18963
		 * can be added to it.  What happens afterwards depends
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18964
		 * on whether or not we are set to chain the Multidata
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18965
		 * messages.  If we are to link them together, reset
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18966
		 * max_pld to its original value (tcp_mdt_max_pld) and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18967
		 * prepare to create a new Multidata message which will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18968
		 * get linked to md_mp_head.  Else, leave it alone and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18969
		 * let the inner loop break on its own.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18970
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18971
		if (tcp_mdt_chain && max_pld == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18972
			PREP_NEW_MULTIDATA();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18973
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18974
		/* adding a payload buffer; re-initialize values */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18975
		if (add_buffer)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18976
			PREP_NEW_PBUF();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18977
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18978
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18979
		 * If we don't have a Multidata, either because we just
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18980
		 * (re)entered this outer loop, or after we branched off
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18981
		 * to tcp_send above, setup the Multidata and header
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18982
		 * buffer to be used.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18983
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18984
		if (md_mp == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18985
			int md_hbuflen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18986
			uint32_t start, stuff;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18987
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18988
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18989
			 * Calculate Multidata header buffer size large enough
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18990
			 * to hold all of the headers that can possibly be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18991
			 * sent at this moment.  We'd rather over-estimate
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18992
			 * the size than running out of space; this is okay
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18993
			 * since this buffer is small anyway.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18994
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18995
			md_hbuflen = (howmany(*usable, mss) + 1) * hdr_frag_sz;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18996
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18997
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18998
			 * Start and stuff offset for partial hardware
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18999
			 * checksum offload; these are currently for IPv4.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19000
			 * For full checksum offload, they are set to zero.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19001
			 */
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19002
			if ((hwcksum_flags & HCK_PARTIALCKSUM)) {
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19003
				if (af == AF_INET) {
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19004
					start = IP_SIMPLE_HDR_LENGTH;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19005
					stuff = IP_SIMPLE_HDR_LENGTH +
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19006
					    TCP_CHECKSUM_OFFSET;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19007
				} else {
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19008
					start = IPV6_HDR_LEN;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19009
					stuff = IPV6_HDR_LEN +
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19010
					    TCP_CHECKSUM_OFFSET;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19011
				}
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19012
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19013
				start = stuff = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19014
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19015
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19016
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19017
			 * Create the header buffer, Multidata, as well as
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19018
			 * any necessary attributes (destination address,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19019
			 * SAP and hardware checksum offload) that should
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19020
			 * be associated with the Multidata message.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19021
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19022
			ASSERT(cur_hdr_off == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19023
			if ((md_hbuf = allocb(md_hbuflen, BPRI_HI)) == NULL ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19024
			    ((md_hbuf->b_wptr += md_hbuflen),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19025
			    (mmd = mmd_alloc(md_hbuf, &md_mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19026
			    KM_NOSLEEP)) == NULL) || (tcp_mdt_add_attrs(mmd,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19027
			    /* fastpath mblk */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19028
			    (af == AF_INET) ? ire->ire_dlureq_mp :
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19029
			    ire->ire_nce->nce_res_mp,
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19030
			    /* hardware checksum enabled */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19031
			    (hwcksum_flags & (HCK_FULLCKSUM|HCK_PARTIALCKSUM)),
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19032
			    /* hardware checksum offsets */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19033
			    start, stuff, 0,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19034
			    /* hardware checksum flag */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19035
			    hwcksum_flags) != 0)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19036
legacy_send:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19037
				if (md_mp != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19038
					/* Unlink message from the chain */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19039
					if (md_mp_head != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19040
						err = (intptr_t)rmvb(md_mp_head,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19041
						    md_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19042
						/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19043
						 * We can't assert that rmvb
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19044
						 * did not return -1, since we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19045
						 * may get here before linkb
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19046
						 * happens.  We do, however,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19047
						 * check if we just removed the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19048
						 * only element in the list.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19049
						 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19050
						if (err == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19051
							md_mp_head = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19052
					}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19053
					/* md_hbuf gets freed automatically */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19054
					TCP_STAT(tcp_mdt_discarded);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19055
					freeb(md_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19056
				} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19057
					/* Either allocb or mmd_alloc failed */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19058
					TCP_STAT(tcp_mdt_allocfail);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19059
					if (md_hbuf != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19060
						freeb(md_hbuf);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19061
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19062
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19063
				/* send down what we've got so far */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19064
				if (md_mp_head != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19065
					tcp_multisend_data(tcp, ire, ill,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19066
					    md_mp_head, obsegs, obbytes,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19067
					    &rconfirm);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19068
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19069
legacy_send_no_md:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19070
				if (ire != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19071
					IRE_REFRELE(ire);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19072
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19073
				 * Too bad; let the legacy path handle this.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19074
				 * We specify INT_MAX for the threshold, since
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19075
				 * we gave up with the Multidata processings
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19076
				 * and let the old path have it all.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19077
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19078
				TCP_STAT(tcp_mdt_legacy_all);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19079
				return (tcp_send(q, tcp, mss, tcp_hdr_len,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19080
				    tcp_tcp_hdr_len, num_sack_blk, usable,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19081
				    snxt, tail_unsent, xmit_tail, local_time,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19082
				    INT_MAX));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19083
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19084
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19085
			/* link to any existing ones, if applicable */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19086
			TCP_STAT(tcp_mdt_allocd);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19087
			if (md_mp_head == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19088
				md_mp_head = md_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19089
			} else if (tcp_mdt_chain) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19090
				TCP_STAT(tcp_mdt_linked);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19091
				linkb(md_mp_head, md_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19092
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19093
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19094
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19095
		ASSERT(md_mp_head != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19096
		ASSERT(tcp_mdt_chain || md_mp_head->b_cont == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19097
		ASSERT(md_mp != NULL && mmd != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19098
		ASSERT(md_hbuf != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19099
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19100
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19101
		 * Packetize the transmittable portion of the data block;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19102
		 * each data block is essentially added to the Multidata
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19103
		 * as a payload buffer.  We also deal with adding more
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19104
		 * than one payload buffers, which happens when the remaining
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19105
		 * packetized portion of the current payload buffer is less
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19106
		 * than MSS, while the next data block in transmit queue
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19107
		 * has enough data to make up for one.  This "spillover"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19108
		 * case essentially creates a split-packet, where portions
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19109
		 * of the packet's payload fragments may span across two
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19110
		 * virtually discontiguous address blocks.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19111
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19112
		seg_len = mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19113
		do {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19114
			len = seg_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19115
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19116
			ASSERT(len > 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19117
			ASSERT(max_pld >= 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19118
			ASSERT(!add_buffer || cur_pld_off == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19119
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19120
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19121
			 * First time around for this payload buffer; note
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19122
			 * in the case of a spillover, the following has
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19123
			 * been done prior to adding the split-packet
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19124
			 * descriptor to Multidata, and we don't want to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19125
			 * repeat the process.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19126
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19127
			if (add_buffer) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19128
				ASSERT(mmd != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19129
				ASSERT(md_pbuf == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19130
				ASSERT(md_pbuf_nxt == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19131
				ASSERT(pbuf_idx == -1 && pbuf_idx_nxt == -1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19132
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19133
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19134
				 * Have we reached the limit?  We'd get to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19135
				 * this case when we're not chaining the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19136
				 * Multidata messages together, and since
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19137
				 * we're done, terminate this loop.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19138
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19139
				if (max_pld == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19140
					break; /* done */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19141
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19142
				if ((md_pbuf = dupb(*xmit_tail)) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19143
					TCP_STAT(tcp_mdt_allocfail);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19144
					goto legacy_send; /* out_of_mem */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19145
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19146
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19147
				if (IS_VMLOANED_MBLK(md_pbuf) && !zcopy &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19148
				    zc_cap != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19149
					if (!ip_md_zcopy_attr(mmd, NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19150
					    zc_cap->ill_zerocopy_flags)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19151
						freeb(md_pbuf);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19152
						TCP_STAT(tcp_mdt_allocfail);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19153
						/* out_of_mem */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19154
						goto legacy_send;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19155
					}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19156
					zcopy = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19157
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19158
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19159
				md_pbuf->b_rptr += base_pld_off;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19160
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19161
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19162
				 * Add a payload buffer to the Multidata; this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19163
				 * operation must not fail, or otherwise our
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19164
				 * logic in this routine is broken.  There
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19165
				 * is no memory allocation done by the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19166
				 * routine, so any returned failure simply
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19167
				 * tells us that we've done something wrong.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19168
				 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19169
				 * A failure tells us that either we're adding
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19170
				 * the same payload buffer more than once, or
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19171
				 * we're trying to add more buffers than
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19172
				 * allowed (max_pld calculation is wrong).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19173
				 * None of the above cases should happen, and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19174
				 * we panic because either there's horrible
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19175
				 * heap corruption, and/or programming mistake.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19176
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19177
				pbuf_idx = mmd_addpldbuf(mmd, md_pbuf);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19178
				if (pbuf_idx < 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19179
					cmn_err(CE_PANIC, "tcp_multisend: "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19180
					    "payload buffer logic error "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19181
					    "detected for tcp %p mmd %p "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19182
					    "pbuf %p (%d)\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19183
					    (void *)tcp, (void *)mmd,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19184
					    (void *)md_pbuf, pbuf_idx);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19185
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19186
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19187
				ASSERT(max_pld > 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19188
				--max_pld;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19189
				add_buffer = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19190
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19191
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19192
			ASSERT(md_mp_head != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19193
			ASSERT(md_pbuf != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19194
			ASSERT(md_pbuf_nxt == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19195
			ASSERT(pbuf_idx != -1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19196
			ASSERT(pbuf_idx_nxt == -1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19197
			ASSERT(*usable > 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19198
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19199
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19200
			 * We spillover to the next payload buffer only
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19201
			 * if all of the following is true:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19202
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19203
			 *   1. There is not enough data on the current
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19204
			 *	payload buffer to make up `len',
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19205
			 *   2. We are allowed to send `len',
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19206
			 *   3. The next payload buffer length is large
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19207
			 *	enough to accomodate `spill'.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19208
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19209
			if ((spill = len - *tail_unsent) > 0 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19210
			    *usable >= len &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19211
			    MBLKL((*xmit_tail)->b_cont) >= spill &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19212
			    max_pld > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19213
				md_pbuf_nxt = dupb((*xmit_tail)->b_cont);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19214
				if (md_pbuf_nxt == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19215
					TCP_STAT(tcp_mdt_allocfail);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19216
					goto legacy_send; /* out_of_mem */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19217
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19218
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19219
				if (IS_VMLOANED_MBLK(md_pbuf_nxt) && !zcopy &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19220
				    zc_cap != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19221
					if (!ip_md_zcopy_attr(mmd, NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19222
					    zc_cap->ill_zerocopy_flags)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19223
						freeb(md_pbuf_nxt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19224
						TCP_STAT(tcp_mdt_allocfail);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19225
						/* out_of_mem */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19226
						goto legacy_send;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19227
					}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19228
					zcopy = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19229
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19230
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19231
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19232
				 * See comments above on the first call to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19233
				 * mmd_addpldbuf for explanation on the panic.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19234
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19235
				pbuf_idx_nxt = mmd_addpldbuf(mmd, md_pbuf_nxt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19236
				if (pbuf_idx_nxt < 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19237
					panic("tcp_multisend: "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19238
					    "next payload buffer logic error "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19239
					    "detected for tcp %p mmd %p "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19240
					    "pbuf %p (%d)\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19241
					    (void *)tcp, (void *)mmd,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19242
					    (void *)md_pbuf_nxt, pbuf_idx_nxt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19243
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19244
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19245
				ASSERT(max_pld > 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19246
				--max_pld;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19247
			} else if (spill > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19248
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19249
				 * If there's a spillover, but the following
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19250
				 * xmit_tail couldn't give us enough octets
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19251
				 * to reach "len", then stop the current
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19252
				 * Multidata creation and let the legacy
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19253
				 * tcp_send() path take over.  We don't want
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19254
				 * to send the tiny segment as part of this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19255
				 * Multidata for performance reasons; instead,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19256
				 * we let the legacy path deal with grouping
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19257
				 * it with the subsequent small mblks.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19258
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19259
				if (*usable >= len &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19260
				    MBLKL((*xmit_tail)->b_cont) < spill) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19261
					max_pld = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19262
					break;	/* done */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19263
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19264
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19265
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19266
				 * We can't spillover, and we are near
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19267
				 * the end of the current payload buffer,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19268
				 * so send what's left.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19269
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19270
				ASSERT(*tail_unsent > 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19271
				len = *tail_unsent;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19272
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19273
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19274
			/* tail_unsent is negated if there is a spillover */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19275
			*tail_unsent -= len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19276
			*usable -= len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19277
			ASSERT(*usable >= 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19278
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19279
			if (*usable < mss)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19280
				seg_len = *usable;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19281
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19282
			 * Sender SWS avoidance; see comments in tcp_send();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19283
			 * everything else is the same, except that we only
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19284
			 * do this here if there is no more data to be sent
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19285
			 * following the current xmit_tail.  We don't check
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19286
			 * for 1-byte urgent data because we shouldn't get
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19287
			 * here if TCP_URG_VALID is set.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19288
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19289
			if (*usable > 0 && *usable < mss &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19290
			    ((md_pbuf_nxt == NULL &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19291
			    (*xmit_tail)->b_cont == NULL) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19292
			    (md_pbuf_nxt != NULL &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19293
			    (*xmit_tail)->b_cont->b_cont == NULL)) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19294
			    seg_len < (tcp->tcp_max_swnd >> 1) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19295
			    (tcp->tcp_unsent -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19296
			    ((*snxt + len) - tcp->tcp_snxt)) > seg_len &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19297
			    !tcp->tcp_zero_win_probe) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19298
				if ((*snxt + len) == tcp->tcp_snxt &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19299
				    (*snxt + len) == tcp->tcp_suna) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19300
					TCP_TIMER_RESTART(tcp, tcp->tcp_rto);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19301
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19302
				done = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19303
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19304
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19305
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19306
			 * Prime pump for IP's checksumming on our behalf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19307
			 * include the adjustment for a source route if any.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19308
			 * Do this only for software/partial hardware checksum
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19309
			 * offload, as this field gets zeroed out later for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19310
			 * the full hardware checksum offload case.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19311
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19312
			if (!(hwcksum_flags & HCK_FULLCKSUM)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19313
				cksum = len + tcp_tcp_hdr_len + tcp->tcp_sum;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19314
				cksum = (cksum >> 16) + (cksum & 0xFFFF);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19315
				U16_TO_ABE16(cksum, tcp->tcp_tcph->th_sum);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19316
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19317
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19318
			U32_TO_ABE32(*snxt, tcp->tcp_tcph->th_seq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19319
			*snxt += len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19320
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19321
			tcp->tcp_tcph->th_flags[0] = TH_ACK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19322
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19323
			 * We set the PUSH bit only if TCP has no more buffered
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19324
			 * data to be transmitted (or if sender SWS avoidance
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19325
			 * takes place), as opposed to setting it for every
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19326
			 * last packet in the burst.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19327
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19328
			if (done ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19329
			    (tcp->tcp_unsent - (*snxt - tcp->tcp_snxt)) == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19330
				tcp->tcp_tcph->th_flags[0] |= TH_PUSH;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19331
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19332
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19333
			 * Set FIN bit if this is our last segment; snxt
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19334
			 * already includes its length, and it will not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19335
			 * be adjusted after this point.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19336
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19337
			if (tcp->tcp_valid_bits == TCP_FSS_VALID &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19338
			    *snxt == tcp->tcp_fss) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19339
				if (!tcp->tcp_fin_acked) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19340
					tcp->tcp_tcph->th_flags[0] |= TH_FIN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19341
					BUMP_MIB(&tcp_mib, tcpOutControl);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19342
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19343
				if (!tcp->tcp_fin_sent) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19344
					tcp->tcp_fin_sent = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19345
					/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19346
					 * tcp state must be ESTABLISHED
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19347
					 * in order for us to get here in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19348
					 * the first place.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19349
					 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19350
					tcp->tcp_state = TCPS_FIN_WAIT_1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19351
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19352
					/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19353
					 * Upon returning from this routine,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19354
					 * tcp_wput_data() will set tcp_snxt
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19355
					 * to be equal to snxt + tcp_fin_sent.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19356
					 * This is essentially the same as
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19357
					 * setting it to tcp_fss + 1.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19358
					 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19359
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19360
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19361
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19362
			tcp->tcp_last_sent_len = (ushort_t)len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19363
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19364
			len += tcp_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19365
			if (tcp->tcp_ipversion == IPV4_VERSION)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19366
				tcp->tcp_ipha->ipha_length = htons(len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19367
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19368
				tcp->tcp_ip6h->ip6_plen = htons(len -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19369
				    ((char *)&tcp->tcp_ip6h[1] -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19370
				    tcp->tcp_iphc));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19371
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19372
			pkt_info->flags = (PDESC_HBUF_REF | PDESC_PBUF_REF);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19373
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19374
			/* setup header fragment */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19375
			PDESC_HDR_ADD(pkt_info,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19376
			    md_hbuf->b_rptr + cur_hdr_off,	/* base */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19377
			    tcp->tcp_mdt_hdr_head,		/* head room */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19378
			    tcp_hdr_len,			/* len */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19379
			    tcp->tcp_mdt_hdr_tail);		/* tail room */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19380
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19381
			ASSERT(pkt_info->hdr_lim - pkt_info->hdr_base ==
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19382
			    hdr_frag_sz);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19383
			ASSERT(MBLKIN(md_hbuf,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19384
			    (pkt_info->hdr_base - md_hbuf->b_rptr),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19385
			    PDESC_HDRSIZE(pkt_info)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19386
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19387
			/* setup first payload fragment */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19388
			PDESC_PLD_INIT(pkt_info);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19389
			PDESC_PLD_SPAN_ADD(pkt_info,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19390
			    pbuf_idx,				/* index */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19391
			    md_pbuf->b_rptr + cur_pld_off,	/* start */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19392
			    tcp->tcp_last_sent_len);		/* len */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19393
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19394
			/* create a split-packet in case of a spillover */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19395
			if (md_pbuf_nxt != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19396
				ASSERT(spill > 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19397
				ASSERT(pbuf_idx_nxt > pbuf_idx);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19398
				ASSERT(!add_buffer);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19399
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19400
				md_pbuf = md_pbuf_nxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19401
				md_pbuf_nxt = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19402
				pbuf_idx = pbuf_idx_nxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19403
				pbuf_idx_nxt = -1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19404
				cur_pld_off = spill;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19405
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19406
				/* trim out first payload fragment */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19407
				PDESC_PLD_SPAN_TRIM(pkt_info, 0, spill);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19408
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19409
				/* setup second payload fragment */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19410
				PDESC_PLD_SPAN_ADD(pkt_info,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19411
				    pbuf_idx,			/* index */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19412
				    md_pbuf->b_rptr,		/* start */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19413
				    spill);			/* len */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19414
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19415
				if ((*xmit_tail)->b_next == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19416
					/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19417
					 * Store the lbolt used for RTT
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19418
					 * estimation. We can only record one
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19419
					 * timestamp per mblk so we do it when
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19420
					 * we reach the end of the payload
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19421
					 * buffer.  Also we only take a new
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19422
					 * timestamp sample when the previous
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19423
					 * timed data from the same mblk has
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19424
					 * been ack'ed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19425
					 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19426
					(*xmit_tail)->b_prev = local_time;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19427
					(*xmit_tail)->b_next =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19428
					    (mblk_t *)(uintptr_t)first_snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19429
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19430
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19431
				first_snxt = *snxt - spill;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19432
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19433
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19434
				 * Advance xmit_tail; usable could be 0 by
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19435
				 * the time we got here, but we made sure
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19436
				 * above that we would only spillover to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19437
				 * the next data block if usable includes
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19438
				 * the spilled-over amount prior to the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19439
				 * subtraction.  Therefore, we are sure
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19440
				 * that xmit_tail->b_cont can't be NULL.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19441
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19442
				ASSERT((*xmit_tail)->b_cont != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19443
				*xmit_tail = (*xmit_tail)->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19444
				ASSERT((uintptr_t)MBLKL(*xmit_tail) <=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19445
				    (uintptr_t)INT_MAX);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19446
				*tail_unsent = (int)MBLKL(*xmit_tail) - spill;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19447
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19448
				cur_pld_off += tcp->tcp_last_sent_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19449
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19450
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19451
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19452
			 * Fill in the header using the template header, and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19453
			 * add options such as time-stamp, ECN and/or SACK,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19454
			 * as needed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19455
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19456
			tcp_fill_header(tcp, pkt_info->hdr_rptr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19457
			    (clock_t)local_time, num_sack_blk);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19458
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19459
			/* take care of some IP header businesses */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19460
			if (af == AF_INET) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19461
				ipha = (ipha_t *)pkt_info->hdr_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19462
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19463
				ASSERT(OK_32PTR((uchar_t *)ipha));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19464
				ASSERT(PDESC_HDRL(pkt_info) >=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19465
				    IP_SIMPLE_HDR_LENGTH);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19466
				ASSERT(ipha->ipha_version_and_hdr_length ==
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19467
				    IP_SIMPLE_HDR_VERSION);
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
				 * Assign ident value for current packet; see
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19471
				 * related comments in ip_wput_ire() about the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19472
				 * contract private interface with clustering
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19473
				 * group.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19474
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19475
				clusterwide = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19476
				if (cl_inet_ipident != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19477
					ASSERT(cl_inet_isclusterwide != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19478
					if ((*cl_inet_isclusterwide)(IPPROTO_IP,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19479
					    AF_INET,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19480
					    (uint8_t *)(uintptr_t)src)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19481
						ipha->ipha_ident =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19482
						    (*cl_inet_ipident)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19483
						    (IPPROTO_IP, AF_INET,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19484
						    (uint8_t *)(uintptr_t)src,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19485
						    (uint8_t *)(uintptr_t)dst);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19486
						clusterwide = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19487
					}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19488
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19489
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19490
				if (!clusterwide) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19491
					ipha->ipha_ident = (uint16_t)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19492
					    atomic_add_32_nv(
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19493
						&ire->ire_ident, 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19494
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19495
#ifndef _BIG_ENDIAN
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19496
				ipha->ipha_ident = (ipha->ipha_ident << 8) |
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19497
				    (ipha->ipha_ident >> 8);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19498
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19499
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19500
				ip6h = (ip6_t *)pkt_info->hdr_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19501
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19502
				ASSERT(OK_32PTR((uchar_t *)ip6h));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19503
				ASSERT(IPVER(ip6h) == IPV6_VERSION);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19504
				ASSERT(ip6h->ip6_nxt == IPPROTO_TCP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19505
				ASSERT(PDESC_HDRL(pkt_info) >=
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19506
				    (IPV6_HDR_LEN + TCP_CHECKSUM_OFFSET +
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19507
				    TCP_CHECKSUM_SIZE));
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19508
				ASSERT(tcp->tcp_ipversion == IPV6_VERSION);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19509
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19510
				if (tcp->tcp_ip_forward_progress) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19511
					rconfirm = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19512
					tcp->tcp_ip_forward_progress = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19513
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19514
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19515
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19516
			/* at least one payload span, and at most two */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19517
			ASSERT(pkt_info->pld_cnt > 0 && pkt_info->pld_cnt < 3);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19518
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19519
			/* add the packet descriptor to Multidata */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19520
			if ((pkt = mmd_addpdesc(mmd, pkt_info, &err,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19521
			    KM_NOSLEEP)) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19522
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19523
				 * Any failure other than ENOMEM indicates
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19524
				 * that we have passed in invalid pkt_info
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19525
				 * or parameters to mmd_addpdesc, which must
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19526
				 * not happen.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19527
				 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19528
				 * EINVAL is a result of failure on boundary
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19529
				 * checks against the pkt_info contents.  It
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19530
				 * should not happen, and we panic because
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19531
				 * either there's horrible heap corruption,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19532
				 * and/or programming mistake.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19533
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19534
				if (err != ENOMEM) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19535
					cmn_err(CE_PANIC, "tcp_multisend: "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19536
					    "pdesc logic error detected for "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19537
					    "tcp %p mmd %p pinfo %p (%d)\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19538
					    (void *)tcp, (void *)mmd,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19539
					    (void *)pkt_info, err);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19540
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19541
				TCP_STAT(tcp_mdt_addpdescfail);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19542
				goto legacy_send; /* out_of_mem */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19543
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19544
			ASSERT(pkt != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19545
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19546
			/* calculate IP header and TCP checksums */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19547
			if (af == AF_INET) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19548
				/* calculate pseudo-header checksum */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19549
				cksum = (dst >> 16) + (dst & 0xFFFF) +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19550
				    (src >> 16) + (src & 0xFFFF);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19551
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19552
				/* offset for TCP header checksum */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19553
				up = IPH_TCPH_CHECKSUMP(ipha,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19554
				    IP_SIMPLE_HDR_LENGTH);
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19555
			} else {
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19556
				up = (uint16_t *)&ip6h->ip6_src;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19557
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19558
				/* calculate pseudo-header checksum */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19559
				cksum = up[0] + up[1] + up[2] + up[3] +
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19560
				    up[4] + up[5] + up[6] + up[7] +
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19561
				    up[8] + up[9] + up[10] + up[11] +
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19562
				    up[12] + up[13] + up[14] + up[15];
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19563
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19564
				/* Fold the initial sum */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19565
				cksum = (cksum & 0xffff) + (cksum >> 16);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19566
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19567
				up = (uint16_t *)(((uchar_t *)ip6h) +
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19568
				    IPV6_HDR_LEN + TCP_CHECKSUM_OFFSET);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19569
			}
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19570
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19571
			if (hwcksum_flags & HCK_FULLCKSUM) {
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19572
				/* clear checksum field for hardware */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19573
				*up = 0;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19574
			} else if (hwcksum_flags & HCK_PARTIALCKSUM) {
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19575
				uint32_t sum;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19576
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19577
				/* pseudo-header checksumming */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19578
				sum = *up + cksum + IP_TCP_CSUM_COMP;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19579
				sum = (sum & 0xFFFF) + (sum >> 16);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19580
				*up = (sum & 0xFFFF) + (sum >> 16);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19581
			} else {
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19582
				/* software checksumming */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19583
				TCP_STAT(tcp_out_sw_cksum);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19584
				TCP_STAT_UPDATE(tcp_out_sw_cksum_bytes,
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19585
				    tcp->tcp_hdr_len + tcp->tcp_last_sent_len);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19586
				*up = IP_MD_CSUM(pkt, tcp->tcp_ip_hdr_len,
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19587
				    cksum + IP_TCP_CSUM_COMP);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19588
				if (*up == 0)
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19589
					*up = 0xFFFF;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19590
			}
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19591
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19592
			/* IPv4 header checksum */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19593
			if (af == AF_INET) {
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19594
				ipha->ipha_fragment_offset_and_flags |=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19595
				    (uint32_t)htons(ire->ire_frag_flag);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19596
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19597
				if (hwcksum_flags & HCK_IPV4_HDRCKSUM) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19598
					ipha->ipha_hdr_checksum = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19599
				} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19600
					IP_HDR_CKSUM(ipha, cksum,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19601
					    ((uint32_t *)ipha)[0],
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19602
					    ((uint16_t *)ipha)[4]);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19603
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19604
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19605
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19606
			/* advance header offset */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19607
			cur_hdr_off += hdr_frag_sz;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19608
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19609
			obbytes += tcp->tcp_last_sent_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19610
			++obsegs;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19611
		} while (!done && *usable > 0 && --num_burst_seg > 0 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19612
		    *tail_unsent > 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19613
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19614
		if ((*xmit_tail)->b_next == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19615
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19616
			 * Store the lbolt used for RTT estimation. We can only
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19617
			 * record one timestamp per mblk so we do it when we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19618
			 * reach the end of the payload buffer. Also we only
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19619
			 * take a new timestamp sample when the previous timed
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19620
			 * data from the same mblk has been ack'ed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19621
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19622
			(*xmit_tail)->b_prev = local_time;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19623
			(*xmit_tail)->b_next = (mblk_t *)(uintptr_t)first_snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19624
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19625
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19626
		ASSERT(*tail_unsent >= 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19627
		if (*tail_unsent > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19628
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19629
			 * We got here because we broke out of the above
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19630
			 * loop due to of one of the following cases:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19631
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19632
			 *   1. len < adjusted MSS (i.e. small),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19633
			 *   2. Sender SWS avoidance,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19634
			 *   3. max_pld is zero.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19635
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19636
			 * We are done for this Multidata, so trim our
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19637
			 * last payload buffer (if any) accordingly.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19638
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19639
			if (md_pbuf != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19640
				md_pbuf->b_wptr -= *tail_unsent;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19641
		} else if (*usable > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19642
			*xmit_tail = (*xmit_tail)->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19643
			ASSERT((uintptr_t)MBLKL(*xmit_tail) <=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19644
			    (uintptr_t)INT_MAX);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19645
			*tail_unsent = (int)MBLKL(*xmit_tail);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19646
			add_buffer = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19647
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19648
	} while (!done && *usable > 0 && num_burst_seg > 0 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19649
	    (tcp_mdt_chain || max_pld > 0));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19650
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19651
	/* send everything down */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19652
	tcp_multisend_data(tcp, ire, ill, md_mp_head, obsegs, obbytes,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19653
	    &rconfirm);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19654
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19655
#undef PREP_NEW_MULTIDATA
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19656
#undef PREP_NEW_PBUF
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19657
#undef IPVER
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19658
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19659
	IRE_REFRELE(ire);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19660
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19661
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19662
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19663
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19664
 * A wrapper function for sending one or more Multidata messages down to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19665
 * the module below ip; this routine does not release the reference of the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19666
 * IRE (caller does that).  This routine is analogous to tcp_send_data().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19667
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19668
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19669
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
 19670
    const uint_t obsegs, const uint_t obbytes, boolean_t *rconfirm)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19671
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19672
	uint64_t delta;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19673
	nce_t *nce;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19674
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19675
	ASSERT(ire != NULL && ill != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19676
	ASSERT(ire->ire_stq != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19677
	ASSERT(md_mp_head != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19678
	ASSERT(rconfirm != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19679
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19680
	/* adjust MIBs and IRE timestamp */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19681
	TCP_RECORD_TRACE(tcp, md_mp_head, TCP_TRACE_SEND_PKT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19682
	tcp->tcp_obsegs += obsegs;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19683
	UPDATE_MIB(&tcp_mib, tcpOutDataSegs, obsegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19684
	UPDATE_MIB(&tcp_mib, tcpOutDataBytes, obbytes);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19685
	TCP_STAT_UPDATE(tcp_mdt_pkt_out, obsegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19686
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19687
	if (tcp->tcp_ipversion == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19688
		TCP_STAT_UPDATE(tcp_mdt_pkt_out_v4, obsegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19689
		UPDATE_MIB(&ip_mib, ipOutRequests, obsegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19690
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19691
		TCP_STAT_UPDATE(tcp_mdt_pkt_out_v6, obsegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19692
		UPDATE_MIB(&ip6_mib, ipv6OutRequests, obsegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19693
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19694
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19695
	ire->ire_ob_pkt_count += obsegs;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19696
	if (ire->ire_ipif != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19697
		atomic_add_32(&ire->ire_ipif->ipif_ob_pkt_count, obsegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19698
	ire->ire_last_used_time = lbolt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19699
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19700
	/* send it down */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19701
	putnext(ire->ire_stq, md_mp_head);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19702
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19703
	/* we're done for TCP/IPv4 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19704
	if (tcp->tcp_ipversion == IPV4_VERSION)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19705
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19706
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19707
	nce = ire->ire_nce;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19708
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19709
	ASSERT(nce != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19710
	ASSERT(!(nce->nce_flags & (NCE_F_NONUD|NCE_F_PERMANENT)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19711
	ASSERT(nce->nce_state != ND_INCOMPLETE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19712
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19713
	/* reachability confirmation? */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19714
	if (*rconfirm) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19715
		nce->nce_last = TICK_TO_MSEC(lbolt64);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19716
		if (nce->nce_state != ND_REACHABLE) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19717
			mutex_enter(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19718
			nce->nce_state = ND_REACHABLE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19719
			nce->nce_pcnt = ND_MAX_UNICAST_SOLICIT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19720
			mutex_exit(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19721
			(void) untimeout(nce->nce_timeout_id);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19722
			if (ip_debug > 2) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19723
				/* ip1dbg */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19724
				pr_addr_dbg("tcp_multisend_data: state "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19725
				    "for %s changed to REACHABLE\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19726
				    AF_INET6, &ire->ire_addr_v6);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19727
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19728
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19729
		/* reset transport reachability confirmation */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19730
		*rconfirm = B_FALSE;
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
	delta =  TICK_TO_MSEC(lbolt64) - nce->nce_last;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19734
	ip1dbg(("tcp_multisend_data: delta = %" PRId64
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19735
	    " ill_reachable_time = %d \n", delta, ill->ill_reachable_time));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19736
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19737
	if (delta > (uint64_t)ill->ill_reachable_time) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19738
		mutex_enter(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19739
		switch (nce->nce_state) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19740
		case ND_REACHABLE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19741
		case ND_STALE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19742
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19743
			 * ND_REACHABLE is identical to ND_STALE in this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19744
			 * specific case. If reachable time has expired for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19745
			 * this neighbor (delta is greater than reachable
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19746
			 * time), conceptually, the neighbor cache is no
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19747
			 * longer in REACHABLE state, but already in STALE
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19748
			 * state.  So the correct transition here is to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19749
			 * ND_DELAY.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19750
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19751
			nce->nce_state = ND_DELAY;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19752
			mutex_exit(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19753
			NDP_RESTART_TIMER(nce, delay_first_probe_time);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19754
			if (ip_debug > 3) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19755
				/* ip2dbg */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19756
				pr_addr_dbg("tcp_multisend_data: state "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19757
				    "for %s changed to DELAY\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19758
				    AF_INET6, &ire->ire_addr_v6);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19759
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19760
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19761
		case ND_DELAY:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19762
		case ND_PROBE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19763
			mutex_exit(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19764
			/* Timers have already started */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19765
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19766
		case ND_UNREACHABLE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19767
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19768
			 * ndp timer has detected that this nce is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19769
			 * unreachable and initiated deleting this nce
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19770
			 * and all its associated IREs. This is a race
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19771
			 * where we found the ire before it was deleted
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19772
			 * and have just sent out a packet using this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19773
			 * unreachable nce.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19774
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19775
			mutex_exit(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19776
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19777
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19778
			ASSERT(0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19779
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19780
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19781
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19782
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19783
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19784
 * tcp_send() is called by tcp_wput_data() for non-Multidata transmission
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19785
 * scheme, and returns one of the following:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19786
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19787
 * -1 = failed allocation.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19788
 *  0 = success; burst count reached, or usable send window is too small,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19789
 *      and that we'd rather wait until later before sending again.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19790
 *  1 = success; we are called from tcp_multisend(), and both usable send
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19791
 *      window and tail_unsent are greater than the MDT threshold, and thus
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19792
 *      Multidata Transmit should be used instead.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19793
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19794
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19795
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
 19796
    const int tcp_tcp_hdr_len, const int num_sack_blk, int *usable,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19797
    uint_t *snxt, int *tail_unsent, mblk_t **xmit_tail, mblk_t *local_time,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19798
    const int mdt_thres)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19799
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19800
	int num_burst_seg = tcp->tcp_snd_burst;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19801
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19802
	for (;;) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19803
		struct datab	*db;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19804
		tcph_t		*tcph;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19805
		uint32_t	sum;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19806
		mblk_t		*mp, *mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19807
		uchar_t		*rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19808
		int		len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19809
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19810
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19811
		 * If we're called by tcp_multisend(), and the amount of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19812
		 * sendable data as well as the size of current xmit_tail
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19813
		 * is beyond the MDT threshold, return to the caller and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19814
		 * let the large data transmit be done using MDT.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19815
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19816
		if (*usable > 0 && *usable > mdt_thres &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19817
		    (*tail_unsent > mdt_thres || (*tail_unsent == 0 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19818
		    MBLKL((*xmit_tail)->b_cont) > mdt_thres))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19819
			ASSERT(tcp->tcp_mdt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19820
			return (1);	/* success; do large send */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19821
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19822
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19823
		if (num_burst_seg-- == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19824
			break;		/* success; burst count reached */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19825
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19826
		len = mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19827
		if (len > *usable) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19828
			len = *usable;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19829
			if (len <= 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19830
				/* Terminate the loop */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19831
				break;	/* success; too small */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19832
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19833
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19834
			 * Sender silly-window avoidance.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19835
			 * Ignore this if we are going to send a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19836
			 * zero window probe out.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19837
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19838
			 * TODO: force data into microscopic window?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19839
			 *	==> (!pushed || (unsent > usable))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19840
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19841
			if (len < (tcp->tcp_max_swnd >> 1) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19842
			    (tcp->tcp_unsent - (*snxt - tcp->tcp_snxt)) > len &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19843
			    !((tcp->tcp_valid_bits & TCP_URG_VALID) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19844
			    len == 1) && (! tcp->tcp_zero_win_probe)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19845
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19846
				 * If the retransmit timer is not running
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19847
				 * we start it so that we will retransmit
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19848
				 * in the case when the the receiver has
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19849
				 * decremented the window.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19850
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19851
				if (*snxt == tcp->tcp_snxt &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19852
				    *snxt == tcp->tcp_suna) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19853
					/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19854
					 * We are not supposed to send
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19855
					 * anything.  So let's wait a little
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19856
					 * bit longer before breaking SWS
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19857
					 * avoidance.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19858
					 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19859
					 * What should the value be?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19860
					 * Suggestion: MAX(init rexmit time,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19861
					 * tcp->tcp_rto)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19862
					 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19863
					TCP_TIMER_RESTART(tcp, tcp->tcp_rto);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19864
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19865
				break;	/* success; too small */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19866
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19867
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19868
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19869
		tcph = tcp->tcp_tcph;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19870
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19871
		*usable -= len; /* Approximate - can be adjusted later */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19872
		if (*usable > 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19873
			tcph->th_flags[0] = TH_ACK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19874
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19875
			tcph->th_flags[0] = (TH_ACK | TH_PUSH);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19876
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19877
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19878
		 * Prime pump for IP's checksumming on our behalf
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19879
		 * Include the adjustment for a source route if any.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19880
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19881
		sum = len + tcp_tcp_hdr_len + tcp->tcp_sum;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19882
		sum = (sum >> 16) + (sum & 0xFFFF);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19883
		U16_TO_ABE16(sum, tcph->th_sum);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19884
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19885
		U32_TO_ABE32(*snxt, tcph->th_seq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19886
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19887
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19888
		 * Branch off to tcp_xmit_mp() if any of the VALID bits is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19889
		 * set.  For the case when TCP_FSS_VALID is the only valid
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19890
		 * bit (normal active close), branch off only when we think
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19891
		 * that the FIN flag needs to be set.  Note for this case,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19892
		 * that (snxt + len) may not reflect the actual seg_len,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19893
		 * as len may be further reduced in tcp_xmit_mp().  If len
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19894
		 * gets modified, we will end up here again.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19895
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19896
		if (tcp->tcp_valid_bits != 0 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19897
		    (tcp->tcp_valid_bits != TCP_FSS_VALID ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19898
		    ((*snxt + len) == tcp->tcp_fss))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19899
			uchar_t		*prev_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19900
			uint32_t	prev_snxt = tcp->tcp_snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19901
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19902
			if (*tail_unsent == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19903
				ASSERT((*xmit_tail)->b_cont != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19904
				*xmit_tail = (*xmit_tail)->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19905
				prev_rptr = (*xmit_tail)->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19906
				*tail_unsent = (int)((*xmit_tail)->b_wptr -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19907
				    (*xmit_tail)->b_rptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19908
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19909
				prev_rptr = (*xmit_tail)->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19910
				(*xmit_tail)->b_rptr = (*xmit_tail)->b_wptr -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19911
				    *tail_unsent;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19912
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19913
			mp = tcp_xmit_mp(tcp, *xmit_tail, len, NULL, NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19914
			    *snxt, B_FALSE, (uint32_t *)&len, B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19915
			/* Restore tcp_snxt so we get amount sent right. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19916
			tcp->tcp_snxt = prev_snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19917
			if (prev_rptr == (*xmit_tail)->b_rptr) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19918
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19919
				 * If the previous timestamp is still in use,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19920
				 * don't stomp on it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19921
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19922
				if ((*xmit_tail)->b_next == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19923
					(*xmit_tail)->b_prev = local_time;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19924
					(*xmit_tail)->b_next =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19925
					    (mblk_t *)(uintptr_t)(*snxt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19926
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19927
			} else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19928
				(*xmit_tail)->b_rptr = prev_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19929
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19930
			if (mp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19931
				return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19932
			mp1 = mp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19933
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19934
			tcp->tcp_last_sent_len = (ushort_t)len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19935
			while (mp1->b_cont) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19936
				*xmit_tail = (*xmit_tail)->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19937
				(*xmit_tail)->b_prev = local_time;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19938
				(*xmit_tail)->b_next =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19939
				    (mblk_t *)(uintptr_t)(*snxt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19940
				mp1 = mp1->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19941
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19942
			*snxt += len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19943
			*tail_unsent = (*xmit_tail)->b_wptr - mp1->b_wptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19944
			BUMP_LOCAL(tcp->tcp_obsegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19945
			BUMP_MIB(&tcp_mib, tcpOutDataSegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19946
			UPDATE_MIB(&tcp_mib, tcpOutDataBytes, len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19947
			TCP_RECORD_TRACE(tcp, mp, TCP_TRACE_SEND_PKT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19948
			tcp_send_data(tcp, q, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19949
			continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19950
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19951
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19952
		*snxt += len;	/* Adjust later if we don't send all of len */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19953
		BUMP_MIB(&tcp_mib, tcpOutDataSegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19954
		UPDATE_MIB(&tcp_mib, tcpOutDataBytes, len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19955
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19956
		if (*tail_unsent) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19957
			/* Are the bytes above us in flight? */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19958
			rptr = (*xmit_tail)->b_wptr - *tail_unsent;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19959
			if (rptr != (*xmit_tail)->b_rptr) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19960
				*tail_unsent -= len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19961
				tcp->tcp_last_sent_len = (ushort_t)len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19962
				len += tcp_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19963
				if (tcp->tcp_ipversion == IPV4_VERSION)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19964
					tcp->tcp_ipha->ipha_length = htons(len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19965
				else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19966
					tcp->tcp_ip6h->ip6_plen =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19967
					    htons(len -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19968
					    ((char *)&tcp->tcp_ip6h[1] -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19969
					    tcp->tcp_iphc));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19970
				mp = dupb(*xmit_tail);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19971
				if (!mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19972
					return (-1);	/* out_of_mem */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19973
				mp->b_rptr = rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19974
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19975
				 * If the old timestamp is no longer in use,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19976
				 * sample a new timestamp now.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19977
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19978
				if ((*xmit_tail)->b_next == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19979
					(*xmit_tail)->b_prev = local_time;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19980
					(*xmit_tail)->b_next =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19981
					    (mblk_t *)(uintptr_t)(*snxt-len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19982
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19983
				goto must_alloc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19984
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19985
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19986
			*xmit_tail = (*xmit_tail)->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19987
			ASSERT((uintptr_t)((*xmit_tail)->b_wptr -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19988
			    (*xmit_tail)->b_rptr) <= (uintptr_t)INT_MAX);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19989
			*tail_unsent = (int)((*xmit_tail)->b_wptr -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19990
			    (*xmit_tail)->b_rptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19991
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19992
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19993
		(*xmit_tail)->b_prev = local_time;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19994
		(*xmit_tail)->b_next = (mblk_t *)(uintptr_t)(*snxt - len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19995
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19996
		*tail_unsent -= len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19997
		tcp->tcp_last_sent_len = (ushort_t)len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19998
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19999
		len += tcp_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20000
		if (tcp->tcp_ipversion == IPV4_VERSION)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20001
			tcp->tcp_ipha->ipha_length = htons(len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20002
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20003
			tcp->tcp_ip6h->ip6_plen = htons(len -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20004
			    ((char *)&tcp->tcp_ip6h[1] - tcp->tcp_iphc));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20005
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20006
		mp = dupb(*xmit_tail);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20007
		if (!mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20008
			return (-1);	/* out_of_mem */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20009
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20010
		len = tcp_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20011
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20012
		 * There are four reasons to allocate a new hdr mblk:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20013
		 *  1) The bytes above us are in use by another packet
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20014
		 *  2) We don't have good alignment
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20015
		 *  3) The mblk is being shared
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20016
		 *  4) We don't have enough room for a header
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20017
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20018
		rptr = mp->b_rptr - len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20019
		if (!OK_32PTR(rptr) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20020
		    ((db = mp->b_datap), db->db_ref != 2) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20021
		    rptr < db->db_base) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20022
			/* NOTE: we assume allocb returns an OK_32PTR */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20023
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20024
		must_alloc:;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20025
			mp1 = allocb(tcp->tcp_ip_hdr_len + TCP_MAX_HDR_LENGTH +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20026
			    tcp_wroff_xtra, BPRI_MED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20027
			if (!mp1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20028
				freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20029
				return (-1);	/* out_of_mem */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20030
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20031
			mp1->b_cont = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20032
			mp = mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20033
			/* Leave room for Link Level header */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20034
			len = tcp_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20035
			rptr = &mp->b_rptr[tcp_wroff_xtra];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20036
			mp->b_wptr = &rptr[len];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20037
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20038
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20039
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20040
		 * Fill in the header using the template header, and add
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20041
		 * options such as time-stamp, ECN and/or SACK, as needed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20042
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20043
		tcp_fill_header(tcp, rptr, (clock_t)local_time, num_sack_blk);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20044
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20045
		mp->b_rptr = rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20046
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20047
		if (*tail_unsent) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20048
			int spill = *tail_unsent;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20049
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20050
			mp1 = mp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20051
			if (!mp1)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20052
				mp1 = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20053
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20054
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20055
			 * If we're a little short, tack on more mblks until
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20056
			 * there is no more spillover.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20057
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20058
			while (spill < 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20059
				mblk_t *nmp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20060
				int nmpsz;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20061
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20062
				nmp = (*xmit_tail)->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20063
				nmpsz = MBLKL(nmp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20064
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20065
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20066
				 * Excess data in mblk; can we split it?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20067
				 * If MDT is enabled for the connection,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20068
				 * keep on splitting as this is a transient
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20069
				 * send path.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20070
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20071
				if (!tcp->tcp_mdt && (spill + nmpsz > 0)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20072
					/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20073
					 * Don't split if stream head was
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20074
					 * told to break up larger writes
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20075
					 * into smaller ones.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20076
					 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20077
					if (tcp->tcp_maxpsz > 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20078
						break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20079
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20080
					/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20081
					 * Next mblk is less than SMSS/2
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20082
					 * rounded up to nearest 64-byte;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20083
					 * let it get sent as part of the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20084
					 * next segment.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20085
					 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20086
					if (tcp->tcp_localnet &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20087
					    !tcp->tcp_cork &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20088
					    (nmpsz < roundup((mss >> 1), 64)))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20089
						break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20090
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20091
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20092
				*xmit_tail = nmp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20093
				ASSERT((uintptr_t)nmpsz <= (uintptr_t)INT_MAX);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20094
				/* Stash for rtt use later */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20095
				(*xmit_tail)->b_prev = local_time;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20096
				(*xmit_tail)->b_next =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20097
				    (mblk_t *)(uintptr_t)(*snxt - len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20098
				mp1->b_cont = dupb(*xmit_tail);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20099
				mp1 = mp1->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20100
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20101
				spill += nmpsz;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20102
				if (mp1 == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20103
					*tail_unsent = spill;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20104
					freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20105
					return (-1);	/* out_of_mem */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20106
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20107
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20108
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20109
			/* Trim back any surplus on the last mblk */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20110
			if (spill >= 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20111
				mp1->b_wptr -= spill;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20112
				*tail_unsent = spill;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20113
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20114
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20115
				 * We did not send everything we could in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20116
				 * order to remain within the b_cont limit.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20117
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20118
				*usable -= spill;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20119
				*snxt += spill;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20120
				tcp->tcp_last_sent_len += spill;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20121
				UPDATE_MIB(&tcp_mib, tcpOutDataBytes, spill);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20122
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20123
				 * Adjust the checksum
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20124
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20125
				tcph = (tcph_t *)(rptr + tcp->tcp_ip_hdr_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20126
				sum += spill;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20127
				sum = (sum >> 16) + (sum & 0xFFFF);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20128
				U16_TO_ABE16(sum, tcph->th_sum);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20129
				if (tcp->tcp_ipversion == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20130
					sum = ntohs(
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20131
					    ((ipha_t *)rptr)->ipha_length) +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20132
					    spill;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20133
					((ipha_t *)rptr)->ipha_length =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20134
					    htons(sum);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20135
				} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20136
					sum = ntohs(
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20137
					    ((ip6_t *)rptr)->ip6_plen) +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20138
					    spill;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20139
					((ip6_t *)rptr)->ip6_plen =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20140
					    htons(sum);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20141
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20142
				*tail_unsent = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20143
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20144
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20145
		if (tcp->tcp_ip_forward_progress) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20146
			ASSERT(tcp->tcp_ipversion == IPV6_VERSION);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20147
			*(uint32_t *)mp->b_rptr  |= IP_FORWARD_PROG;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20148
			tcp->tcp_ip_forward_progress = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20149
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20150
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20151
		TCP_RECORD_TRACE(tcp, mp, TCP_TRACE_SEND_PKT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20152
		tcp_send_data(tcp, q, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20153
		BUMP_LOCAL(tcp->tcp_obsegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20154
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20155
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20156
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20157
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20158
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20159
/* Unlink and return any mblk that looks like it contains a MDT info */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20160
static mblk_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20161
tcp_mdt_info_mp(mblk_t *mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20162
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20163
	mblk_t	*prev_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20164
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20165
	for (;;) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20166
		prev_mp = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20167
		/* no more to process? */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20168
		if ((mp = mp->b_cont) == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20169
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20170
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20171
		switch (DB_TYPE(mp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20172
		case M_CTL:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20173
			if (*(uint32_t *)mp->b_rptr != MDT_IOC_INFO_UPDATE)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20174
				continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20175
			ASSERT(prev_mp != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20176
			prev_mp->b_cont = mp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20177
			mp->b_cont = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20178
			return (mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20179
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20180
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20181
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20182
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20183
	return (mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20184
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20185
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20186
/* MDT info update routine, called when IP notifies us about MDT */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20187
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20188
tcp_mdt_update(tcp_t *tcp, ill_mdt_capab_t *mdt_capab, boolean_t first)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20189
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20190
	boolean_t prev_state;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20191
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20192
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20193
	 * IP is telling us to abort MDT on this connection?  We know
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20194
	 * this because the capability is only turned off when IP
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20195
	 * encounters some pathological cases, e.g. link-layer change
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20196
	 * where the new driver doesn't support MDT, or in situation
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20197
	 * where MDT usage on the link-layer has been switched off.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20198
	 * IP would not have sent us the initial MDT_IOC_INFO_UPDATE
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20199
	 * if the link-layer doesn't support MDT, and if it does, it
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20200
	 * will indicate that the feature is to be turned on.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20201
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20202
	prev_state = tcp->tcp_mdt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20203
	tcp->tcp_mdt = (mdt_capab->ill_mdt_on != 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20204
	if (!tcp->tcp_mdt && !first) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20205
		TCP_STAT(tcp_mdt_conn_halted3);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20206
		ip1dbg(("tcp_mdt_update: disabling MDT for connp %p\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20207
		    (void *)tcp->tcp_connp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20208
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20209
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20210
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20211
	 * We currently only support MDT on simple TCP/{IPv4,IPv6},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20212
	 * so disable MDT otherwise.  The checks are done here
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20213
	 * and in tcp_wput_data().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20214
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20215
	if (tcp->tcp_mdt &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20216
	    (tcp->tcp_ipversion == IPV4_VERSION &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20217
	    tcp->tcp_ip_hdr_len != IP_SIMPLE_HDR_LENGTH) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20218
	    (tcp->tcp_ipversion == IPV6_VERSION &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20219
	    tcp->tcp_ip_hdr_len != IPV6_HDR_LEN))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20220
		tcp->tcp_mdt = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20221
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20222
	if (tcp->tcp_mdt) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20223
		if (mdt_capab->ill_mdt_version != MDT_VERSION_2) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20224
			cmn_err(CE_NOTE, "tcp_mdt_update: unknown MDT "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20225
			    "version (%d), expected version is %d",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20226
			    mdt_capab->ill_mdt_version, MDT_VERSION_2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20227
			tcp->tcp_mdt = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20228
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20229
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20230
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20231
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20232
		 * We need the driver to be able to handle at least three
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20233
		 * spans per packet in order for tcp MDT to be utilized.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20234
		 * The first is for the header portion, while the rest are
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20235
		 * needed to handle a packet that straddles across two
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20236
		 * virtually non-contiguous buffers; a typical tcp packet
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20237
		 * therefore consists of only two spans.  Note that we take
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20238
		 * a zero as "don't care".
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20239
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20240
		if (mdt_capab->ill_mdt_span_limit > 0 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20241
		    mdt_capab->ill_mdt_span_limit < 3) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20242
			tcp->tcp_mdt = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20243
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20244
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20245
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20246
		/* a zero means driver wants default value */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20247
		tcp->tcp_mdt_max_pld = MIN(mdt_capab->ill_mdt_max_pld,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20248
		    tcp_mdt_max_pbufs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20249
		if (tcp->tcp_mdt_max_pld == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20250
			tcp->tcp_mdt_max_pld = tcp_mdt_max_pbufs;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20251
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20252
		/* ensure 32-bit alignment */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20253
		tcp->tcp_mdt_hdr_head = roundup(MAX(tcp_mdt_hdr_head_min,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20254
		    mdt_capab->ill_mdt_hdr_head), 4);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20255
		tcp->tcp_mdt_hdr_tail = roundup(MAX(tcp_mdt_hdr_tail_min,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20256
		    mdt_capab->ill_mdt_hdr_tail), 4);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20257
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20258
		if (!first && !prev_state) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20259
			TCP_STAT(tcp_mdt_conn_resumed2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20260
			ip1dbg(("tcp_mdt_update: reenabling MDT for connp %p\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20261
			    (void *)tcp->tcp_connp));
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
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20265
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20266
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20267
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
 20268
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20269
	conn_t *connp = tcp->tcp_connp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20270
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20271
	ASSERT(ire != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20272
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20273
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20274
	 * We may be in the fastpath here, and although we essentially do
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20275
	 * similar checks as in ip_bind_connected{_v6}/ip_mdinfo_return,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20276
	 * we try to keep things as brief as possible.  After all, these
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20277
	 * are only best-effort checks, and we do more thorough ones prior
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20278
	 * to calling tcp_multisend().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20279
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20280
	if (ip_multidata_outbound && check_mdt &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20281
	    !(ire->ire_type & (IRE_LOCAL | IRE_LOOPBACK)) &&
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20282
	    ill != NULL && ILL_MDT_CAPABLE(ill) &&
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20283
	    !CONN_IPSEC_OUT_ENCAPSULATED(connp) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20284
	    !(ire->ire_flags & RTF_MULTIRT) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20285
	    !IPP_ENABLED(IPP_LOCAL_OUT) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20286
	    CONN_IS_MD_FASTPATH(connp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20287
		/* Remember the result */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20288
		connp->conn_mdt_ok = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20289
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20290
		ASSERT(ill->ill_mdt_capab != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20291
		if (!ill->ill_mdt_capab->ill_mdt_on) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20292
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20293
			 * If MDT has been previously turned off in the past,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20294
			 * and we currently can do MDT (due to IPQoS policy
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20295
			 * removal, etc.) then enable it for this interface.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20296
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20297
			ill->ill_mdt_capab->ill_mdt_on = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20298
			ip1dbg(("tcp_ire_ill_check: connp %p enables MDT for "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20299
			    "interface %s\n", (void *)connp, ill->ill_name));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20300
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20301
		tcp_mdt_update(tcp, ill->ill_mdt_capab, B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20302
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20303
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20304
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20305
	 * The goal is to reduce the number of generated tcp segments by
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20306
	 * setting the maxpsz multiplier to 0; this will have an affect on
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20307
	 * tcp_maxpsz_set().  With this behavior, tcp will pack more data
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20308
	 * into each packet, up to SMSS bytes.  Doing this reduces the number
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20309
	 * of outbound segments and incoming ACKs, thus allowing for better
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20310
	 * network and system performance.  In contrast the legacy behavior
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20311
	 * may result in sending less than SMSS size, because the last mblk
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20312
	 * for some packets may have more data than needed to make up SMSS,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20313
	 * and the legacy code refused to "split" it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20314
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20315
	 * We apply the new behavior on following situations:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20316
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20317
	 *   1) Loopback connections,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20318
	 *   2) Connections in which the remote peer is not on local subnet,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20319
	 *   3) Local subnet connections over the bge interface (see below).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20320
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20321
	 * Ideally, we would like this behavior to apply for interfaces other
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20322
	 * than bge.  However, doing so would negatively impact drivers which
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20323
	 * perform dynamic mapping and unmapping of DMA resources, which are
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20324
	 * increased by setting the maxpsz multiplier to 0 (more mblks per
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20325
	 * packet will be generated by tcp).  The bge driver does not suffer
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20326
	 * from this, as it copies the mblks into pre-mapped buffers, and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20327
	 * therefore does not require more I/O resources than before.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20328
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20329
	 * Otherwise, this behavior is present on all network interfaces when
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20330
	 * the destination endpoint is non-local, since reducing the number
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20331
	 * of packets in general is good for the network.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20332
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20333
	 * TODO We need to remove this hard-coded conditional for bge once
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20334
	 *	a better "self-tuning" mechanism, or a way to comprehend
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20335
	 *	the driver transmit strategy is devised.  Until the solution
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20336
	 *	is found and well understood, we live with this hack.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20337
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20338
	if (!tcp_static_maxpsz &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20339
	    (tcp->tcp_loopback || !tcp->tcp_localnet ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20340
	    (ill->ill_name_length > 3 && bcmp(ill->ill_name, "bge", 3) == 0))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20341
		/* override the default value */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20342
		tcp->tcp_maxpsz = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20343
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20344
		ip3dbg(("tcp_ire_ill_check: connp %p tcp_maxpsz %d on "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20345
		    "interface %s\n", (void *)connp, tcp->tcp_maxpsz,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20346
		    ill != NULL ? ill->ill_name : ipif_loopback_name));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20347
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20348
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20349
	/* set the stream head parameters accordingly */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20350
	(void) tcp_maxpsz_set(tcp, B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20351
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20352
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20353
/* tcp_wput_flush is called by tcp_wput_nondata to handle M_FLUSH messages. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20354
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20355
tcp_wput_flush(tcp_t *tcp, mblk_t *mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20356
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20357
	uchar_t	fval = *mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20358
	mblk_t	*tail;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20359
	queue_t	*q = tcp->tcp_wq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20360
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20361
	/* TODO: How should flush interact with urgent data? */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20362
	if ((fval & FLUSHW) && tcp->tcp_xmit_head &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20363
	    !(tcp->tcp_valid_bits & TCP_URG_VALID)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20364
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20365
		 * Flush only data that has not yet been put on the wire.  If
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20366
		 * we flush data that we have already transmitted, life, as we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20367
		 * know it, may come to an end.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20368
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20369
		tail = tcp->tcp_xmit_tail;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20370
		tail->b_wptr -= tcp->tcp_xmit_tail_unsent;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20371
		tcp->tcp_xmit_tail_unsent = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20372
		tcp->tcp_unsent = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20373
		if (tail->b_wptr != tail->b_rptr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20374
			tail = tail->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20375
		if (tail) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20376
			mblk_t **excess = &tcp->tcp_xmit_head;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20377
			for (;;) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20378
				mblk_t *mp1 = *excess;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20379
				if (mp1 == tail)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20380
					break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20381
				tcp->tcp_xmit_tail = mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20382
				tcp->tcp_xmit_last = mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20383
				excess = &mp1->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20384
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20385
			*excess = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20386
			tcp_close_mpp(&tail);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20387
			if (tcp->tcp_snd_zcopy_aware)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20388
				tcp_zcopy_notify(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20389
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20390
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20391
		 * We have no unsent data, so unsent must be less than
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20392
		 * tcp_xmit_lowater, so re-enable flow.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20393
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20394
		if (tcp->tcp_flow_stopped) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20395
			tcp_clrqfull(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20396
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20397
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20398
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20399
	 * TODO: you can't just flush these, you have to increase rwnd for one
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20400
	 * thing.  For another, how should urgent data interact?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20401
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20402
	if (fval & FLUSHR) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20403
		*mp->b_rptr = fval & ~FLUSHW;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20404
		/* XXX */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20405
		qreply(q, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20406
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20407
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20408
	freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20409
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20410
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20411
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20412
 * tcp_wput_iocdata is called by tcp_wput_nondata to handle all M_IOCDATA
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20413
 * messages.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20414
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20415
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20416
tcp_wput_iocdata(tcp_t *tcp, mblk_t *mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20417
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20418
	mblk_t	*mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20419
	STRUCT_HANDLE(strbuf, sb);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20420
	uint16_t port;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20421
	queue_t 	*q = tcp->tcp_wq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20422
	in6_addr_t	v6addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20423
	ipaddr_t	v4addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20424
	uint32_t	flowinfo = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20425
	int		addrlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20426
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20427
	/* Make sure it is one of ours. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20428
	switch (((struct iocblk *)mp->b_rptr)->ioc_cmd) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20429
	case TI_GETMYNAME:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20430
	case TI_GETPEERNAME:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20431
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20432
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20433
		CALL_IP_WPUT(tcp->tcp_connp, q, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20434
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20435
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20436
	switch (mi_copy_state(q, mp, &mp1)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20437
	case -1:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20438
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20439
	case MI_COPY_CASE(MI_COPY_IN, 1):
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20440
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20441
	case MI_COPY_CASE(MI_COPY_OUT, 1):
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20442
		/* Copy out the strbuf. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20443
		mi_copyout(q, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20444
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20445
	case MI_COPY_CASE(MI_COPY_OUT, 2):
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20446
		/* All done. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20447
		mi_copy_done(q, mp, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20448
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20449
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20450
		mi_copy_done(q, mp, EPROTO);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20451
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20452
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20453
	/* Check alignment of the strbuf */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20454
	if (!OK_32PTR(mp1->b_rptr)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20455
		mi_copy_done(q, mp, EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20456
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20457
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20458
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20459
	STRUCT_SET_HANDLE(sb, ((struct iocblk *)mp->b_rptr)->ioc_flag,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20460
	    (void *)mp1->b_rptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20461
	addrlen = tcp->tcp_family == AF_INET ? sizeof (sin_t) : sizeof (sin6_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20462
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20463
	if (STRUCT_FGET(sb, maxlen) < addrlen) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20464
		mi_copy_done(q, mp, EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20465
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20466
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20467
	switch (((struct iocblk *)mp->b_rptr)->ioc_cmd) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20468
	case TI_GETMYNAME:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20469
		if (tcp->tcp_family == AF_INET) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20470
			if (tcp->tcp_ipversion == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20471
				v4addr = tcp->tcp_ipha->ipha_src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20472
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20473
				/* can't return an address in this case */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20474
				v4addr = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20475
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20476
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20477
			/* tcp->tcp_family == AF_INET6 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20478
			if (tcp->tcp_ipversion == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20479
				IN6_IPADDR_TO_V4MAPPED(tcp->tcp_ipha->ipha_src,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20480
				    &v6addr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20481
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20482
				v6addr = tcp->tcp_ip6h->ip6_src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20483
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20484
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20485
		port = tcp->tcp_lport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20486
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20487
	case TI_GETPEERNAME:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20488
		if (tcp->tcp_family == AF_INET) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20489
			if (tcp->tcp_ipversion == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20490
				IN6_V4MAPPED_TO_IPADDR(&tcp->tcp_remote_v6,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20491
				    v4addr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20492
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20493
				/* can't return an address in this case */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20494
				v4addr = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20495
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20496
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20497
			/* tcp->tcp_family == AF_INET6) */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20498
			v6addr = tcp->tcp_remote_v6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20499
			if (tcp->tcp_ipversion == IPV6_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20500
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20501
				 * No flowinfo if tcp->tcp_ipversion is v4.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20502
				 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20503
				 * flowinfo was already initialized to zero
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20504
				 * where it was declared above, so only
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20505
				 * set it if ipversion is v6.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20506
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20507
				flowinfo = tcp->tcp_ip6h->ip6_vcf &
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20508
				    ~IPV6_VERS_AND_FLOW_MASK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20509
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20510
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20511
		port = tcp->tcp_fport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20512
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20513
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20514
		mi_copy_done(q, mp, EPROTO);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20515
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20516
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20517
	mp1 = mi_copyout_alloc(q, mp, STRUCT_FGETP(sb, buf), addrlen, B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20518
	if (!mp1)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20519
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20520
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20521
	if (tcp->tcp_family == AF_INET) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20522
		sin_t *sin;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20523
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20524
		STRUCT_FSET(sb, len, (int)sizeof (sin_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20525
		sin = (sin_t *)mp1->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20526
		mp1->b_wptr = (uchar_t *)&sin[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20527
		*sin = sin_null;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20528
		sin->sin_family = AF_INET;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20529
		sin->sin_addr.s_addr = v4addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20530
		sin->sin_port = port;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20531
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20532
		/* tcp->tcp_family == AF_INET6 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20533
		sin6_t *sin6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20534
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20535
		STRUCT_FSET(sb, len, (int)sizeof (sin6_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20536
		sin6 = (sin6_t *)mp1->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20537
		mp1->b_wptr = (uchar_t *)&sin6[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20538
		*sin6 = sin6_null;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20539
		sin6->sin6_family = AF_INET6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20540
		sin6->sin6_flowinfo = flowinfo;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20541
		sin6->sin6_addr = v6addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20542
		sin6->sin6_port = port;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20543
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20544
	/* Copy out the address */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20545
	mi_copyout(q, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20546
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20547
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20548
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20549
 * tcp_wput_ioctl is called by tcp_wput_nondata() to handle all M_IOCTL
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20550
 * messages.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20551
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20552
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20553
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20554
tcp_wput_ioctl(void *arg, mblk_t *mp, void *arg2)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20555
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20556
	conn_t 	*connp = (conn_t *)arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20557
	tcp_t	*tcp = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20558
	queue_t	*q = tcp->tcp_wq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20559
	struct iocblk	*iocp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20560
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20561
	ASSERT(DB_TYPE(mp) == M_IOCTL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20562
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20563
	 * Try and ASSERT the minimum possible references on the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20564
	 * conn early enough. Since we are executing on write side,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20565
	 * the connection is obviously not detached and that means
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20566
	 * there is a ref each for TCP and IP. Since we are behind
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20567
	 * the squeue, the minimum references needed are 3. If the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20568
	 * conn is in classifier hash list, there should be an
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20569
	 * extra ref for that (we check both the possibilities).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20570
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20571
	ASSERT((connp->conn_fanout != NULL && connp->conn_ref >= 4) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20572
	    (connp->conn_fanout == NULL && connp->conn_ref >= 3));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20573
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20574
	iocp = (struct iocblk *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20575
	switch (iocp->ioc_cmd) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20576
	case TCP_IOC_DEFAULT_Q:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20577
		/* Wants to be the default wq. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20578
		if (secpolicy_net_config(iocp->ioc_cr, B_FALSE) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20579
			iocp->ioc_error = EPERM;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20580
			iocp->ioc_count = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20581
			mp->b_datap->db_type = M_IOCACK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20582
			qreply(q, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20583
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20584
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20585
		tcp_def_q_set(tcp, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20586
		return;
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20587
	case _SIOCSOCKFALLBACK:
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20588
		/*
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20589
		 * Either sockmod is about to be popped and the socket
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20590
		 * would now be treated as a plain stream, or a module
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20591
		 * 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
 20592
		 * side synchronous streams for fused loopback tcp.
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20593
		 * Drain any queued data and disable direct sockfs
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20594
		 * interface from now on.
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20595
		 */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20596
		if (!tcp->tcp_issocket) {
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20597
			DB_TYPE(mp) = M_IOCNAK;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20598
			iocp->ioc_error = EINVAL;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20599
		} else {
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20600
#ifdef	_ILP32
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20601
			tcp->tcp_acceptor_id = (t_uscalar_t)RD(q);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20602
#else
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20603
			tcp->tcp_acceptor_id = tcp->tcp_connp->conn_dev;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20604
#endif
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20605
			/*
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20606
			 * Insert this socket into the acceptor hash.
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20607
			 * We might need it for T_CONN_RES message
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20608
			 */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20609
			tcp_acceptor_hash_insert(tcp->tcp_acceptor_id, tcp);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20610
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20611
			if (tcp->tcp_fused) {
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20612
				/*
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20613
				 * This is a fused loopback tcp; disable
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20614
				 * read-side synchronous streams interface
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20615
				 * and drain any queued data.  It is okay
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20616
				 * to do this for non-synchronous streams
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20617
				 * fused tcp as well.
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20618
				 */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20619
				tcp_fuse_disable_pair(tcp, B_FALSE);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20620
			}
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20621
			tcp->tcp_issocket = B_FALSE;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20622
			TCP_STAT(tcp_sock_fallback);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20623
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20624
			DB_TYPE(mp) = M_IOCACK;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20625
			iocp->ioc_error = 0;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20626
		}
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20627
		iocp->ioc_count = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20628
		iocp->ioc_rval = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20629
		qreply(q, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20630
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20631
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20632
	CALL_IP_WPUT(connp, q, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20633
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20634
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20635
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20636
 * This routine is called by tcp_wput() to handle all TPI requests.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20637
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20638
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20639
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20640
tcp_wput_proto(void *arg, mblk_t *mp, void *arg2)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20641
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20642
	conn_t 	*connp = (conn_t *)arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20643
	tcp_t	*tcp = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20644
	union T_primitives *tprim = (union T_primitives *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20645
	uchar_t *rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20646
	t_scalar_t type;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20647
	int len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20648
	cred_t *cr = DB_CREDDEF(mp, tcp->tcp_cred);
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
	 * Try and ASSERT the minimum possible references on the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20652
	 * conn early enough. Since we are executing on write side,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20653
	 * the connection is obviously not detached and that means
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20654
	 * there is a ref each for TCP and IP. Since we are behind
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20655
	 * the squeue, the minimum references needed are 3. If the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20656
	 * conn is in classifier hash list, there should be an
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20657
	 * extra ref for that (we check both the possibilities).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20658
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20659
	ASSERT((connp->conn_fanout != NULL && connp->conn_ref >= 4) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20660
	    (connp->conn_fanout == NULL && connp->conn_ref >= 3));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20661
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20662
	rptr = mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20663
	ASSERT((uintptr_t)(mp->b_wptr - rptr) <= (uintptr_t)INT_MAX);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20664
	if ((mp->b_wptr - rptr) >= sizeof (t_scalar_t)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20665
		type = ((union T_primitives *)rptr)->type;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20666
		if (type == T_EXDATA_REQ) {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20667
			uint32_t msize = msgdsize(mp->b_cont);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20668
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20669
			len = msize - 1;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20670
			if (len < 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20671
				freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20672
				return;
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
			 * Try to force urgent data out on the wire.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20676
			 * Even if we have unsent data this will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20677
			 * at least send the urgent flag.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20678
			 * XXX does not handle more flag correctly.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20679
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20680
			len += tcp->tcp_unsent;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20681
			len += tcp->tcp_snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20682
			tcp->tcp_urg = len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20683
			tcp->tcp_valid_bits |= TCP_URG_VALID;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20684
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20685
			/* Bypass tcp protocol for fused tcp loopback */
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20686
			if (tcp->tcp_fused && tcp_fuse_output(tcp, mp, msize))
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20687
				return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20688
		} else if (type != T_DATA_REQ) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20689
			goto non_urgent_data;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20690
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20691
		/* TODO: options, flags, ... from user */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20692
		/* Set length to zero for reclamation below */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20693
		tcp_wput_data(tcp, mp->b_cont, B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20694
		freeb(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20695
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20696
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20697
		if (tcp->tcp_debug) {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20698
			(void) strlog(TCP_MOD_ID, 0, 1, SL_ERROR|SL_TRACE,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20699
			    "tcp_wput_proto, dropping one...");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20700
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20701
		freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20702
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20703
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20704
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20705
non_urgent_data:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20706
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20707
	switch ((int)tprim->type) {
898
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 20708
	case T_SSL_PROXY_BIND_REQ:	/* an SSL proxy endpoint bind request */
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 20709
		/*
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 20710
		 * save the kssl_ent_t from the next block, and convert this
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 20711
		 * back to a normal bind_req.
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 20712
		 */
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 20713
		if (mp->b_cont != NULL) {
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 20714
		    ASSERT(MBLKL(mp->b_cont) >= sizeof (kssl_ent_t));
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 20715
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 20716
			if (tcp->tcp_kssl_ent != NULL) {
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 20717
				kssl_release_ent(tcp->tcp_kssl_ent, NULL,
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 20718
				    KSSL_NO_PROXY);
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 20719
				tcp->tcp_kssl_ent = NULL;
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 20720
			}
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 20721
			bcopy(mp->b_cont->b_rptr, &tcp->tcp_kssl_ent,
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 20722
			    sizeof (kssl_ent_t));
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 20723
			kssl_hold_ent(tcp->tcp_kssl_ent);
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 20724
			freemsg(mp->b_cont);
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 20725
			mp->b_cont = NULL;
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 20726
		}
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 20727
		tprim->type = T_BIND_REQ;
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 20728
64b2a371a6bd PSARC/2005/625 Greyhound - Solaris Kernel SSL proxy
kais
parents: 766
diff changeset
 20729
	/* FALLTHROUGH */
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20730
	case O_T_BIND_REQ:	/* bind request */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20731
	case T_BIND_REQ:	/* new semantics bind request */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20732
		tcp_bind(tcp, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20733
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20734
	case T_UNBIND_REQ:	/* unbind request */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20735
		tcp_unbind(tcp, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20736
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20737
	case O_T_CONN_RES:	/* old connection response XXX */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20738
	case T_CONN_RES:	/* connection response */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20739
		tcp_accept(tcp, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20740
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20741
	case T_CONN_REQ:	/* connection request */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20742
		tcp_connect(tcp, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20743
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20744
	case T_DISCON_REQ:	/* disconnect request */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20745
		tcp_disconnect(tcp, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20746
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20747
	case T_CAPABILITY_REQ:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20748
		tcp_capability_req(tcp, mp);	/* capability request */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20749
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20750
	case T_INFO_REQ:	/* information request */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20751
		tcp_info_req(tcp, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20752
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20753
	case T_SVR4_OPTMGMT_REQ:	/* manage options req */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20754
		/* Only IP is allowed to return meaningful value */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20755
		(void) svr4_optcom_req(tcp->tcp_wq, mp, cr, &tcp_opt_obj);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20756
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20757
	case T_OPTMGMT_REQ:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20758
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20759
		 * Note:  no support for snmpcom_req() through new
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20760
		 * T_OPTMGMT_REQ. See comments in ip.c
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20761
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20762
		/* Only IP is allowed to return meaningful value */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20763
		(void) tpi_optcom_req(tcp->tcp_wq, mp, cr, &tcp_opt_obj);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20764
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20765
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20766
	case T_UNITDATA_REQ:	/* unitdata request */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20767
		tcp_err_ack(tcp, mp, TNOTSUPPORT, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20768
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20769
	case T_ORDREL_REQ:	/* orderly release req */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20770
		freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20771
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20772
		if (tcp->tcp_fused)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20773
			tcp_unfuse(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20774
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20775
		if (tcp_xmit_end(tcp) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20776
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20777
			 * We were crossing FINs and got a reset from
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20778
			 * the other side. Just ignore it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20779
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20780
			if (tcp->tcp_debug) {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20781
				(void) strlog(TCP_MOD_ID, 0, 1,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20782
				    SL_ERROR|SL_TRACE,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20783
				    "tcp_wput_proto, T_ORDREL_REQ out of "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20784
				    "state %s",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20785
				    tcp_display(tcp, NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20786
				    DISP_ADDR_AND_PORT));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20787
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20788
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20789
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20790
	case T_ADDR_REQ:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20791
		tcp_addr_req(tcp, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20792
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20793
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20794
		if (tcp->tcp_debug) {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20795
			(void) strlog(TCP_MOD_ID, 0, 1, SL_ERROR|SL_TRACE,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20796
			    "tcp_wput_proto, bogus TPI msg, type %d",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20797
			    tprim->type);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20798
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20799
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20800
		 * We used to M_ERROR.  Sending TNOTSUPPORT gives the user
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20801
		 * to recover.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20802
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20803
		tcp_err_ack(tcp, mp, TNOTSUPPORT, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20804
		break;
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
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20808
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20809
 * The TCP write service routine should never be called...
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20810
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20811
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20812
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20813
tcp_wsrv(queue_t *q)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20814
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20815
	TCP_STAT(tcp_wsrv_called);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20816
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20817
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20818
/* Non overlapping byte exchanger */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20819
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20820
tcp_xchg(uchar_t *a, uchar_t *b, int len)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20821
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20822
	uchar_t	uch;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20823
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20824
	while (len-- > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20825
		uch = a[len];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20826
		a[len] = b[len];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20827
		b[len] = uch;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20828
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20829
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20830
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20831
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20832
 * Send out a control packet on the tcp connection specified.  This routine
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20833
 * is typically called where we need a simple ACK or RST generated.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20834
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20835
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20836
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
 20837
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20838
	uchar_t		*rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20839
	tcph_t		*tcph;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20840
	ipha_t		*ipha = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20841
	ip6_t		*ip6h = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20842
	uint32_t	sum;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20843
	int		tcp_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20844
	int		tcp_ip_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20845
	mblk_t		*mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20846
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20847
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20848
	 * Save sum for use in source route later.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20849
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20850
	ASSERT(tcp != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20851
	sum = tcp->tcp_tcp_hdr_len + tcp->tcp_sum;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20852
	tcp_hdr_len = tcp->tcp_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20853
	tcp_ip_hdr_len = tcp->tcp_ip_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20854
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20855
	/* If a text string is passed in with the request, pass it to strlog. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20856
	if (str != NULL && tcp->tcp_debug) {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20857
		(void) strlog(TCP_MOD_ID, 0, 1, SL_TRACE,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20858
		    "tcp_xmit_ctl: '%s', seq 0x%x, ack 0x%x, ctl 0x%x",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20859
		    str, seq, ack, ctl);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20860
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20861
	mp = allocb(tcp_ip_hdr_len + TCP_MAX_HDR_LENGTH + tcp_wroff_xtra,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20862
	    BPRI_MED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20863
	if (mp == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20864
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20865
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20866
	rptr = &mp->b_rptr[tcp_wroff_xtra];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20867
	mp->b_rptr = rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20868
	mp->b_wptr = &rptr[tcp_hdr_len];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20869
	bcopy(tcp->tcp_iphc, rptr, tcp_hdr_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20870
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20871
	if (tcp->tcp_ipversion == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20872
		ipha = (ipha_t *)rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20873
		ipha->ipha_length = htons(tcp_hdr_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20874
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20875
		ip6h = (ip6_t *)rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20876
		ASSERT(tcp != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20877
		ip6h->ip6_plen = htons(tcp->tcp_hdr_len -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20878
		    ((char *)&tcp->tcp_ip6h[1] - tcp->tcp_iphc));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20879
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20880
	tcph = (tcph_t *)&rptr[tcp_ip_hdr_len];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20881
	tcph->th_flags[0] = (uint8_t)ctl;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20882
	if (ctl & TH_RST) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20883
		BUMP_MIB(&tcp_mib, tcpOutRsts);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20884
		BUMP_MIB(&tcp_mib, tcpOutControl);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20885
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20886
		 * Don't send TSopt w/ TH_RST packets per RFC 1323.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20887
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20888
		if (tcp->tcp_snd_ts_ok &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20889
		    tcp->tcp_state > TCPS_SYN_SENT) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20890
			mp->b_wptr = &rptr[tcp_hdr_len - TCPOPT_REAL_TS_LEN];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20891
			*(mp->b_wptr) = TCPOPT_EOL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20892
			if (tcp->tcp_ipversion == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20893
				ipha->ipha_length = htons(tcp_hdr_len -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20894
				    TCPOPT_REAL_TS_LEN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20895
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20896
				ip6h->ip6_plen = htons(ntohs(ip6h->ip6_plen) -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20897
				    TCPOPT_REAL_TS_LEN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20898
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20899
			tcph->th_offset_and_rsrvd[0] -= (3 << 4);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20900
			sum -= TCPOPT_REAL_TS_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20901
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20902
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20903
	if (ctl & TH_ACK) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20904
		if (tcp->tcp_snd_ts_ok) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20905
			U32_TO_BE32(lbolt,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20906
			    (char *)tcph+TCP_MIN_HEADER_LENGTH+4);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20907
			U32_TO_BE32(tcp->tcp_ts_recent,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20908
			    (char *)tcph+TCP_MIN_HEADER_LENGTH+8);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20909
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20910
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20911
		/* Update the latest receive window size in TCP header. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20912
		U32_TO_ABE16(tcp->tcp_rwnd >> tcp->tcp_rcv_ws,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20913
		    tcph->th_win);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20914
		tcp->tcp_rack = ack;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20915
		tcp->tcp_rack_cnt = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20916
		BUMP_MIB(&tcp_mib, tcpOutAck);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20917
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20918
	BUMP_LOCAL(tcp->tcp_obsegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20919
	U32_TO_BE32(seq, tcph->th_seq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20920
	U32_TO_BE32(ack, tcph->th_ack);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20921
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20922
	 * Include the adjustment for a source route if any.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20923
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20924
	sum = (sum >> 16) + (sum & 0xFFFF);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20925
	U16_TO_BE16(sum, tcph->th_sum);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20926
	TCP_RECORD_TRACE(tcp, mp, TCP_TRACE_SEND_PKT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20927
	tcp_send_data(tcp, tcp->tcp_wq, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20928
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20929
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20930
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20931
 * If this routine returns B_TRUE, TCP can generate a RST in response
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20932
 * to a segment.  If it returns B_FALSE, TCP should not respond.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20933
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20934
static boolean_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20935
tcp_send_rst_chk(void)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20936
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20937
	clock_t	now;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20938
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20939
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20940
	 * TCP needs to protect itself from generating too many RSTs.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20941
	 * This can be a DoS attack by sending us random segments
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20942
	 * soliciting RSTs.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20943
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20944
	 * What we do here is to have a limit of tcp_rst_sent_rate RSTs
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20945
	 * in each 1 second interval.  In this way, TCP still generate
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20946
	 * RSTs in normal cases but when under attack, the impact is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20947
	 * limited.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20948
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20949
	if (tcp_rst_sent_rate_enabled != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20950
		now = lbolt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20951
		/* lbolt can wrap around. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20952
		if ((tcp_last_rst_intrvl > now) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20953
		    (TICK_TO_MSEC(now - tcp_last_rst_intrvl) > 1*SECONDS)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20954
			tcp_last_rst_intrvl = now;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20955
			tcp_rst_cnt = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20956
		} else if (++tcp_rst_cnt > tcp_rst_sent_rate) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20957
			return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20958
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20959
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20960
	return (B_TRUE);
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
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20964
 * Send down the advice IP ioctl to tell IP to mark an IRE temporary.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20965
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20966
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20967
tcp_ip_ire_mark_advice(tcp_t *tcp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20968
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20969
	mblk_t *mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20970
	ipic_t *ipic;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20971
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20972
	if (tcp->tcp_ipversion == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20973
		mp = tcp_ip_advise_mblk(&tcp->tcp_ipha->ipha_dst, IP_ADDR_LEN,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20974
		    &ipic);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20975
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20976
		mp = tcp_ip_advise_mblk(&tcp->tcp_ip6h->ip6_dst, IPV6_ADDR_LEN,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20977
		    &ipic);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20978
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20979
	if (mp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20980
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20981
	ipic->ipic_ire_marks |= IRE_MARK_TEMPORARY;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20982
	CALL_IP_WPUT(tcp->tcp_connp, tcp->tcp_wq, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20983
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20984
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20985
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20986
 * Return an IP advice ioctl mblk and set ipic to be the pointer
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20987
 * to the advice structure.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20988
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20989
static mblk_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20990
tcp_ip_advise_mblk(void *addr, int addr_len, ipic_t **ipic)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20991
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20992
	struct iocblk *ioc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20993
	mblk_t *mp, *mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20994
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20995
	mp = allocb(sizeof (ipic_t) + addr_len, BPRI_HI);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20996
	if (mp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20997
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20998
	bzero(mp->b_rptr, sizeof (ipic_t) + addr_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20999
	*ipic = (ipic_t *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21000
	(*ipic)->ipic_cmd = IP_IOC_IRE_ADVISE_NO_REPLY;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21001
	(*ipic)->ipic_addr_offset = sizeof (ipic_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21002
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21003
	bcopy(addr, *ipic + 1, addr_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21004
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21005
	(*ipic)->ipic_addr_length = addr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21006
	mp->b_wptr = &mp->b_rptr[sizeof (ipic_t) + addr_len];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21007
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21008
	mp1 = mkiocb(IP_IOCTL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21009
	if (mp1 == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21010
		freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21011
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21012
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21013
	mp1->b_cont = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21014
	ioc = (struct iocblk *)mp1->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21015
	ioc->ioc_count = sizeof (ipic_t) + addr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21016
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21017
	return (mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21018
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21019
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21020
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21021
 * Generate a reset based on an inbound packet for which there is no active
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21022
 * tcp state that we can find.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21023
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21024
 * IPSEC NOTE : Try to send the reply with the same protection as it came
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21025
 * in.  We still have the ipsec_mp that the packet was attached to. Thus
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21026
 * 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
 21027
 * converting the IPSEC_IN to IPSEC_OUT.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21028
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21029
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21030
tcp_xmit_early_reset(char *str, mblk_t *mp, uint32_t seq,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21031
    uint32_t ack, int ctl, uint_t ip_hdr_len)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21032
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21033
	ipha_t		*ipha = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21034
	ip6_t		*ip6h = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21035
	ushort_t	len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21036
	tcph_t		*tcph;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21037
	int		i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21038
	mblk_t		*ipsec_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21039
	boolean_t	mctl_present;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21040
	ipic_t		*ipic;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21041
	ipaddr_t	v4addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21042
	in6_addr_t	v6addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21043
	int		addr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21044
	void		*addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21045
	queue_t		*q = tcp_g_q;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21046
	tcp_t		*tcp = Q_TO_TCP(q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21047
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21048
	if (!tcp_send_rst_chk()) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21049
		tcp_rst_unsent++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21050
		freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21051
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21052
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21053
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21054
	if (mp->b_datap->db_type == M_CTL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21055
		ipsec_mp = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21056
		mp = mp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21057
		mctl_present = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21058
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21059
		ipsec_mp = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21060
		mctl_present = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21061
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21062
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21063
	if (str && q && tcp_dbg) {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 21064
		(void) strlog(TCP_MOD_ID, 0, 1, SL_TRACE,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21065
		    "tcp_xmit_early_reset: '%s', seq 0x%x, ack 0x%x, "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21066
		    "flags 0x%x",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21067
		    str, seq, ack, ctl);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21068
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21069
	if (mp->b_datap->db_ref != 1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21070
		mblk_t *mp1 = copyb(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21071
		freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21072
		mp = mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21073
		if (!mp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21074
			if (mctl_present)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21075
				freeb(ipsec_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21076
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21077
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21078
			if (mctl_present) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21079
				ipsec_mp->b_cont = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21080
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21081
				ipsec_mp = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21082
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21083
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21084
	} else if (mp->b_cont) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21085
		freemsg(mp->b_cont);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21086
		mp->b_cont = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21087
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21088
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21089
	 * We skip reversing source route here.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21090
	 * (for now we replace all IP options with EOL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21091
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21092
	if (IPH_HDR_VERSION(mp->b_rptr) == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21093
		ipha = (ipha_t *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21094
		for (i = IP_SIMPLE_HDR_LENGTH; i < (int)ip_hdr_len; i++)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21095
			mp->b_rptr[i] = IPOPT_EOL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21096
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21097
		 * Make sure that src address isn't flagrantly invalid.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21098
		 * Not all broadcast address checking for the src address
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21099
		 * is possible, since we don't know the netmask of the src
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21100
		 * addr.  No check for destination address is done, since
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21101
		 * IP will not pass up a packet with a broadcast dest
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21102
		 * address to TCP.  Similar checks are done below for IPv6.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21103
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21104
		if (ipha->ipha_src == 0 || ipha->ipha_src == INADDR_BROADCAST ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21105
		    CLASSD(ipha->ipha_src)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21106
			freemsg(ipsec_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21107
			BUMP_MIB(&ip_mib, ipInDiscards);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21108
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21109
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21110
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21111
		ip6h = (ip6_t *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21112
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21113
		if (IN6_IS_ADDR_UNSPECIFIED(&ip6h->ip6_src) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21114
		    IN6_IS_ADDR_MULTICAST(&ip6h->ip6_src)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21115
			freemsg(ipsec_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21116
			BUMP_MIB(&ip6_mib, ipv6InDiscards);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21117
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21118
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21119
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21120
		/* Remove any extension headers assuming partial overlay */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21121
		if (ip_hdr_len > IPV6_HDR_LEN) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21122
			uint8_t *to;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21123
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21124
			to = mp->b_rptr + ip_hdr_len - IPV6_HDR_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21125
			ovbcopy(ip6h, to, IPV6_HDR_LEN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21126
			mp->b_rptr += ip_hdr_len - IPV6_HDR_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21127
			ip_hdr_len = IPV6_HDR_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21128
			ip6h = (ip6_t *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21129
			ip6h->ip6_nxt = IPPROTO_TCP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21130
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21131
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21132
	tcph = (tcph_t *)&mp->b_rptr[ip_hdr_len];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21133
	if (tcph->th_flags[0] & TH_RST) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21134
		freemsg(ipsec_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21135
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21136
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21137
	tcph->th_offset_and_rsrvd[0] = (5 << 4);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21138
	len = ip_hdr_len + sizeof (tcph_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21139
	mp->b_wptr = &mp->b_rptr[len];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21140
	if (IPH_HDR_VERSION(mp->b_rptr) == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21141
		ipha->ipha_length = htons(len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21142
		/* Swap addresses */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21143
		v4addr = ipha->ipha_src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21144
		ipha->ipha_src = ipha->ipha_dst;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21145
		ipha->ipha_dst = v4addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21146
		ipha->ipha_ident = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21147
		ipha->ipha_ttl = (uchar_t)tcp_ipv4_ttl;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21148
		addr_len = IP_ADDR_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21149
		addr = &v4addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21150
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21151
		/* No ip6i_t in this case */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21152
		ip6h->ip6_plen = htons(len - IPV6_HDR_LEN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21153
		/* Swap addresses */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21154
		v6addr = ip6h->ip6_src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21155
		ip6h->ip6_src = ip6h->ip6_dst;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21156
		ip6h->ip6_dst = v6addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21157
		ip6h->ip6_hops = (uchar_t)tcp_ipv6_hoplimit;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21158
		addr_len = IPV6_ADDR_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21159
		addr = &v6addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21160
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21161
	tcp_xchg(tcph->th_fport, tcph->th_lport, 2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21162
	U32_TO_BE32(ack, tcph->th_ack);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21163
	U32_TO_BE32(seq, tcph->th_seq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21164
	U16_TO_BE16(0, tcph->th_win);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21165
	U16_TO_BE16(sizeof (tcph_t), tcph->th_sum);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21166
	tcph->th_flags[0] = (uint8_t)ctl;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21167
	if (ctl & TH_RST) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21168
		BUMP_MIB(&tcp_mib, tcpOutRsts);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21169
		BUMP_MIB(&tcp_mib, tcpOutControl);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21170
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21171
	if (mctl_present) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21172
		ipsec_in_t *ii = (ipsec_in_t *)ipsec_mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21173
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21174
		ASSERT(ii->ipsec_in_type == IPSEC_IN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21175
		if (!ipsec_in_to_out(ipsec_mp, ipha, ip6h)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21176
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21177
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21178
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21179
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21180
	 * NOTE:  one might consider tracing a TCP packet here, but
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21181
	 * this function has no active TCP state nd no tcp structure
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21182
	 * which has trace buffer.  If we traced here, we would have
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21183
	 * to keep a local trace buffer in tcp_record_trace().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21184
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21185
	CALL_IP_WPUT(tcp->tcp_connp, tcp->tcp_wq, ipsec_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21186
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21187
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21188
	 * Tell IP to mark the IRE used for this destination temporary.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21189
	 * This way, we can limit our exposure to DoS attack because IP
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21190
	 * creates an IRE for each destination.  If there are too many,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21191
	 * the time to do any routing lookup will be extremely long.  And
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21192
	 * the lookup can be in interrupt context.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21193
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21194
	 * Note that in normal circumstances, this marking should not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21195
	 * affect anything.  It would be nice if only 1 message is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21196
	 * needed to inform IP that the IRE created for this RST should
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21197
	 * not be added to the cache table.  But there is currently
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21198
	 * not such communication mechanism between TCP and IP.  So
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21199
	 * the best we can do now is to send the advice ioctl to IP
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21200
	 * to mark the IRE temporary.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21201
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21202
	if ((mp = tcp_ip_advise_mblk(addr, addr_len, &ipic)) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21203
		ipic->ipic_ire_marks |= IRE_MARK_TEMPORARY;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21204
		CALL_IP_WPUT(tcp->tcp_connp, tcp->tcp_wq, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21205
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21206
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21207
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21208
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21209
 * Initiate closedown sequence on an active connection.  (May be called as
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21210
 * writer.)  Return value zero for OK return, non-zero for error return.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21211
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21212
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21213
tcp_xmit_end(tcp_t *tcp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21214
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21215
	ipic_t	*ipic;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21216
	mblk_t	*mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21217
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21218
	if (tcp->tcp_state < TCPS_SYN_RCVD ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21219
	    tcp->tcp_state > TCPS_CLOSE_WAIT) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21220
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21221
		 * Invalid state, only states TCPS_SYN_RCVD,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21222
		 * TCPS_ESTABLISHED and TCPS_CLOSE_WAIT are valid
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21223
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21224
		return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21225
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21226
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21227
	tcp->tcp_fss = tcp->tcp_snxt + tcp->tcp_unsent;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21228
	tcp->tcp_valid_bits |= TCP_FSS_VALID;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21229
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21230
	 * If there is nothing more unsent, send the FIN now.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21231
	 * Otherwise, it will go out with the last segment.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21232
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21233
	if (tcp->tcp_unsent == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21234
		mp = tcp_xmit_mp(tcp, NULL, 0, NULL, NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21235
		    tcp->tcp_fss, B_FALSE, NULL, B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21236
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21237
		if (mp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21238
			TCP_RECORD_TRACE(tcp, mp, TCP_TRACE_SEND_PKT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21239
			tcp_send_data(tcp, tcp->tcp_wq, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21240
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21241
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21242
			 * Couldn't allocate msg.  Pretend we got it out.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21243
			 * Wait for rexmit timeout.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21244
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21245
			tcp->tcp_snxt = tcp->tcp_fss + 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21246
			TCP_TIMER_RESTART(tcp, tcp->tcp_rto);
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
		 * If needed, update tcp_rexmit_snxt as tcp_snxt is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21251
		 * changed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21252
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21253
		if (tcp->tcp_rexmit && tcp->tcp_rexmit_nxt == tcp->tcp_fss) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21254
			tcp->tcp_rexmit_nxt = tcp->tcp_snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21255
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21256
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21257
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21258
		 * If tcp->tcp_cork is set, then the data will not get sent,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21259
		 * so we have to check that and unset it first.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21260
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21261
		if (tcp->tcp_cork)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21262
			tcp->tcp_cork = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21263
		tcp_wput_data(tcp, NULL, B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21264
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21265
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21266
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21267
	 * If TCP does not get enough samples of RTT or tcp_rtt_updates
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21268
	 * is 0, don't update the cache.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21269
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21270
	if (tcp_rtt_updates == 0 || tcp->tcp_rtt_update < tcp_rtt_updates)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21271
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21272
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21273
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21274
	 * NOTE: should not update if source routes i.e. if tcp_remote if
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21275
	 * different from the destination.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21276
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21277
	if (tcp->tcp_ipversion == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21278
		if (tcp->tcp_remote !=  tcp->tcp_ipha->ipha_dst) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21279
			return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21280
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21281
		mp = tcp_ip_advise_mblk(&tcp->tcp_ipha->ipha_dst, IP_ADDR_LEN,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21282
		    &ipic);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21283
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21284
		if (!(IN6_ARE_ADDR_EQUAL(&tcp->tcp_remote_v6,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21285
		    &tcp->tcp_ip6h->ip6_dst))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21286
			return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21287
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21288
		mp = tcp_ip_advise_mblk(&tcp->tcp_ip6h->ip6_dst, IPV6_ADDR_LEN,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21289
		    &ipic);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21290
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21291
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21292
	/* Record route attributes in the IRE for use by future connections. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21293
	if (mp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21294
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21295
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21296
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21297
	 * We do not have a good algorithm to update ssthresh at this time.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21298
	 * So don't do any update.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21299
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21300
	ipic->ipic_rtt = tcp->tcp_rtt_sa;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21301
	ipic->ipic_rtt_sd = tcp->tcp_rtt_sd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21302
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21303
	CALL_IP_WPUT(tcp->tcp_connp, tcp->tcp_wq, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21304
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21305
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21306
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21307
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21308
 * Generate a "no listener here" RST in response to an "unknown" segment.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21309
 * Note that we are reusing the incoming mp to construct the outgoing
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21310
 * RST.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21311
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21312
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21313
tcp_xmit_listeners_reset(mblk_t *mp, uint_t ip_hdr_len)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21314
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21315
	uchar_t		*rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21316
	uint32_t	seg_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21317
	tcph_t		*tcph;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21318
	uint32_t	seg_seq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21319
	uint32_t	seg_ack;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21320
	uint_t		flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21321
	mblk_t		*ipsec_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21322
	ipha_t 		*ipha;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21323
	ip6_t 		*ip6h;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21324
	boolean_t	mctl_present = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21325
	boolean_t	check = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21326
	boolean_t	policy_present;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21327
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21328
	TCP_STAT(tcp_no_listener);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21329
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21330
	ipsec_mp = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21331
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21332
	if (mp->b_datap->db_type == M_CTL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21333
		ipsec_in_t *ii;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21334
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21335
		mctl_present = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21336
		mp = mp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21337
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21338
		ii = (ipsec_in_t *)ipsec_mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21339
		ASSERT(ii->ipsec_in_type == IPSEC_IN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21340
		if (ii->ipsec_in_dont_check) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21341
			check = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21342
			if (!ii->ipsec_in_secure) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21343
				freeb(ipsec_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21344
				mctl_present = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21345
				ipsec_mp = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21346
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21347
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21348
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21349
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21350
	if (IPH_HDR_VERSION(mp->b_rptr) == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21351
		policy_present = ipsec_inbound_v4_policy_present;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21352
		ipha = (ipha_t *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21353
		ip6h = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21354
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21355
		policy_present = ipsec_inbound_v6_policy_present;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21356
		ipha = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21357
		ip6h = (ip6_t *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21358
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21359
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21360
	if (check && policy_present) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21361
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21362
		 * The conn_t parameter is NULL because we already know
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21363
		 * nobody's home.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21364
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21365
		ipsec_mp = ipsec_check_global_policy(
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21366
			ipsec_mp, (conn_t *)NULL, ipha, ip6h, mctl_present);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21367
		if (ipsec_mp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21368
			return;
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
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21372
	rptr = mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21373
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21374
	tcph = (tcph_t *)&rptr[ip_hdr_len];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21375
	seg_seq = BE32_TO_U32(tcph->th_seq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21376
	seg_ack = BE32_TO_U32(tcph->th_ack);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21377
	flags = tcph->th_flags[0];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21378
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21379
	seg_len = msgdsize(mp) - (TCP_HDR_LENGTH(tcph) + ip_hdr_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21380
	if (flags & TH_RST) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21381
		freemsg(ipsec_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21382
	} else if (flags & TH_ACK) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21383
		tcp_xmit_early_reset("no tcp, reset",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21384
		    ipsec_mp, seg_ack, 0, TH_RST, ip_hdr_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21385
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21386
		if (flags & TH_SYN) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21387
			seg_len++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21388
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21389
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21390
			 * Here we violate the RFC.  Note that a normal
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21391
			 * TCP will never send a segment without the ACK
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21392
			 * flag, except for RST or SYN segment.  This
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21393
			 * segment is neither.  Just drop it on the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21394
			 * floor.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21395
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21396
			freemsg(ipsec_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21397
			tcp_rst_unsent++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21398
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21399
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21400
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21401
		tcp_xmit_early_reset("no tcp, reset/ack",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21402
		    ipsec_mp, 0, seg_seq + seg_len,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21403
		    TH_RST | TH_ACK, ip_hdr_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21404
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21405
}
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
 * tcp_xmit_mp is called to return a pointer to an mblk chain complete with
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21409
 * 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
 21410
 * 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
 21411
 * mblk. (If sendall is not set the dup'ing will stop at an mblk boundary
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21412
 * otherwise it will dup partial mblks.)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21413
 * Otherwise, an appropriate ACK packet will be generated.  This
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21414
 * routine is not usually called to send new data for the first time.  It
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21415
 * is mostly called out of the timer for retransmits, and to generate ACKs.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21416
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21417
 * 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
 21418
 * be adjusted by *offset.  And after dupb(), the offset and the ending mblk
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21419
 * of the original mblk chain will be returned in *offset and *end_mp.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21420
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21421
static mblk_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21422
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
 21423
    mblk_t **end_mp, uint32_t seq, boolean_t sendall, uint32_t *seg_len,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21424
    boolean_t rexmit)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21425
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21426
	int	data_length;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21427
	int32_t	off = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21428
	uint_t	flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21429
	mblk_t	*mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21430
	mblk_t	*mp2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21431
	uchar_t	*rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21432
	tcph_t	*tcph;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21433
	int32_t	num_sack_blk = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21434
	int32_t	sack_opt_len = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21435
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21436
	/* Allocate for our maximum TCP header + link-level */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21437
	mp1 = allocb(tcp->tcp_ip_hdr_len + TCP_MAX_HDR_LENGTH + tcp_wroff_xtra,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21438
	    BPRI_MED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21439
	if (!mp1)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21440
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21441
	data_length = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21442
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21443
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21444
	 * Note that tcp_mss has been adjusted to take into account the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21445
	 * timestamp option if applicable.  Because SACK options do not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21446
	 * appear in every TCP segments and they are of variable lengths,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21447
	 * they cannot be included in tcp_mss.  Thus we need to calculate
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21448
	 * the actual segment length when we need to send a segment which
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21449
	 * includes SACK options.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21450
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21451
	if (tcp->tcp_snd_sack_ok && tcp->tcp_num_sack_blk > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21452
		num_sack_blk = MIN(tcp->tcp_max_sack_blk,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21453
		    tcp->tcp_num_sack_blk);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21454
		sack_opt_len = num_sack_blk * sizeof (sack_blk_t) +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21455
		    TCPOPT_NOP_LEN * 2 + TCPOPT_HEADER_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21456
		if (max_to_send + sack_opt_len > tcp->tcp_mss)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21457
			max_to_send -= sack_opt_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21458
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21459
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21460
	if (offset != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21461
		off = *offset;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21462
		/* We use offset as an indicator that end_mp is not NULL. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21463
		*end_mp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21464
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21465
	for (mp2 = mp1; mp && data_length != max_to_send; mp = mp->b_cont) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21466
		/* This could be faster with cooperation from downstream */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21467
		if (mp2 != mp1 && !sendall &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21468
		    data_length + (int)(mp->b_wptr - mp->b_rptr) >
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21469
		    max_to_send)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21470
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21471
			 * Don't send the next mblk since the whole mblk
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21472
			 * does not fit.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21473
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21474
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21475
		mp2->b_cont = dupb(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21476
		mp2 = mp2->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21477
		if (!mp2) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21478
			freemsg(mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21479
			return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21480
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21481
		mp2->b_rptr += off;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21482
		ASSERT((uintptr_t)(mp2->b_wptr - mp2->b_rptr) <=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21483
		    (uintptr_t)INT_MAX);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21484
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21485
		data_length += (int)(mp2->b_wptr - mp2->b_rptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21486
		if (data_length > max_to_send) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21487
			mp2->b_wptr -= data_length - max_to_send;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21488
			data_length = max_to_send;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21489
			off = mp2->b_wptr - mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21490
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21491
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21492
			off = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21493
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21494
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21495
	if (offset != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21496
		*offset = off;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21497
		*end_mp = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21498
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21499
	if (seg_len != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21500
		*seg_len = data_length;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21501
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21502
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21503
	/* Update the latest receive window size in TCP header. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21504
	U32_TO_ABE16(tcp->tcp_rwnd >> tcp->tcp_rcv_ws,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21505
	    tcp->tcp_tcph->th_win);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21506
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21507
	rptr = mp1->b_rptr + tcp_wroff_xtra;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21508
	mp1->b_rptr = rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21509
	mp1->b_wptr = rptr + tcp->tcp_hdr_len + sack_opt_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21510
	bcopy(tcp->tcp_iphc, rptr, tcp->tcp_hdr_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21511
	tcph = (tcph_t *)&rptr[tcp->tcp_ip_hdr_len];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21512
	U32_TO_ABE32(seq, tcph->th_seq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21513
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21514
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21515
	 * Use tcp_unsent to determine if the PUSH bit should be used assumes
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21516
	 * that this function was called from tcp_wput_data. Thus, when called
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21517
	 * to retransmit data the setting of the PUSH bit may appear some
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21518
	 * what random in that it might get set when it should not. This
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21519
	 * should not pose any performance issues.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21520
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21521
	if (data_length != 0 && (tcp->tcp_unsent == 0 ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21522
	    tcp->tcp_unsent == data_length)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21523
		flags = TH_ACK | TH_PUSH;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21524
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21525
		flags = TH_ACK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21526
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21527
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21528
	if (tcp->tcp_ecn_ok) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21529
		if (tcp->tcp_ecn_echo_on)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21530
			flags |= TH_ECE;
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
		 * Only set ECT bit and ECN_CWR if a segment contains new data.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21534
		 * There is no TCP flow control for non-data segments, and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21535
		 * only data segment is transmitted reliably.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21536
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21537
		if (data_length > 0 && !rexmit) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21538
			SET_ECT(tcp, rptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21539
			if (tcp->tcp_cwr && !tcp->tcp_ecn_cwr_sent) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21540
				flags |= TH_CWR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21541
				tcp->tcp_ecn_cwr_sent = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21542
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21543
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21544
	}
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) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21547
		uint32_t u1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21548
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21549
		if ((tcp->tcp_valid_bits & TCP_ISS_VALID) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21550
		    seq == tcp->tcp_iss) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21551
			uchar_t	*wptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21552
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21553
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21554
			 * If TCP_ISS_VALID and the seq number is tcp_iss,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21555
			 * TCP can only be in SYN-SENT, SYN-RCVD or
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21556
			 * FIN-WAIT-1 state.  It can be FIN-WAIT-1 if
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21557
			 * our SYN is not ack'ed but the app closes this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21558
			 * TCP connection.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21559
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21560
			ASSERT(tcp->tcp_state == TCPS_SYN_SENT ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21561
			    tcp->tcp_state == TCPS_SYN_RCVD ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21562
			    tcp->tcp_state == TCPS_FIN_WAIT_1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21563
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21564
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21565
			 * Tack on the MSS option.  It is always needed
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21566
			 * for both active and passive open.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21567
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21568
			 * MSS option value should be interface MTU - MIN
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21569
			 * TCP/IP header according to RFC 793 as it means
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21570
			 * the maximum segment size TCP can receive.  But
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21571
			 * to get around some broken middle boxes/end hosts
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21572
			 * out there, we allow the option value to be the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21573
			 * same as the MSS option size on the peer side.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21574
			 * In this way, the other side will not send
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21575
			 * anything larger than they can receive.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21576
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21577
			 * Note that for SYN_SENT state, the ndd param
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21578
			 * tcp_use_smss_as_mss_opt has no effect as we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21579
			 * don't know the peer's MSS option value. So
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21580
			 * the only case we need to take care of is in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21581
			 * SYN_RCVD state, which is done later.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21582
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21583
			wptr = mp1->b_wptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21584
			wptr[0] = TCPOPT_MAXSEG;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21585
			wptr[1] = TCPOPT_MAXSEG_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21586
			wptr += 2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21587
			u1 = tcp->tcp_if_mtu -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21588
			    (tcp->tcp_ipversion == IPV4_VERSION ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21589
			    IP_SIMPLE_HDR_LENGTH : IPV6_HDR_LEN) -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21590
			    TCP_MIN_HEADER_LENGTH;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21591
			U16_TO_BE16(u1, wptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21592
			mp1->b_wptr = wptr + 2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21593
			/* Update the offset to cover the additional word */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21594
			tcph->th_offset_and_rsrvd[0] += (1 << 4);
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
			 * Note that the following way of filling in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21598
			 * TCP options are not optimal.  Some NOPs can
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21599
			 * be saved.  But there is no need at this time
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21600
			 * to optimize it.  When it is needed, we will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21601
			 * do it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21602
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21603
			switch (tcp->tcp_state) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21604
			case TCPS_SYN_SENT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21605
				flags = TH_SYN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21606
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21607
				if (tcp->tcp_snd_ts_ok) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21608
					uint32_t llbolt = (uint32_t)lbolt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21609
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21610
					wptr = mp1->b_wptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21611
					wptr[0] = TCPOPT_NOP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21612
					wptr[1] = TCPOPT_NOP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21613
					wptr[2] = TCPOPT_TSTAMP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21614
					wptr[3] = TCPOPT_TSTAMP_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21615
					wptr += 4;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21616
					U32_TO_BE32(llbolt, wptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21617
					wptr += 4;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21618
					ASSERT(tcp->tcp_ts_recent == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21619
					U32_TO_BE32(0L, wptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21620
					mp1->b_wptr += TCPOPT_REAL_TS_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21621
					tcph->th_offset_and_rsrvd[0] +=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21622
					    (3 << 4);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21623
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21624
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21625
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21626
				 * Set up all the bits to tell other side
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21627
				 * we are ECN capable.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21628
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21629
				if (tcp->tcp_ecn_ok) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21630
					flags |= (TH_ECE | TH_CWR);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21631
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21632
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21633
			case TCPS_SYN_RCVD:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21634
				flags |= TH_SYN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21635
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21636
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21637
				 * Reset the MSS option value to be SMSS
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21638
				 * We should probably add back the bytes
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21639
				 * for timestamp option and IPsec.  We
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21640
				 * don't do that as this is a workaround
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21641
				 * for broken middle boxes/end hosts, it
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21642
				 * is better for us to be more cautious.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21643
				 * They may not take these things into
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21644
				 * account in their SMSS calculation.  Thus
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21645
				 * the peer's calculated SMSS may be smaller
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21646
				 * than what it can be.  This should be OK.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21647
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21648
				if (tcp_use_smss_as_mss_opt) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21649
					u1 = tcp->tcp_mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21650
					U16_TO_BE16(u1, wptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21651
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21652
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21653
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21654
				 * If the other side is ECN capable, reply
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21655
				 * that we are also ECN capable.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21656
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21657
				if (tcp->tcp_ecn_ok)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21658
					flags |= TH_ECE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21659
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21660
			default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21661
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21662
				 * The above ASSERT() makes sure that this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21663
				 * must be FIN-WAIT-1 state.  Our SYN has
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21664
				 * not been ack'ed so retransmit it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21665
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21666
				flags |= TH_SYN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21667
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21668
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21669
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21670
			if (tcp->tcp_snd_ws_ok) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21671
				wptr = mp1->b_wptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21672
				wptr[0] =  TCPOPT_NOP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21673
				wptr[1] =  TCPOPT_WSCALE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21674
				wptr[2] =  TCPOPT_WS_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21675
				wptr[3] = (uchar_t)tcp->tcp_rcv_ws;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21676
				mp1->b_wptr += TCPOPT_REAL_WS_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21677
				tcph->th_offset_and_rsrvd[0] += (1 << 4);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21678
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21679
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21680
			if (tcp->tcp_snd_sack_ok) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21681
				wptr = mp1->b_wptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21682
				wptr[0] = TCPOPT_NOP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21683
				wptr[1] = TCPOPT_NOP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21684
				wptr[2] = TCPOPT_SACK_PERMITTED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21685
				wptr[3] = TCPOPT_SACK_OK_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21686
				mp1->b_wptr += TCPOPT_REAL_SACK_OK_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21687
				tcph->th_offset_and_rsrvd[0] += (1 << 4);
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
			/* allocb() of adequate mblk assures space */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21691
			ASSERT((uintptr_t)(mp1->b_wptr - mp1->b_rptr) <=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21692
			    (uintptr_t)INT_MAX);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21693
			u1 = (int)(mp1->b_wptr - mp1->b_rptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21694
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21695
			 * Get IP set to checksum on our behalf
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21696
			 * Include the adjustment for a source route if any.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21697
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21698
			u1 += tcp->tcp_sum;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21699
			u1 = (u1 >> 16) + (u1 & 0xFFFF);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21700
			U16_TO_BE16(u1, tcph->th_sum);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21701
			BUMP_MIB(&tcp_mib, tcpOutControl);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21702
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21703
		if ((tcp->tcp_valid_bits & TCP_FSS_VALID) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21704
		    (seq + data_length) == tcp->tcp_fss) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21705
			if (!tcp->tcp_fin_acked) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21706
				flags |= TH_FIN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21707
				BUMP_MIB(&tcp_mib, tcpOutControl);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21708
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21709
			if (!tcp->tcp_fin_sent) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21710
				tcp->tcp_fin_sent = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21711
				switch (tcp->tcp_state) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21712
				case TCPS_SYN_RCVD:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21713
				case TCPS_ESTABLISHED:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21714
					tcp->tcp_state = TCPS_FIN_WAIT_1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21715
					break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21716
				case TCPS_CLOSE_WAIT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21717
					tcp->tcp_state = TCPS_LAST_ACK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21718
					break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21719
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21720
				if (tcp->tcp_suna == tcp->tcp_snxt)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21721
					TCP_TIMER_RESTART(tcp, tcp->tcp_rto);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21722
				tcp->tcp_snxt = tcp->tcp_fss + 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21723
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21724
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21725
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21726
		 * Note the trick here.  u1 is unsigned.  When tcp_urg
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21727
		 * is smaller than seq, u1 will become a very huge value.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21728
		 * So the comparison will fail.  Also note that tcp_urp
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21729
		 * should be positive, see RFC 793 page 17.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21730
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21731
		u1 = tcp->tcp_urg - seq + TCP_OLD_URP_INTERPRETATION;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21732
		if ((tcp->tcp_valid_bits & TCP_URG_VALID) && u1 != 0 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21733
		    u1 < (uint32_t)(64 * 1024)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21734
			flags |= TH_URG;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21735
			BUMP_MIB(&tcp_mib, tcpOutUrg);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21736
			U32_TO_ABE16(u1, tcph->th_urp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21737
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21738
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21739
	tcph->th_flags[0] = (uchar_t)flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21740
	tcp->tcp_rack = tcp->tcp_rnxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21741
	tcp->tcp_rack_cnt = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21742
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21743
	if (tcp->tcp_snd_ts_ok) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21744
		if (tcp->tcp_state != TCPS_SYN_SENT) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21745
			uint32_t llbolt = (uint32_t)lbolt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21746
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21747
			U32_TO_BE32(llbolt,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21748
			    (char *)tcph+TCP_MIN_HEADER_LENGTH+4);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21749
			U32_TO_BE32(tcp->tcp_ts_recent,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21750
			    (char *)tcph+TCP_MIN_HEADER_LENGTH+8);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21751
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21752
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21753
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21754
	if (num_sack_blk > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21755
		uchar_t *wptr = (uchar_t *)tcph + tcp->tcp_tcp_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21756
		sack_blk_t *tmp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21757
		int32_t	i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21758
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21759
		wptr[0] = TCPOPT_NOP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21760
		wptr[1] = TCPOPT_NOP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21761
		wptr[2] = TCPOPT_SACK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21762
		wptr[3] = TCPOPT_HEADER_LEN + num_sack_blk *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21763
		    sizeof (sack_blk_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21764
		wptr += TCPOPT_REAL_SACK_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21765
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21766
		tmp = tcp->tcp_sack_list;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21767
		for (i = 0; i < num_sack_blk; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21768
			U32_TO_BE32(tmp[i].begin, wptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21769
			wptr += sizeof (tcp_seq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21770
			U32_TO_BE32(tmp[i].end, wptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21771
			wptr += sizeof (tcp_seq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21772
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21773
		tcph->th_offset_and_rsrvd[0] += ((num_sack_blk * 2 + 1) << 4);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21774
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21775
	ASSERT((uintptr_t)(mp1->b_wptr - rptr) <= (uintptr_t)INT_MAX);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21776
	data_length += (int)(mp1->b_wptr - rptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21777
	if (tcp->tcp_ipversion == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21778
		((ipha_t *)rptr)->ipha_length = htons(data_length);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21779
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21780
		ip6_t *ip6 = (ip6_t *)(rptr +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21781
		    (((ip6_t *)rptr)->ip6_nxt == IPPROTO_RAW ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21782
		    sizeof (ip6i_t) : 0));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21783
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21784
		ip6->ip6_plen = htons(data_length -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21785
		    ((char *)&tcp->tcp_ip6h[1] - tcp->tcp_iphc));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21786
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21787
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21788
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21789
	 * Prime pump for IP
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21790
	 * Include the adjustment for a source route if any.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21791
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21792
	data_length -= tcp->tcp_ip_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21793
	data_length += tcp->tcp_sum;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21794
	data_length = (data_length >> 16) + (data_length & 0xFFFF);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21795
	U16_TO_ABE16(data_length, tcph->th_sum);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21796
	if (tcp->tcp_ip_forward_progress) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21797
		ASSERT(tcp->tcp_ipversion == IPV6_VERSION);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21798
		*(uint32_t *)mp1->b_rptr  |= IP_FORWARD_PROG;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21799
		tcp->tcp_ip_forward_progress = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21800
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21801
	return (mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21802
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21803
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21804
/* This function handles the push timeout. */
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 21805
void
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21806
tcp_push_timer(void *arg)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21807
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21808
	conn_t	*connp = (conn_t *)arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21809
	tcp_t *tcp = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21810
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21811
	TCP_DBGSTAT(tcp_push_timer_cnt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21812
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21813
	ASSERT(tcp->tcp_listener == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21814
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 21815
	/*
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 21816
	 * We need to stop synchronous streams temporarily to prevent a race
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 21817
	 * 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
 21818
	 * tcp_rcv_list here because those entry points will return right
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 21819
	 * away when synchronous streams is stopped.
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 21820
	 */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 21821
	TCP_FUSE_SYNCSTR_STOP(tcp);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21822
	tcp->tcp_push_tid = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21823
	if ((tcp->tcp_rcv_list != NULL) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21824
	    (tcp_rcv_drain(tcp->tcp_rq, tcp) == TH_ACK_NEEDED))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21825
		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
 21826
	TCP_FUSE_SYNCSTR_RESUME(tcp);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21827
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21828
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21829
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21830
 * This function handles delayed ACK timeout.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21831
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21832
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21833
tcp_ack_timer(void *arg)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21834
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21835
	conn_t	*connp = (conn_t *)arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21836
	tcp_t *tcp = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21837
	mblk_t *mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21838
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21839
	TCP_DBGSTAT(tcp_ack_timer_cnt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21840
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21841
	tcp->tcp_ack_tid = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21842
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21843
	if (tcp->tcp_fused)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21844
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21845
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21846
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21847
	 * Do not send ACK if there is no outstanding unack'ed data.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21848
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21849
	if (tcp->tcp_rnxt == tcp->tcp_rack) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21850
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21851
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21852
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21853
	if ((tcp->tcp_rnxt - tcp->tcp_rack) > tcp->tcp_mss) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21854
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21855
		 * Make sure we don't allow deferred ACKs to result in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21856
		 * timer-based ACKing.  If we have held off an ACK
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21857
		 * when there was more than an mss here, and the timer
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21858
		 * goes off, we have to worry about the possibility
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21859
		 * that the sender isn't doing slow-start, or is out
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21860
		 * of step with us for some other reason.  We fall
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21861
		 * permanently back in the direction of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21862
		 * ACK-every-other-packet as suggested in RFC 1122.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21863
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21864
		if (tcp->tcp_rack_abs_max > 2)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21865
			tcp->tcp_rack_abs_max--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21866
		tcp->tcp_rack_cur_max = 2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21867
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21868
	mp = tcp_ack_mp(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21869
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21870
	if (mp != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21871
		TCP_RECORD_TRACE(tcp, mp, TCP_TRACE_SEND_PKT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21872
		BUMP_LOCAL(tcp->tcp_obsegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21873
		BUMP_MIB(&tcp_mib, tcpOutAck);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21874
		BUMP_MIB(&tcp_mib, tcpOutAckDelayed);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21875
		tcp_send_data(tcp, tcp->tcp_wq, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21876
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21877
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21878
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21879
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21880
/* Generate an ACK-only (no data) segment for a TCP endpoint */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21881
static mblk_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21882
tcp_ack_mp(tcp_t *tcp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21883
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21884
	uint32_t	seq_no;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21885
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21886
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21887
	 * There are a few cases to be considered while setting the sequence no.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21888
	 * Essentially, we can come here while processing an unacceptable pkt
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21889
	 * in the TCPS_SYN_RCVD state, in which case we set the sequence number
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21890
	 * to snxt (per RFC 793), note the swnd wouldn't have been set yet.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21891
	 * If we are here for a zero window probe, stick with suna. In all
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21892
	 * other cases, we check if suna + swnd encompasses snxt and set
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21893
	 * the sequence number to snxt, if so. If snxt falls outside the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21894
	 * window (the receiver probably shrunk its window), we will go with
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21895
	 * suna + swnd, otherwise the sequence no will be unacceptable to the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21896
	 * receiver.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21897
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21898
	if (tcp->tcp_zero_win_probe) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21899
		seq_no = tcp->tcp_suna;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21900
	} else if (tcp->tcp_state == TCPS_SYN_RCVD) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21901
		ASSERT(tcp->tcp_swnd == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21902
		seq_no = tcp->tcp_snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21903
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21904
		seq_no = SEQ_GT(tcp->tcp_snxt,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21905
		    (tcp->tcp_suna + tcp->tcp_swnd)) ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21906
		    (tcp->tcp_suna + tcp->tcp_swnd) : tcp->tcp_snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21907
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21908
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21909
	if (tcp->tcp_valid_bits) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21910
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21911
		 * For the complex case where we have to send some
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21912
		 * controls (FIN or SYN), let tcp_xmit_mp do it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21913
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21914
		return (tcp_xmit_mp(tcp, NULL, 0, NULL, NULL, seq_no, B_FALSE,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21915
		    NULL, B_FALSE));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21916
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21917
		/* Generate a simple ACK */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21918
		int	data_length;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21919
		uchar_t	*rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21920
		tcph_t	*tcph;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21921
		mblk_t	*mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21922
		int32_t	tcp_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21923
		int32_t	tcp_tcp_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21924
		int32_t	num_sack_blk = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21925
		int32_t sack_opt_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21926
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21927
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21928
		 * Allocate space for TCP + IP headers
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21929
		 * and link-level header
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21930
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21931
		if (tcp->tcp_snd_sack_ok && tcp->tcp_num_sack_blk > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21932
			num_sack_blk = MIN(tcp->tcp_max_sack_blk,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21933
			    tcp->tcp_num_sack_blk);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21934
			sack_opt_len = num_sack_blk * sizeof (sack_blk_t) +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21935
			    TCPOPT_NOP_LEN * 2 + TCPOPT_HEADER_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21936
			tcp_hdr_len = tcp->tcp_hdr_len + sack_opt_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21937
			tcp_tcp_hdr_len = tcp->tcp_tcp_hdr_len + sack_opt_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21938
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21939
			tcp_hdr_len = tcp->tcp_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21940
			tcp_tcp_hdr_len = tcp->tcp_tcp_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21941
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21942
		mp1 = allocb(tcp_hdr_len + tcp_wroff_xtra, BPRI_MED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21943
		if (!mp1)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21944
			return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21945
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21946
		/* Update the latest receive window size in TCP header. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21947
		U32_TO_ABE16(tcp->tcp_rwnd >> tcp->tcp_rcv_ws,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21948
		    tcp->tcp_tcph->th_win);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21949
		/* copy in prototype TCP + IP header */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21950
		rptr = mp1->b_rptr + tcp_wroff_xtra;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21951
		mp1->b_rptr = rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21952
		mp1->b_wptr = rptr + tcp_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21953
		bcopy(tcp->tcp_iphc, rptr, tcp->tcp_hdr_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21954
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21955
		tcph = (tcph_t *)&rptr[tcp->tcp_ip_hdr_len];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21956
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21957
		/* Set the TCP sequence number. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21958
		U32_TO_ABE32(seq_no, tcph->th_seq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21959
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21960
		/* Set up the TCP flag field. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21961
		tcph->th_flags[0] = (uchar_t)TH_ACK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21962
		if (tcp->tcp_ecn_echo_on)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21963
			tcph->th_flags[0] |= TH_ECE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21964
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21965
		tcp->tcp_rack = tcp->tcp_rnxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21966
		tcp->tcp_rack_cnt = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21967
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21968
		/* fill in timestamp option if in use */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21969
		if (tcp->tcp_snd_ts_ok) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21970
			uint32_t llbolt = (uint32_t)lbolt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21971
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21972
			U32_TO_BE32(llbolt,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21973
			    (char *)tcph+TCP_MIN_HEADER_LENGTH+4);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21974
			U32_TO_BE32(tcp->tcp_ts_recent,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21975
			    (char *)tcph+TCP_MIN_HEADER_LENGTH+8);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21976
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21977
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21978
		/* Fill in SACK options */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21979
		if (num_sack_blk > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21980
			uchar_t *wptr = (uchar_t *)tcph + tcp->tcp_tcp_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21981
			sack_blk_t *tmp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21982
			int32_t	i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21983
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21984
			wptr[0] = TCPOPT_NOP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21985
			wptr[1] = TCPOPT_NOP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21986
			wptr[2] = TCPOPT_SACK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21987
			wptr[3] = TCPOPT_HEADER_LEN + num_sack_blk *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21988
			    sizeof (sack_blk_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21989
			wptr += TCPOPT_REAL_SACK_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21990
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21991
			tmp = tcp->tcp_sack_list;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21992
			for (i = 0; i < num_sack_blk; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21993
				U32_TO_BE32(tmp[i].begin, wptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21994
				wptr += sizeof (tcp_seq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21995
				U32_TO_BE32(tmp[i].end, wptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21996
				wptr += sizeof (tcp_seq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21997
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21998
			tcph->th_offset_and_rsrvd[0] += ((num_sack_blk * 2 + 1)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21999
			    << 4);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22000
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22001
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22002
		if (tcp->tcp_ipversion == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22003
			((ipha_t *)rptr)->ipha_length = htons(tcp_hdr_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22004
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22005
			/* Check for ip6i_t header in sticky hdrs */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22006
			ip6_t *ip6 = (ip6_t *)(rptr +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22007
			    (((ip6_t *)rptr)->ip6_nxt == IPPROTO_RAW ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22008
			    sizeof (ip6i_t) : 0));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22009
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22010
			ip6->ip6_plen = htons(tcp_hdr_len -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22011
			    ((char *)&tcp->tcp_ip6h[1] - tcp->tcp_iphc));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22012
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22013
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22014
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22015
		 * Prime pump for checksum calculation in IP.  Include the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22016
		 * adjustment for a source route if any.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22017
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22018
		data_length = tcp_tcp_hdr_len + tcp->tcp_sum;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22019
		data_length = (data_length >> 16) + (data_length & 0xFFFF);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22020
		U16_TO_ABE16(data_length, tcph->th_sum);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22021
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22022
		if (tcp->tcp_ip_forward_progress) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22023
			ASSERT(tcp->tcp_ipversion == IPV6_VERSION);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22024
			*(uint32_t *)mp1->b_rptr  |= IP_FORWARD_PROG;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22025
			tcp->tcp_ip_forward_progress = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22026
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22027
		return (mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22028
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22029
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22030
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22031
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22032
 * To create a temporary tcp structure for inserting into bind hash list.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22033
 * The parameter is assumed to be in network byte order, ready for use.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22034
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22035
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22036
static tcp_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22037
tcp_alloc_temp_tcp(in_port_t port)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22038
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22039
	conn_t	*connp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22040
	tcp_t	*tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22041
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22042
	connp = ipcl_conn_create(IPCL_TCPCONN, KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22043
	if (connp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22044
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22045
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22046
	tcp = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22047
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22048
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22049
	 * Only initialize the necessary info in those structures.  Note
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22050
	 * that since INADDR_ANY is all 0, we do not need to set
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22051
	 * tcp_bound_source to INADDR_ANY here.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22052
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22053
	tcp->tcp_state = TCPS_BOUND;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22054
	tcp->tcp_lport = port;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22055
	tcp->tcp_exclbind = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22056
	tcp->tcp_reserved_port = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22057
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22058
	/* Just for place holding... */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22059
	tcp->tcp_ipversion = IPV4_VERSION;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22060
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22061
	return (tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22062
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22063
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22064
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22065
 * To remove a port range specified by lo_port and hi_port from the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22066
 * reserved port ranges.  This is one of the three public functions of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22067
 * the reserved port interface.  Note that a port range has to be removed
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22068
 * as a whole.  Ports in a range cannot be removed individually.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22069
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22070
 * Params:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22071
 *	in_port_t lo_port: the beginning port of the reserved port range to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22072
 *		be deleted.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22073
 *	in_port_t hi_port: the ending port of the reserved port range to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22074
 *		be deleted.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22075
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22076
 * Return:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22077
 *	B_TRUE if the deletion is successful, B_FALSE otherwise.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22078
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22079
boolean_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22080
tcp_reserved_port_del(in_port_t lo_port, in_port_t hi_port)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22081
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22082
	int	i, j;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22083
	int	size;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22084
	tcp_t	**temp_tcp_array;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22085
	tcp_t	*tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22086
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22087
	rw_enter(&tcp_reserved_port_lock, RW_WRITER);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22088
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22089
	/* First make sure that the port ranage is indeed reserved. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22090
	for (i = 0; i < tcp_reserved_port_array_size; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22091
		if (tcp_reserved_port[i].lo_port == lo_port) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22092
			hi_port = tcp_reserved_port[i].hi_port;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22093
			temp_tcp_array = tcp_reserved_port[i].temp_tcp_array;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22094
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22095
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22096
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22097
	if (i == tcp_reserved_port_array_size) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22098
		rw_exit(&tcp_reserved_port_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22099
		return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22100
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22101
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22102
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22103
	 * Remove the range from the array.  This simple loop is possible
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22104
	 * because port ranges are inserted in ascending order.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22105
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22106
	for (j = i; j < tcp_reserved_port_array_size - 1; j++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22107
		tcp_reserved_port[j].lo_port = tcp_reserved_port[j+1].lo_port;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22108
		tcp_reserved_port[j].hi_port = tcp_reserved_port[j+1].hi_port;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22109
		tcp_reserved_port[j].temp_tcp_array =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22110
		    tcp_reserved_port[j+1].temp_tcp_array;
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
	/* Remove all the temporary tcp structures. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22114
	size = hi_port - lo_port + 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22115
	while (size > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22116
		tcp = temp_tcp_array[size - 1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22117
		ASSERT(tcp != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22118
		tcp_bind_hash_remove(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22119
		CONN_DEC_REF(tcp->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22120
		size--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22121
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22122
	kmem_free(temp_tcp_array, (hi_port - lo_port + 1) * sizeof (tcp_t *));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22123
	tcp_reserved_port_array_size--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22124
	rw_exit(&tcp_reserved_port_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22125
	return (B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22126
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22127
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22128
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22129
 * Macro to remove temporary tcp structure from the bind hash list.  The
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22130
 * first parameter is the list of tcp to be removed.  The second parameter
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22131
 * is the number of tcps in the array.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22132
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22133
#define	TCP_TMP_TCP_REMOVE(tcp_array, num) \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22134
{ \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22135
	while ((num) > 0) { \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22136
		tcp_t *tcp = (tcp_array)[(num) - 1]; \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22137
		tf_t *tbf; \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22138
		tcp_t *tcpnext; \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22139
		tbf = &tcp_bind_fanout[TCP_BIND_HASH(tcp->tcp_lport)]; \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22140
		mutex_enter(&tbf->tf_lock); \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22141
		tcpnext = tcp->tcp_bind_hash; \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22142
		if (tcpnext) { \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22143
			tcpnext->tcp_ptpbhn = \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22144
				tcp->tcp_ptpbhn; \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22145
		} \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22146
		*tcp->tcp_ptpbhn = tcpnext; \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22147
		mutex_exit(&tbf->tf_lock); \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22148
		kmem_free(tcp, sizeof (tcp_t)); \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22149
		(tcp_array)[(num) - 1] = NULL; \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22150
		(num)--; \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22151
	} \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22152
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22153
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22154
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22155
 * The public interface for other modules to call to reserve a port range
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22156
 * in TCP.  The caller passes in how large a port range it wants.  TCP
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22157
 * 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
 22158
 * used by NCA's nca_conn_init.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22159
 * NCA can only be used in the global zone so this only affects the global
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22160
 * zone's ports.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22161
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22162
 * Params:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22163
 *	int size: the size of the port range to be reserved.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22164
 *	in_port_t *lo_port (referenced): returns the beginning port of the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22165
 *		reserved port range added.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22166
 *	in_port_t *hi_port (referenced): returns the ending port of the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22167
 *		reserved port range added.
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 if the port reservation is successful, 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_add(int size, in_port_t *lo_port, in_port_t *hi_port)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22174
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22175
	tcp_t		*tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22176
	tcp_t		*tmp_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22177
	tcp_t		**temp_tcp_array;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22178
	tf_t		*tbf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22179
	in_port_t	net_port;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22180
	in_port_t	port;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22181
	int32_t		cur_size;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22182
	int		i, j;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22183
	boolean_t	used;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22184
	tcp_rport_t 	tmp_ports[TCP_RESERVED_PORTS_ARRAY_MAX_SIZE];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22185
	zoneid_t	zoneid = GLOBAL_ZONEID;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22186
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22187
	/* Sanity check. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22188
	if (size <= 0 || size > TCP_RESERVED_PORTS_RANGE_MAX) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22189
		return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22190
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22191
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22192
	rw_enter(&tcp_reserved_port_lock, RW_WRITER);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22193
	if (tcp_reserved_port_array_size == TCP_RESERVED_PORTS_ARRAY_MAX_SIZE) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22194
		rw_exit(&tcp_reserved_port_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22195
		return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22196
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22197
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22198
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22199
	 * Find the starting port to try.  Since the port ranges are ordered
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22200
	 * in the reserved port array, we can do a simple search here.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22201
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22202
	*lo_port = TCP_SMALLEST_RESERVED_PORT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22203
	*hi_port = TCP_LARGEST_RESERVED_PORT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22204
	for (i = 0; i < tcp_reserved_port_array_size;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22205
	    *lo_port = tcp_reserved_port[i].hi_port + 1, i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22206
		if (tcp_reserved_port[i].lo_port - *lo_port >= size) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22207
			*hi_port = tcp_reserved_port[i].lo_port - 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22208
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22209
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22210
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22211
	/* No available port range. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22212
	if (i == tcp_reserved_port_array_size && *hi_port - *lo_port < size) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22213
		rw_exit(&tcp_reserved_port_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22214
		return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22215
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22216
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22217
	temp_tcp_array = kmem_zalloc(size * sizeof (tcp_t *), KM_NOSLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22218
	if (temp_tcp_array == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22219
		rw_exit(&tcp_reserved_port_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22220
		return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22221
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22222
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22223
	/* Go thru the port range to see if some ports are already bound. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22224
	for (port = *lo_port, cur_size = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22225
	    cur_size < size && port <= *hi_port;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22226
	    cur_size++, port++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22227
		used = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22228
		net_port = htons(port);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22229
		tbf = &tcp_bind_fanout[TCP_BIND_HASH(net_port)];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22230
		mutex_enter(&tbf->tf_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22231
		for (tcp = tbf->tf_tcp; tcp != NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22232
		    tcp = tcp->tcp_bind_hash) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22233
			if (zoneid == tcp->tcp_connp->conn_zoneid &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22234
			    net_port == tcp->tcp_lport) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22235
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22236
				 * A port is already bound.  Search again
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22237
				 * starting from port + 1.  Release all
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22238
				 * temporary tcps.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22239
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22240
				mutex_exit(&tbf->tf_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22241
				TCP_TMP_TCP_REMOVE(temp_tcp_array, cur_size);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22242
				*lo_port = port + 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22243
				cur_size = -1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22244
				used = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22245
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22246
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22247
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22248
		if (!used) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22249
			if ((tmp_tcp = tcp_alloc_temp_tcp(net_port)) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22250
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22251
				 * Allocation failure.  Just fail the request.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22252
				 * Need to remove all those temporary tcp
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22253
				 * structures.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22254
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22255
				mutex_exit(&tbf->tf_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22256
				TCP_TMP_TCP_REMOVE(temp_tcp_array, cur_size);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22257
				rw_exit(&tcp_reserved_port_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22258
				kmem_free(temp_tcp_array,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22259
				    (hi_port - lo_port + 1) *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22260
				    sizeof (tcp_t *));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22261
				return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22262
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22263
			temp_tcp_array[cur_size] = tmp_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22264
			tcp_bind_hash_insert(tbf, tmp_tcp, B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22265
			mutex_exit(&tbf->tf_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22266
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22267
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22268
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22269
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22270
	 * The current range is not large enough.  We can actually do another
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22271
	 * search if this search is done between 2 reserved port ranges.  But
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22272
	 * for first release, we just stop here and return saying that no port
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22273
	 * range is available.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22274
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22275
	if (cur_size < size) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22276
		TCP_TMP_TCP_REMOVE(temp_tcp_array, cur_size);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22277
		rw_exit(&tcp_reserved_port_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22278
		kmem_free(temp_tcp_array, size * sizeof (tcp_t *));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22279
		return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22280
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22281
	*hi_port = port - 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22282
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22283
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22284
	 * Insert range into array in ascending order.  Since this function
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22285
	 * must not be called often, we choose to use the simplest method.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22286
	 * The above array should not consume excessive stack space as
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22287
	 * the size must be very small.  If in future releases, we find
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22288
	 * that we should provide more reserved port ranges, this function
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22289
	 * has to be modified to be more efficient.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22290
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22291
	if (tcp_reserved_port_array_size == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22292
		tcp_reserved_port[0].lo_port = *lo_port;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22293
		tcp_reserved_port[0].hi_port = *hi_port;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22294
		tcp_reserved_port[0].temp_tcp_array = temp_tcp_array;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22295
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22296
		for (i = 0, j = 0; i < tcp_reserved_port_array_size; i++, j++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22297
			if (*lo_port < tcp_reserved_port[i].lo_port && i == j) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22298
				tmp_ports[j].lo_port = *lo_port;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22299
				tmp_ports[j].hi_port = *hi_port;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22300
				tmp_ports[j].temp_tcp_array = temp_tcp_array;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22301
				j++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22302
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22303
			tmp_ports[j].lo_port = tcp_reserved_port[i].lo_port;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22304
			tmp_ports[j].hi_port = tcp_reserved_port[i].hi_port;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22305
			tmp_ports[j].temp_tcp_array =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22306
			    tcp_reserved_port[i].temp_tcp_array;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22307
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22308
		if (j == i) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22309
			tmp_ports[j].lo_port = *lo_port;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22310
			tmp_ports[j].hi_port = *hi_port;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22311
			tmp_ports[j].temp_tcp_array = temp_tcp_array;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22312
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22313
		bcopy(tmp_ports, tcp_reserved_port, sizeof (tmp_ports));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22314
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22315
	tcp_reserved_port_array_size++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22316
	rw_exit(&tcp_reserved_port_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22317
	return (B_TRUE);
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
 * Check to see if a port is in any reserved port range.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22322
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22323
 * Params:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22324
 *	in_port_t port: the port to be verified.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22325
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22326
 * Return:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22327
 *	B_TRUE is the port is inside a reserved port range, B_FALSE otherwise.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22328
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22329
boolean_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22330
tcp_reserved_port_check(in_port_t port)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22331
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22332
	int i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22333
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22334
	rw_enter(&tcp_reserved_port_lock, RW_READER);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22335
	for (i = 0; i < tcp_reserved_port_array_size; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22336
		if (port >= tcp_reserved_port[i].lo_port ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22337
		    port <= tcp_reserved_port[i].hi_port) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22338
			rw_exit(&tcp_reserved_port_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22339
			return (B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22340
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22341
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22342
	rw_exit(&tcp_reserved_port_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22343
	return (B_FALSE);
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
 * To list all reserved port ranges.  This is the function to handle
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22348
 * ndd tcp_reserved_port_list.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22349
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22350
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22351
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22352
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
 22353
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22354
	int i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22355
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22356
	rw_enter(&tcp_reserved_port_lock, RW_READER);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22357
	if (tcp_reserved_port_array_size > 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22358
		(void) mi_mpprintf(mp, "The following ports are reserved:");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22359
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22360
		(void) mi_mpprintf(mp, "No port is reserved.");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22361
	for (i = 0; i < tcp_reserved_port_array_size; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22362
		(void) mi_mpprintf(mp, "%d-%d",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22363
		    tcp_reserved_port[i].lo_port, tcp_reserved_port[i].hi_port);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22364
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22365
	rw_exit(&tcp_reserved_port_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22366
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22367
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22368
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22369
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22370
 * Hash list insertion routine for tcp_t structures.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22371
 * Inserts entries with the ones bound to a specific IP address first
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22372
 * followed by those bound to INADDR_ANY.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22373
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22374
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22375
tcp_bind_hash_insert(tf_t *tbf, tcp_t *tcp, int caller_holds_lock)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22376
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22377
	tcp_t	**tcpp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22378
	tcp_t	*tcpnext;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22379
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22380
	if (tcp->tcp_ptpbhn != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22381
		ASSERT(!caller_holds_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22382
		tcp_bind_hash_remove(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22383
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22384
	tcpp = &tbf->tf_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22385
	if (!caller_holds_lock) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22386
		mutex_enter(&tbf->tf_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22387
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22388
		ASSERT(MUTEX_HELD(&tbf->tf_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22389
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22390
	tcpnext = tcpp[0];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22391
	if (tcpnext) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22392
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22393
		 * If the new tcp bound to the INADDR_ANY address
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22394
		 * and the first one in the list is not bound to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22395
		 * INADDR_ANY we skip all entries until we find the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22396
		 * first one bound to INADDR_ANY.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22397
		 * This makes sure that applications binding to a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22398
		 * specific address get preference over those binding to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22399
		 * INADDR_ANY.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22400
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22401
		if (V6_OR_V4_INADDR_ANY(tcp->tcp_bound_source_v6) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22402
		    !V6_OR_V4_INADDR_ANY(tcpnext->tcp_bound_source_v6)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22403
			while ((tcpnext = tcpp[0]) != NULL &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22404
			    !V6_OR_V4_INADDR_ANY(tcpnext->tcp_bound_source_v6))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22405
				tcpp = &(tcpnext->tcp_bind_hash);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22406
			if (tcpnext)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22407
				tcpnext->tcp_ptpbhn = &tcp->tcp_bind_hash;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22408
		} else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22409
			tcpnext->tcp_ptpbhn = &tcp->tcp_bind_hash;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22410
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22411
	tcp->tcp_bind_hash = tcpnext;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22412
	tcp->tcp_ptpbhn = tcpp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22413
	tcpp[0] = tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22414
	if (!caller_holds_lock)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22415
		mutex_exit(&tbf->tf_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22416
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22417
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22418
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22419
 * Hash list removal routine for tcp_t structures.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22420
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22421
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22422
tcp_bind_hash_remove(tcp_t *tcp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22423
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22424
	tcp_t	*tcpnext;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22425
	kmutex_t *lockp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22426
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22427
	if (tcp->tcp_ptpbhn == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22428
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22429
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22430
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22431
	 * Extract the lock pointer in case there are concurrent
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22432
	 * hash_remove's for this instance.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22433
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22434
	ASSERT(tcp->tcp_lport != 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22435
	lockp = &tcp_bind_fanout[TCP_BIND_HASH(tcp->tcp_lport)].tf_lock;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22436
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22437
	ASSERT(lockp != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22438
	mutex_enter(lockp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22439
	if (tcp->tcp_ptpbhn) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22440
		tcpnext = tcp->tcp_bind_hash;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22441
		if (tcpnext) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22442
			tcpnext->tcp_ptpbhn = tcp->tcp_ptpbhn;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22443
			tcp->tcp_bind_hash = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22444
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22445
		*tcp->tcp_ptpbhn = tcpnext;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22446
		tcp->tcp_ptpbhn = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22447
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22448
	mutex_exit(lockp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22449
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22450
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22451
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22452
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22453
 * Hash list lookup routine for tcp_t structures.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22454
 * Returns with a CONN_INC_REF tcp structure. Caller must do a CONN_DEC_REF.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22455
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22456
static tcp_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22457
tcp_acceptor_hash_lookup(t_uscalar_t id)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22458
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22459
	tf_t	*tf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22460
	tcp_t	*tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22461
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22462
	tf = &tcp_acceptor_fanout[TCP_ACCEPTOR_HASH(id)];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22463
	mutex_enter(&tf->tf_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22464
	for (tcp = tf->tf_tcp; tcp != NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22465
	    tcp = tcp->tcp_acceptor_hash) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22466
		if (tcp->tcp_acceptor_id == id) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22467
			CONN_INC_REF(tcp->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22468
			mutex_exit(&tf->tf_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22469
			return (tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22470
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22471
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22472
	mutex_exit(&tf->tf_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22473
	return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22474
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22475
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22476
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22477
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22478
 * Hash list insertion routine for tcp_t structures.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22479
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22480
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22481
tcp_acceptor_hash_insert(t_uscalar_t id, tcp_t *tcp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22482
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22483
	tf_t	*tf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22484
	tcp_t	**tcpp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22485
	tcp_t	*tcpnext;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22486
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22487
	tf = &tcp_acceptor_fanout[TCP_ACCEPTOR_HASH(id)];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22488
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22489
	if (tcp->tcp_ptpahn != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22490
		tcp_acceptor_hash_remove(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22491
	tcpp = &tf->tf_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22492
	mutex_enter(&tf->tf_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22493
	tcpnext = tcpp[0];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22494
	if (tcpnext)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22495
		tcpnext->tcp_ptpahn = &tcp->tcp_acceptor_hash;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22496
	tcp->tcp_acceptor_hash = tcpnext;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22497
	tcp->tcp_ptpahn = tcpp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22498
	tcpp[0] = tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22499
	tcp->tcp_acceptor_lockp = &tf->tf_lock;	/* For tcp_*_hash_remove */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22500
	mutex_exit(&tf->tf_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22501
}
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
 * Hash list removal routine for tcp_t structures.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22505
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22506
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22507
tcp_acceptor_hash_remove(tcp_t *tcp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22508
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22509
	tcp_t	*tcpnext;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22510
	kmutex_t *lockp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22511
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22512
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22513
	 * Extract the lock pointer in case there are concurrent
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22514
	 * hash_remove's for this instance.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22515
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22516
	lockp = tcp->tcp_acceptor_lockp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22517
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22518
	if (tcp->tcp_ptpahn == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22519
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22520
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22521
	ASSERT(lockp != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22522
	mutex_enter(lockp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22523
	if (tcp->tcp_ptpahn) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22524
		tcpnext = tcp->tcp_acceptor_hash;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22525
		if (tcpnext) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22526
			tcpnext->tcp_ptpahn = tcp->tcp_ptpahn;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22527
			tcp->tcp_acceptor_hash = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22528
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22529
		*tcp->tcp_ptpahn = tcpnext;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22530
		tcp->tcp_ptpahn = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22531
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22532
	mutex_exit(lockp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22533
	tcp->tcp_acceptor_lockp = NULL;
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
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22537
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22538
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
 22539
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22540
	int error = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22541
	int retval;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22542
	char *end;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22543
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22544
	tcp_hsp_t *hsp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22545
	tcp_hsp_t *hspprev;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22546
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22547
	ipaddr_t addr = 0;		/* Address we're looking for */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22548
	in6_addr_t v6addr;		/* Address we're looking for */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22549
	uint32_t hash;			/* Hash of that address */
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
	 * If the following variables are still zero after parsing the input
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22553
	 * string, the user didn't specify them and we don't change them in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22554
	 * the HSP.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22555
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22556
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22557
	ipaddr_t mask = 0;		/* Subnet mask */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22558
	in6_addr_t v6mask;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22559
	long sendspace = 0;		/* Send buffer size */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22560
	long recvspace = 0;		/* Receive buffer size */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22561
	long timestamp = 0;	/* Originate TCP TSTAMP option, 1 = yes */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22562
	boolean_t delete = B_FALSE;	/* User asked to delete this HSP */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22563
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22564
	rw_enter(&tcp_hsp_lock, RW_WRITER);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22565
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22566
	/* Parse and validate address */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22567
	if (af == AF_INET) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22568
		retval = inet_pton(af, value, &addr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22569
		if (retval == 1)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22570
			IN6_IPADDR_TO_V4MAPPED(addr, &v6addr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22571
	} else if (af == AF_INET6) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22572
		retval = inet_pton(af, value, &v6addr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22573
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22574
		error = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22575
		goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22576
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22577
	if (retval == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22578
		error = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22579
		goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22580
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22581
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22582
	while ((*value) && *value != ' ')
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22583
		value++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22584
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22585
	/* Parse individual keywords, set variables if found */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22586
	while (*value) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22587
		/* Skip leading blanks */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22588
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22589
		while (*value == ' ' || *value == '\t')
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22590
			value++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22591
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22592
		/* If at end of string, we're done */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22593
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22594
		if (!*value)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22595
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22596
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22597
		/* We have a word, figure out what it is */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22598
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22599
		if (strncmp("mask", value, 4) == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22600
			value += 4;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22601
			while (*value == ' ' || *value == '\t')
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22602
				value++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22603
			/* Parse subnet mask */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22604
			if (af == AF_INET) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22605
				retval = inet_pton(af, value, &mask);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22606
				if (retval == 1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22607
					V4MASK_TO_V6(mask, v6mask);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22608
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22609
			} else if (af == AF_INET6) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22610
				retval = inet_pton(af, value, &v6mask);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22611
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22612
			if (retval != 1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22613
				error = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22614
				goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22615
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22616
			while ((*value) && *value != ' ')
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22617
				value++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22618
		} else if (strncmp("sendspace", value, 9) == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22619
			value += 9;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22620
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22621
			if (ddi_strtol(value, &end, 0, &sendspace) != 0 ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22622
			    sendspace < TCP_XMIT_HIWATER ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22623
			    sendspace >= (1L<<30)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22624
				error = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22625
				goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22626
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22627
			value = end;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22628
		} else if (strncmp("recvspace", value, 9) == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22629
			value += 9;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22630
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22631
			if (ddi_strtol(value, &end, 0, &recvspace) != 0 ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22632
			    recvspace < TCP_RECV_HIWATER ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22633
			    recvspace >= (1L<<30)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22634
				error = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22635
				goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22636
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22637
			value = end;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22638
		} else if (strncmp("timestamp", value, 9) == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22639
			value += 9;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22640
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22641
			if (ddi_strtol(value, &end, 0, &timestamp) != 0 ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22642
			    timestamp < 0 || timestamp > 1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22643
				error = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22644
				goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22645
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22646
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22647
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22648
			 * We increment timestamp so we know it's been set;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22649
			 * this is undone when we put it in the HSP
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22650
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22651
			timestamp++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22652
			value = end;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22653
		} else if (strncmp("delete", value, 6) == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22654
			value += 6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22655
			delete = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22656
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22657
			error = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22658
			goto done;
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
	/* Hash address for lookup */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22663
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22664
	hash = TCP_HSP_HASH(addr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22665
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22666
	if (delete) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22667
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22668
		 * Note that deletes don't return an error if the thing
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22669
		 * we're trying to delete isn't there.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22670
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22671
		if (tcp_hsp_hash == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22672
			goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22673
		hsp = tcp_hsp_hash[hash];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22674
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22675
		if (hsp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22676
			if (IN6_ARE_ADDR_EQUAL(&hsp->tcp_hsp_addr_v6,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22677
			    &v6addr)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22678
				tcp_hsp_hash[hash] = hsp->tcp_hsp_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22679
				mi_free((char *)hsp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22680
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22681
				hspprev = hsp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22682
				while ((hsp = hsp->tcp_hsp_next) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22683
					if (IN6_ARE_ADDR_EQUAL(
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22684
					    &hsp->tcp_hsp_addr_v6, &v6addr)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22685
						hspprev->tcp_hsp_next =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22686
						    hsp->tcp_hsp_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22687
						mi_free((char *)hsp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22688
						break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22689
					}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22690
					hspprev = hsp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22691
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22692
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22693
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22694
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22695
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22696
		 * We're adding/modifying an HSP.  If we haven't already done
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22697
		 * so, allocate the hash table.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22698
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22699
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22700
		if (!tcp_hsp_hash) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22701
			tcp_hsp_hash = (tcp_hsp_t **)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22702
			    mi_zalloc(sizeof (tcp_hsp_t *) * TCP_HSP_HASH_SIZE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22703
			if (!tcp_hsp_hash) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22704
				error = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22705
				goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22706
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22707
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22708
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22709
		/* Get head of hash chain */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22710
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22711
		hsp = tcp_hsp_hash[hash];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22712
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22713
		/* Try to find pre-existing hsp on hash chain */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22714
		/* Doesn't handle CIDR prefixes. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22715
		while (hsp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22716
			if (IN6_ARE_ADDR_EQUAL(&hsp->tcp_hsp_addr_v6, &v6addr))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22717
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22718
			hsp = hsp->tcp_hsp_next;
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
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22722
		 * If we didn't, create one with default values and put it
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22723
		 * at head of hash chain
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22724
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22725
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22726
		if (!hsp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22727
			hsp = (tcp_hsp_t *)mi_zalloc(sizeof (tcp_hsp_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22728
			if (!hsp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22729
				error = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22730
				goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22731
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22732
			hsp->tcp_hsp_next = tcp_hsp_hash[hash];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22733
			tcp_hsp_hash[hash] = hsp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22734
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22735
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22736
		/* Set values that the user asked us to change */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22737
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22738
		hsp->tcp_hsp_addr_v6 = v6addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22739
		if (IN6_IS_ADDR_V4MAPPED(&v6addr))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22740
			hsp->tcp_hsp_vers = IPV4_VERSION;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22741
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22742
			hsp->tcp_hsp_vers = IPV6_VERSION;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22743
		hsp->tcp_hsp_subnet_v6 = v6mask;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22744
		if (sendspace > 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22745
			hsp->tcp_hsp_sendspace = sendspace;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22746
		if (recvspace > 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22747
			hsp->tcp_hsp_recvspace = recvspace;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22748
		if (timestamp > 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22749
			hsp->tcp_hsp_tstamp = timestamp - 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22750
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22751
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22752
done:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22753
	rw_exit(&tcp_hsp_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22754
	return (error);
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
/* Set callback routine passed to nd_load by tcp_param_register. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22758
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22759
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22760
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
 22761
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22762
	return (tcp_host_param_setvalue(q, mp, value, cp, AF_INET));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22763
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22764
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22765
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22766
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
 22767
    cred_t *cr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22768
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22769
	return (tcp_host_param_setvalue(q, mp, value, cp, AF_INET6));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22770
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22771
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22772
/* TCP host parameters report triggered via the Named Dispatch mechanism. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22773
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22774
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22775
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
 22776
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22777
	tcp_hsp_t *hsp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22778
	int i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22779
	char addrbuf[INET6_ADDRSTRLEN], subnetbuf[INET6_ADDRSTRLEN];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22780
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22781
	rw_enter(&tcp_hsp_lock, RW_READER);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22782
	(void) mi_mpprintf(mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22783
	    "Hash HSP     " MI_COL_HDRPAD_STR
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22784
	    "Address         Subnet Mask     Send       Receive    TStamp");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22785
	if (tcp_hsp_hash) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22786
		for (i = 0; i < TCP_HSP_HASH_SIZE; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22787
			hsp = tcp_hsp_hash[i];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22788
			while (hsp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22789
				if (hsp->tcp_hsp_vers == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22790
					(void) inet_ntop(AF_INET,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22791
					    &hsp->tcp_hsp_addr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22792
					    addrbuf, sizeof (addrbuf));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22793
					(void) inet_ntop(AF_INET,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22794
					    &hsp->tcp_hsp_subnet,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22795
					    subnetbuf, sizeof (subnetbuf));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22796
				} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22797
					(void) inet_ntop(AF_INET6,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22798
					    &hsp->tcp_hsp_addr_v6,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22799
					    addrbuf, sizeof (addrbuf));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22800
					(void) inet_ntop(AF_INET6,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22801
					    &hsp->tcp_hsp_subnet_v6,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22802
					    subnetbuf, sizeof (subnetbuf));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22803
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22804
				(void) mi_mpprintf(mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22805
				    " %03d " MI_COL_PTRFMT_STR
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22806
				    "%s %s %010d %010d      %d",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22807
				    i,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22808
				    (void *)hsp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22809
				    addrbuf,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22810
				    subnetbuf,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22811
				    hsp->tcp_hsp_sendspace,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22812
				    hsp->tcp_hsp_recvspace,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22813
				    hsp->tcp_hsp_tstamp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22814
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22815
				hsp = hsp->tcp_hsp_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22816
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22817
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22818
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22819
	rw_exit(&tcp_hsp_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22820
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22821
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22822
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22823
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22824
/* Data for fast netmask macro used by tcp_hsp_lookup */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22825
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22826
static ipaddr_t netmasks[] = {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22827
	IN_CLASSA_NET, IN_CLASSA_NET, IN_CLASSB_NET,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22828
	IN_CLASSC_NET | IN_CLASSD_NET  /* Class C,D,E */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22829
};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22830
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22831
#define	netmask(addr) (netmasks[(ipaddr_t)(addr) >> 30])
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22832
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22833
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22834
 * XXX This routine should go away and instead we should use the metrics
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22835
 * associated with the routes to determine the default sndspace and rcvspace.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22836
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22837
static tcp_hsp_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22838
tcp_hsp_lookup(ipaddr_t addr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22839
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22840
	tcp_hsp_t *hsp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22841
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22842
	/* Quick check without acquiring the lock. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22843
	if (tcp_hsp_hash == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22844
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22845
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22846
	rw_enter(&tcp_hsp_lock, RW_READER);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22847
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22848
	/* This routine finds the best-matching HSP for address addr. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22849
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22850
	if (tcp_hsp_hash) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22851
		int i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22852
		ipaddr_t srchaddr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22853
		tcp_hsp_t *hsp_net;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22854
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22855
		/* We do three passes: host, network, and subnet. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22856
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22857
		srchaddr = addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22858
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22859
		for (i = 1; i <= 3; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22860
			/* Look for exact match on srchaddr */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22861
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22862
			hsp = tcp_hsp_hash[TCP_HSP_HASH(srchaddr)];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22863
			while (hsp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22864
				if (hsp->tcp_hsp_vers == IPV4_VERSION &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22865
				    hsp->tcp_hsp_addr == srchaddr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22866
					break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22867
				hsp = hsp->tcp_hsp_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22868
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22869
			ASSERT(hsp == NULL ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22870
			    hsp->tcp_hsp_vers == IPV4_VERSION);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22871
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22872
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22873
			 * If this is the first pass:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22874
			 *   If we found a match, great, return it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22875
			 *   If not, search for the network on the second pass.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22876
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22877
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22878
			if (i == 1)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22879
				if (hsp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22880
					break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22881
				else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22882
				{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22883
					srchaddr = addr & netmask(addr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22884
					continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22885
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22886
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22887
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22888
			 * If this is the second pass:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22889
			 *   If we found a match, but there's a subnet mask,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22890
			 *    save the match but try again using the subnet
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22891
			 *    mask on the third pass.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22892
			 *   Otherwise, return whatever we found.
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
			if (i == 2) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22896
				if (hsp && hsp->tcp_hsp_subnet) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22897
					hsp_net = hsp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22898
					srchaddr = addr & hsp->tcp_hsp_subnet;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22899
					continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22900
				} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22901
					break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22902
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22903
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22904
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22905
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22906
			 * This must be the third pass.  If we didn't find
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22907
			 * anything, return the saved network HSP instead.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22908
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22909
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22910
			if (!hsp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22911
				hsp = hsp_net;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22912
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22913
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22914
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22915
	rw_exit(&tcp_hsp_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22916
	return (hsp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22917
}
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
 * XXX Equally broken as the IPv4 routine. Doesn't handle longest
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22921
 * match lookup.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22922
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22923
static tcp_hsp_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22924
tcp_hsp_lookup_ipv6(in6_addr_t *v6addr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22925
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22926
	tcp_hsp_t *hsp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22927
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22928
	/* Quick check without acquiring the lock. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22929
	if (tcp_hsp_hash == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22930
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22931
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22932
	rw_enter(&tcp_hsp_lock, RW_READER);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22933
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22934
	/* This routine finds the best-matching HSP for address addr. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22935
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22936
	if (tcp_hsp_hash) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22937
		int i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22938
		in6_addr_t v6srchaddr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22939
		tcp_hsp_t *hsp_net;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22940
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22941
		/* We do three passes: host, network, and subnet. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22942
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22943
		v6srchaddr = *v6addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22944
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22945
		for (i = 1; i <= 3; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22946
			/* Look for exact match on srchaddr */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22947
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22948
			hsp = tcp_hsp_hash[TCP_HSP_HASH(
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22949
			    V4_PART_OF_V6(v6srchaddr))];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22950
			while (hsp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22951
				if (hsp->tcp_hsp_vers == IPV6_VERSION &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22952
				    IN6_ARE_ADDR_EQUAL(&hsp->tcp_hsp_addr_v6,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22953
				    &v6srchaddr))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22954
					break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22955
				hsp = hsp->tcp_hsp_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22956
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22957
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22958
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22959
			 * If this is the first pass:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22960
			 *   If we found a match, great, return it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22961
			 *   If not, search for the network on the second pass.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22962
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22963
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22964
			if (i == 1)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22965
				if (hsp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22966
					break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22967
				else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22968
					/* Assume a 64 bit mask */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22969
					v6srchaddr.s6_addr32[0] =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22970
					    v6addr->s6_addr32[0];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22971
					v6srchaddr.s6_addr32[1] =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22972
					    v6addr->s6_addr32[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22973
					v6srchaddr.s6_addr32[2] = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22974
					v6srchaddr.s6_addr32[3] = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22975
					continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22976
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22977
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22978
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22979
			 * If this is the second pass:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22980
			 *   If we found a match, but there's a subnet mask,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22981
			 *    save the match but try again using the subnet
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22982
			 *    mask on the third pass.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22983
			 *   Otherwise, return whatever we found.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22984
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22985
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22986
			if (i == 2) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22987
				ASSERT(hsp == NULL ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22988
				    hsp->tcp_hsp_vers == IPV6_VERSION);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22989
				if (hsp &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22990
				    !IN6_IS_ADDR_UNSPECIFIED(
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22991
				    &hsp->tcp_hsp_subnet_v6)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22992
					hsp_net = hsp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22993
					V6_MASK_COPY(*v6addr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22994
					    hsp->tcp_hsp_subnet_v6, v6srchaddr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22995
					continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22996
				} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22997
					break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22998
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22999
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23000
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23001
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23002
			 * This must be the third pass.  If we didn't find
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23003
			 * anything, return the saved network HSP instead.
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
			if (!hsp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23007
				hsp = hsp_net;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23008
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23009
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23010
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23011
	rw_exit(&tcp_hsp_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23012
	return (hsp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23013
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23014
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23015
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23016
 * Type three generator adapted from the random() function in 4.4 BSD:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23017
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23018
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23019
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23020
 * Copyright (c) 1983, 1993
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23021
 *	The Regents of the University of California.  All rights reserved.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23022
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23023
 * Redistribution and use in source and binary forms, with or without
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23024
 * modification, are permitted provided that the following conditions
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23025
 * are met:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23026
 * 1. Redistributions of source code must retain the above copyright
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23027
 *    notice, this list of conditions and the following disclaimer.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23028
 * 2. Redistributions in binary form must reproduce the above copyright
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23029
 *    notice, this list of conditions and the following disclaimer in the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23030
 *    documentation and/or other materials provided with the distribution.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23031
 * 3. All advertising materials mentioning features or use of this software
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23032
 *    must display the following acknowledgement:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23033
 *	This product includes software developed by the University of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23034
 *	California, Berkeley and its contributors.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23035
 * 4. Neither the name of the University nor the names of its contributors
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23036
 *    may be used to endorse or promote products derived from this software
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23037
 *    without specific prior written permission.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23038
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23039
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23040
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23041
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23042
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23043
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23044
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23045
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23046
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23047
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23048
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23049
 * SUCH DAMAGE.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23050
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23051
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23052
/* Type 3 -- x**31 + x**3 + 1 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23053
#define	DEG_3		31
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23054
#define	SEP_3		3
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23055
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23056
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23057
/* Protected by tcp_random_lock */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23058
static int tcp_randtbl[DEG_3 + 1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23059
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23060
static int *tcp_random_fptr = &tcp_randtbl[SEP_3 + 1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23061
static int *tcp_random_rptr = &tcp_randtbl[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23062
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23063
static int *tcp_random_state = &tcp_randtbl[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23064
static int *tcp_random_end_ptr = &tcp_randtbl[DEG_3 + 1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23065
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23066
kmutex_t tcp_random_lock;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23067
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23068
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23069
tcp_random_init(void)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23070
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23071
	int i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23072
	hrtime_t hrt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23073
	time_t wallclock;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23074
	uint64_t result;
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
	 * Use high-res timer and current time for seed.  Gethrtime() returns
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23078
	 * a longlong, which may contain resolution down to nanoseconds.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23079
	 * The current time will either be a 32-bit or a 64-bit quantity.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23080
	 * XOR the two together in a 64-bit result variable.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23081
	 * Convert the result to a 32-bit value by multiplying the high-order
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23082
	 * 32-bits by the low-order 32-bits.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23083
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23084
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23085
	hrt = gethrtime();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23086
	(void) drv_getparm(TIME, &wallclock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23087
	result = (uint64_t)wallclock ^ (uint64_t)hrt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23088
	mutex_enter(&tcp_random_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23089
	tcp_random_state[0] = ((result >> 32) & 0xffffffff) *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23090
	    (result & 0xffffffff);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23091
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23092
	for (i = 1; i < DEG_3; i++)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23093
		tcp_random_state[i] = 1103515245 * tcp_random_state[i - 1]
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23094
			+ 12345;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23095
	tcp_random_fptr = &tcp_random_state[SEP_3];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23096
	tcp_random_rptr = &tcp_random_state[0];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23097
	mutex_exit(&tcp_random_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23098
	for (i = 0; i < 10 * DEG_3; i++)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23099
		(void) tcp_random();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23100
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23101
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23102
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23103
 * tcp_random: Return a random number in the range [1 - (128K + 1)].
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23104
 * This range is selected to be approximately centered on TCP_ISS / 2,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23105
 * and easy to compute. We get this value by generating a 32-bit random
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23106
 * number, selecting out the high-order 17 bits, and then adding one so
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23107
 * that we never return zero.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23108
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23109
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23110
tcp_random(void)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23111
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23112
	int i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23113
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23114
	mutex_enter(&tcp_random_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23115
	*tcp_random_fptr += *tcp_random_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23116
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23117
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23118
	 * The high-order bits are more random than the low-order bits,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23119
	 * so we select out the high-order 17 bits and add one so that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23120
	 * we never return zero.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23121
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23122
	i = ((*tcp_random_fptr >> 15) & 0x1ffff) + 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23123
	if (++tcp_random_fptr >= tcp_random_end_ptr) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23124
		tcp_random_fptr = tcp_random_state;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23125
		++tcp_random_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23126
	} else if (++tcp_random_rptr >= tcp_random_end_ptr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23127
		tcp_random_rptr = tcp_random_state;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23128
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23129
	mutex_exit(&tcp_random_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23130
	return (i);
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
 * XXX This will go away when TPI is extended to send
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23135
 * info reqs to sockfs/timod .....
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23136
 * Given a queue, set the max packet size for the write
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23137
 * side of the queue below stream head.  This value is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23138
 * cached on the stream head.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23139
 * Returns 1 on success, 0 otherwise.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23140
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23141
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23142
setmaxps(queue_t *q, int maxpsz)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23143
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23144
	struct stdata	*stp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23145
	queue_t		*wq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23146
	stp = STREAM(q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23147
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23148
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23149
	 * At this point change of a queue parameter is not allowed
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23150
	 * when a multiplexor is sitting on top.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23151
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23152
	if (stp->sd_flag & STPLEX)
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
	claimstr(stp->sd_wrq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23156
	wq = stp->sd_wrq->q_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23157
	ASSERT(wq != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23158
	(void) strqset(wq, QMAXPSZ, 0, maxpsz);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23159
	releasestr(stp->sd_wrq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23160
	return (1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23161
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23162
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23163
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23164
tcp_conprim_opt_process(tcp_t *tcp, mblk_t *mp, int *do_disconnectp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23165
    int *t_errorp, int *sys_errorp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23166
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23167
	int error;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23168
	int is_absreq_failure;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23169
	t_scalar_t *opt_lenp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23170
	t_scalar_t opt_offset;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23171
	int prim_type;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23172
	struct T_conn_req *tcreqp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23173
	struct T_conn_res *tcresp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23174
	cred_t *cr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23175
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23176
	cr = DB_CREDDEF(mp, tcp->tcp_cred);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23177
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23178
	prim_type = ((union T_primitives *)mp->b_rptr)->type;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23179
	ASSERT(prim_type == T_CONN_REQ || prim_type == O_T_CONN_RES ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23180
	    prim_type == T_CONN_RES);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23181
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23182
	switch (prim_type) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23183
	case T_CONN_REQ:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23184
		tcreqp = (struct T_conn_req *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23185
		opt_offset = tcreqp->OPT_offset;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23186
		opt_lenp = (t_scalar_t *)&tcreqp->OPT_length;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23187
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23188
	case O_T_CONN_RES:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23189
	case T_CONN_RES:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23190
		tcresp = (struct T_conn_res *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23191
		opt_offset = tcresp->OPT_offset;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23192
		opt_lenp = (t_scalar_t *)&tcresp->OPT_length;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23193
		break;
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
	*t_errorp = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23197
	*sys_errorp = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23198
	*do_disconnectp = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23199
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23200
	error = tpi_optcom_buf(tcp->tcp_wq, mp, opt_lenp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23201
	    opt_offset, cr, &tcp_opt_obj,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23202
	    NULL, &is_absreq_failure);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23203
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23204
	switch (error) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23205
	case  0:		/* no error */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23206
		ASSERT(is_absreq_failure == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23207
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23208
	case ENOPROTOOPT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23209
		*t_errorp = TBADOPT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23210
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23211
	case EACCES:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23212
		*t_errorp = TACCES;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23213
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23214
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23215
		*t_errorp = TSYSERR; *sys_errorp = error;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23216
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23217
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23218
	if (is_absreq_failure != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23219
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23220
		 * The connection request should get the local ack
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23221
		 * T_OK_ACK and then a T_DISCON_IND.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23222
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23223
		*do_disconnectp = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23224
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23225
	return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23226
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23227
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23228
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23229
 * Split this function out so that if the secret changes, I'm okay.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23230
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23231
 * Initialize the tcp_iss_cookie and tcp_iss_key.
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
#define	PASSWD_SIZE 16  /* MUST be multiple of 4 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23235
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23236
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23237
tcp_iss_key_init(uint8_t *phrase, int len)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23238
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23239
	struct {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23240
		int32_t current_time;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23241
		uint32_t randnum;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23242
		uint16_t pad;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23243
		uint8_t ether[6];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23244
		uint8_t passwd[PASSWD_SIZE];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23245
	} tcp_iss_cookie;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23246
	time_t t;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23247
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23248
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23249
	 * Start with the current absolute time.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23250
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23251
	(void) drv_getparm(TIME, &t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23252
	tcp_iss_cookie.current_time = t;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23253
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23254
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23255
	 * XXX - Need a more random number per RFC 1750, not this crap.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23256
	 * OTOH, if what follows is pretty random, then I'm in better shape.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23257
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23258
	tcp_iss_cookie.randnum = (uint32_t)(gethrtime() + tcp_random());
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23259
	tcp_iss_cookie.pad = 0x365c;  /* Picked from HMAC pad values. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23260
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23261
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23262
	 * The cpu_type_info is pretty non-random.  Ugggh.  It does serve
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23263
	 * as a good template.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23264
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23265
	bcopy(&cpu_list->cpu_type_info, &tcp_iss_cookie.passwd,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23266
	    min(PASSWD_SIZE, sizeof (cpu_list->cpu_type_info)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23267
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23268
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23269
	 * The pass-phrase.  Normally this is supplied by user-called NDD.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23270
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23271
	bcopy(phrase, &tcp_iss_cookie.passwd, min(PASSWD_SIZE, len));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23272
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23273
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23274
	 * See 4010593 if this section becomes a problem again,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23275
	 * but the local ethernet address is useful here.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23276
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23277
	(void) localetheraddr(NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23278
	    (struct ether_addr *)&tcp_iss_cookie.ether);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23279
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23280
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23281
	 * Hash 'em all together.  The MD5Final is called per-connection.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23282
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23283
	mutex_enter(&tcp_iss_key_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23284
	MD5Init(&tcp_iss_key);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23285
	MD5Update(&tcp_iss_key, (uchar_t *)&tcp_iss_cookie,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23286
	    sizeof (tcp_iss_cookie));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23287
	mutex_exit(&tcp_iss_key_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23288
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23289
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23290
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23291
 * Set the RFC 1948 pass phrase
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23292
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23293
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23294
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23295
tcp_1948_phrase_set(queue_t *q, mblk_t *mp, char *value, caddr_t cp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23296
    cred_t *cr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23297
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23298
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23299
	 * Basically, value contains a new pass phrase.  Pass it along!
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23300
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23301
	tcp_iss_key_init((uint8_t *)value, strlen(value));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23302
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23303
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23304
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23305
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23306
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23307
tcp_sack_info_constructor(void *buf, void *cdrarg, int kmflags)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23308
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23309
	bzero(buf, sizeof (tcp_sack_info_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23310
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23311
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23312
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23313
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23314
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23315
tcp_iphc_constructor(void *buf, void *cdrarg, int kmflags)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23316
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23317
	bzero(buf, TCP_MAX_COMBINED_HEADER_LENGTH);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23318
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23319
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23320
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23321
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23322
tcp_ddi_init(void)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23323
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23324
	int i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23325
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23326
	/* Initialize locks */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23327
	rw_init(&tcp_hsp_lock, NULL, RW_DEFAULT, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23328
	mutex_init(&tcp_g_q_lock, NULL, MUTEX_DEFAULT, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23329
	mutex_init(&tcp_random_lock, NULL, MUTEX_DEFAULT, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23330
	mutex_init(&tcp_iss_key_lock, NULL, MUTEX_DEFAULT, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23331
	mutex_init(&tcp_epriv_port_lock, NULL, MUTEX_DEFAULT, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23332
	rw_init(&tcp_reserved_port_lock, NULL, RW_DEFAULT, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23333
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23334
	for (i = 0; i < A_CNT(tcp_bind_fanout); i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23335
		mutex_init(&tcp_bind_fanout[i].tf_lock, NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23336
		    MUTEX_DEFAULT, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23337
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23338
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23339
	for (i = 0; i < A_CNT(tcp_acceptor_fanout); i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23340
		mutex_init(&tcp_acceptor_fanout[i].tf_lock, NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23341
		    MUTEX_DEFAULT, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23342
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23343
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23344
	/* TCP's IPsec code calls the packet dropper. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23345
	ip_drop_register(&tcp_dropper, "TCP IPsec policy enforcement");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23346
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23347
	if (!tcp_g_nd) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23348
		if (!tcp_param_register(tcp_param_arr, A_CNT(tcp_param_arr))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23349
			nd_free(&tcp_g_nd);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23350
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23351
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23352
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23353
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23354
	 * Note: To really walk the device tree you need the devinfo
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23355
	 * pointer to your device which is only available after probe/attach.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23356
	 * The following is safe only because it uses ddi_root_node()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23357
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23358
	tcp_max_optsize = optcom_max_optsize(tcp_opt_obj.odb_opt_des_arr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23359
	    tcp_opt_obj.odb_opt_arr_cnt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23360
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23361
	tcp_timercache = kmem_cache_create("tcp_timercache",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23362
	    sizeof (tcp_timer_t) + sizeof (mblk_t), 0,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23363
	    NULL, NULL, NULL, NULL, NULL, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23364
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23365
	tcp_sack_info_cache = kmem_cache_create("tcp_sack_info_cache",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23366
	    sizeof (tcp_sack_info_t), 0,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23367
	    tcp_sack_info_constructor, NULL, NULL, NULL, NULL, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23368
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23369
	tcp_iphc_cache = kmem_cache_create("tcp_iphc_cache",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23370
	    TCP_MAX_COMBINED_HEADER_LENGTH, 0,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23371
	    tcp_iphc_constructor, NULL, NULL, NULL, NULL, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23372
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23373
	tcp_squeue_wput_proc = tcp_squeue_switch(tcp_squeue_wput);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23374
	tcp_squeue_close_proc = tcp_squeue_switch(tcp_squeue_close);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23375
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23376
	ip_squeue_init(tcp_squeue_add);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23377
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23378
	/* Initialize the random number generator */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23379
	tcp_random_init();
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
	 * Initialize RFC 1948 secret values.  This will probably be reset once
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23383
	 * by the boot scripts.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23384
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23385
	 * Use NULL name, as the name is caught by the new lockstats.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23386
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23387
	 * Initialize with some random, non-guessable string, like the global
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23388
	 * T_INFO_ACK.
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
	tcp_iss_key_init((uint8_t *)&tcp_g_t_info_ack,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23392
	    sizeof (tcp_g_t_info_ack));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23393
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 23394
	if ((tcp_kstat = kstat_create(TCP_MOD_NAME, 0, "tcpstat",
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23395
		"net", KSTAT_TYPE_NAMED,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23396
		sizeof (tcp_statistics) / sizeof (kstat_named_t),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23397
		KSTAT_FLAG_VIRTUAL)) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23398
		tcp_kstat->ks_data = &tcp_statistics;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23399
		kstat_install(tcp_kstat);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23400
	}
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 23401
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23402
	tcp_kstat_init();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23403
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23404
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23405
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23406
tcp_ddi_destroy(void)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23407
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23408
	int i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23409
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23410
	nd_free(&tcp_g_nd);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23411
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23412
	for (i = 0; i < A_CNT(tcp_bind_fanout); i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23413
		mutex_destroy(&tcp_bind_fanout[i].tf_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23414
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23415
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23416
	for (i = 0; i < A_CNT(tcp_acceptor_fanout); i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23417
		mutex_destroy(&tcp_acceptor_fanout[i].tf_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23418
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23419
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23420
	mutex_destroy(&tcp_iss_key_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23421
	rw_destroy(&tcp_hsp_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23422
	mutex_destroy(&tcp_g_q_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23423
	mutex_destroy(&tcp_random_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23424
	mutex_destroy(&tcp_epriv_port_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23425
	rw_destroy(&tcp_reserved_port_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23426
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23427
	ip_drop_unregister(&tcp_dropper);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23428
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23429
	kmem_cache_destroy(tcp_timercache);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23430
	kmem_cache_destroy(tcp_sack_info_cache);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23431
	kmem_cache_destroy(tcp_iphc_cache);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23432
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23433
	tcp_kstat_fini();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23434
}
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
 * Generate ISS, taking into account NDD changes may happen halfway through.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23438
 * (If the iss is not zero, set it.)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23439
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23440
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23441
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23442
tcp_iss_init(tcp_t *tcp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23443
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23444
	MD5_CTX context;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23445
	struct { uint32_t ports; in6_addr_t src; in6_addr_t dst; } arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23446
	uint32_t answer[4];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23447
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23448
	tcp_iss_incr_extra += (ISS_INCR >> 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23449
	tcp->tcp_iss = tcp_iss_incr_extra;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23450
	switch (tcp_strong_iss) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23451
	case 2:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23452
		mutex_enter(&tcp_iss_key_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23453
		context = tcp_iss_key;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23454
		mutex_exit(&tcp_iss_key_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23455
		arg.ports = tcp->tcp_ports;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23456
		if (tcp->tcp_ipversion == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23457
			IN6_IPADDR_TO_V4MAPPED(tcp->tcp_ipha->ipha_src,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23458
			    &arg.src);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23459
			IN6_IPADDR_TO_V4MAPPED(tcp->tcp_ipha->ipha_dst,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23460
			    &arg.dst);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23461
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23462
			arg.src = tcp->tcp_ip6h->ip6_src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23463
			arg.dst = tcp->tcp_ip6h->ip6_dst;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23464
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23465
		MD5Update(&context, (uchar_t *)&arg, sizeof (arg));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23466
		MD5Final((uchar_t *)answer, &context);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23467
		tcp->tcp_iss += answer[0] ^ answer[1] ^ answer[2] ^ answer[3];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23468
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23469
		 * Now that we've hashed into a unique per-connection sequence
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23470
		 * space, add a random increment per strong_iss == 1.  So I
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23471
		 * guess we'll have to...
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23472
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23473
		/* FALLTHRU */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23474
	case 1:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23475
		tcp->tcp_iss += (gethrtime() >> ISS_NSEC_SHT) + tcp_random();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23476
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23477
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23478
		tcp->tcp_iss += (uint32_t)gethrestime_sec() * ISS_INCR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23479
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23480
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23481
	tcp->tcp_valid_bits = TCP_ISS_VALID;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23482
	tcp->tcp_fss = tcp->tcp_iss - 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23483
	tcp->tcp_suna = tcp->tcp_iss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23484
	tcp->tcp_snxt = tcp->tcp_iss + 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23485
	tcp->tcp_rexmit_nxt = tcp->tcp_snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23486
	tcp->tcp_csuna = tcp->tcp_snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23487
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23488
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23489
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23490
 * Exported routine for extracting active tcp connection status.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23491
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23492
 * This is used by the Solaris Cluster Networking software to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23493
 * gather a list of connections that need to be forwarded to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23494
 * specific nodes in the cluster when configuration changes occur.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23495
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23496
 * The callback is invoked for each tcp_t structure. Returning
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23497
 * non-zero from the callback routine terminates the search.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23498
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23499
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23500
cl_tcp_walk_list(int (*callback)(cl_tcp_info_t *, void *), void *arg)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23501
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23502
	tcp_t *tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23503
	cl_tcp_info_t	cl_tcpi;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23504
	connf_t	*connfp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23505
	conn_t	*connp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23506
	int	i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23507
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23508
	ASSERT(callback != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23509
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23510
	for (i = 0; i < CONN_G_HASH_SIZE; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23511
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23512
		connfp = &ipcl_globalhash_fanout[i];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23513
		connp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23514
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 23515
		while ((connp =
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 23516
		    ipcl_get_next_conn(connfp, connp, IPCL_TCP)) != NULL) {
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23517
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23518
			tcp = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23519
			cl_tcpi.cl_tcpi_version = CL_TCPI_V1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23520
			cl_tcpi.cl_tcpi_ipversion = tcp->tcp_ipversion;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23521
			cl_tcpi.cl_tcpi_state = tcp->tcp_state;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23522
			cl_tcpi.cl_tcpi_lport = tcp->tcp_lport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23523
			cl_tcpi.cl_tcpi_fport = tcp->tcp_fport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23524
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23525
			 * The macros tcp_laddr and tcp_faddr give the IPv4
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23526
			 * addresses. They are copied implicitly below as
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23527
			 * mapped addresses.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23528
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23529
			cl_tcpi.cl_tcpi_laddr_v6 = tcp->tcp_ip_src_v6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23530
			if (tcp->tcp_ipversion == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23531
				cl_tcpi.cl_tcpi_faddr =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23532
				    tcp->tcp_ipha->ipha_dst;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23533
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23534
				cl_tcpi.cl_tcpi_faddr_v6 =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23535
				    tcp->tcp_ip6h->ip6_dst;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23536
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23537
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23538
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23539
			 * If the callback returns non-zero
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23540
			 * we terminate the traversal.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23541
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23542
			if ((*callback)(&cl_tcpi, arg) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23543
				CONN_DEC_REF(tcp->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23544
				return (1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23545
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23546
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23547
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23548
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23549
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23550
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23551
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23552
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23553
 * Macros used for accessing the different types of sockaddr
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23554
 * structures inside a tcp_ioc_abort_conn_t.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23555
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23556
#define	TCP_AC_V4LADDR(acp) ((sin_t *)&(acp)->ac_local)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23557
#define	TCP_AC_V4RADDR(acp) ((sin_t *)&(acp)->ac_remote)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23558
#define	TCP_AC_V4LOCAL(acp) (TCP_AC_V4LADDR(acp)->sin_addr.s_addr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23559
#define	TCP_AC_V4REMOTE(acp) (TCP_AC_V4RADDR(acp)->sin_addr.s_addr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23560
#define	TCP_AC_V4LPORT(acp) (TCP_AC_V4LADDR(acp)->sin_port)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23561
#define	TCP_AC_V4RPORT(acp) (TCP_AC_V4RADDR(acp)->sin_port)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23562
#define	TCP_AC_V6LADDR(acp) ((sin6_t *)&(acp)->ac_local)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23563
#define	TCP_AC_V6RADDR(acp) ((sin6_t *)&(acp)->ac_remote)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23564
#define	TCP_AC_V6LOCAL(acp) (TCP_AC_V6LADDR(acp)->sin6_addr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23565
#define	TCP_AC_V6REMOTE(acp) (TCP_AC_V6RADDR(acp)->sin6_addr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23566
#define	TCP_AC_V6LPORT(acp) (TCP_AC_V6LADDR(acp)->sin6_port)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23567
#define	TCP_AC_V6RPORT(acp) (TCP_AC_V6RADDR(acp)->sin6_port)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23568
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23569
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23570
 * Return the correct error code to mimic the behavior
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23571
 * of a connection reset.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23572
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23573
#define	TCP_AC_GET_ERRCODE(state, err) {	\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23574
		switch ((state)) {		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23575
		case TCPS_SYN_SENT:		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23576
		case TCPS_SYN_RCVD:		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23577
			(err) = ECONNREFUSED;	\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23578
			break;			\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23579
		case TCPS_ESTABLISHED:		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23580
		case TCPS_FIN_WAIT_1:		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23581
		case TCPS_FIN_WAIT_2:		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23582
		case TCPS_CLOSE_WAIT:		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23583
			(err) = ECONNRESET;	\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23584
			break;			\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23585
		case TCPS_CLOSING:		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23586
		case TCPS_LAST_ACK:		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23587
		case TCPS_TIME_WAIT:		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23588
			(err) = 0;		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23589
			break;			\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23590
		default:			\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23591
			(err) = ENXIO;		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23592
		}				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23593
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23594
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23595
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23596
 * Check if a tcp structure matches the info in acp.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23597
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23598
#define	TCP_AC_ADDR_MATCH(acp, tcp)					\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23599
	(((acp)->ac_local.ss_family == AF_INET) ?		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23600
	((TCP_AC_V4LOCAL((acp)) == INADDR_ANY ||		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23601
	TCP_AC_V4LOCAL((acp)) == (tcp)->tcp_ip_src) &&	\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23602
	(TCP_AC_V4REMOTE((acp)) == INADDR_ANY ||		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23603
	TCP_AC_V4REMOTE((acp)) == (tcp)->tcp_remote) &&	\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23604
	(TCP_AC_V4LPORT((acp)) == 0 ||				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23605
	TCP_AC_V4LPORT((acp)) == (tcp)->tcp_lport) &&		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23606
	(TCP_AC_V4RPORT((acp)) == 0 ||				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23607
	TCP_AC_V4RPORT((acp)) == (tcp)->tcp_fport) &&		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23608
	(acp)->ac_start <= (tcp)->tcp_state &&	\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23609
	(acp)->ac_end >= (tcp)->tcp_state) :		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23610
	((IN6_IS_ADDR_UNSPECIFIED(&TCP_AC_V6LOCAL((acp))) ||	\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23611
	IN6_ARE_ADDR_EQUAL(&TCP_AC_V6LOCAL((acp)),		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23612
	&(tcp)->tcp_ip_src_v6)) &&				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23613
	(IN6_IS_ADDR_UNSPECIFIED(&TCP_AC_V6REMOTE((acp))) ||	\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23614
	IN6_ARE_ADDR_EQUAL(&TCP_AC_V6REMOTE((acp)),		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23615
	&(tcp)->tcp_remote_v6)) &&				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23616
	(TCP_AC_V6LPORT((acp)) == 0 ||				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23617
	TCP_AC_V6LPORT((acp)) == (tcp)->tcp_lport) &&		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23618
	(TCP_AC_V6RPORT((acp)) == 0 ||				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23619
	TCP_AC_V6RPORT((acp)) == (tcp)->tcp_fport) &&		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23620
	(acp)->ac_start <= (tcp)->tcp_state &&	\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23621
	(acp)->ac_end >= (tcp)->tcp_state))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23622
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23623
#define	TCP_AC_MATCH(acp, tcp)					\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23624
	(((acp)->ac_zoneid == ALL_ZONES ||			\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23625
	(acp)->ac_zoneid == tcp->tcp_connp->conn_zoneid) ?	\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23626
	TCP_AC_ADDR_MATCH(acp, tcp) : 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23627
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23628
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23629
 * Build a message containing a tcp_ioc_abort_conn_t structure
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23630
 * which is filled in with information from acp and tp.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23631
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23632
static mblk_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23633
tcp_ioctl_abort_build_msg(tcp_ioc_abort_conn_t *acp, tcp_t *tp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23634
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23635
	mblk_t *mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23636
	tcp_ioc_abort_conn_t *tacp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23637
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23638
	mp = allocb(sizeof (uint32_t) + sizeof (*acp), BPRI_LO);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23639
	if (mp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23640
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23641
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23642
	mp->b_datap->db_type = M_CTL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23643
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23644
	*((uint32_t *)mp->b_rptr) = TCP_IOC_ABORT_CONN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23645
	tacp = (tcp_ioc_abort_conn_t *)((uchar_t *)mp->b_rptr +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23646
		sizeof (uint32_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23647
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23648
	tacp->ac_start = acp->ac_start;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23649
	tacp->ac_end = acp->ac_end;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23650
	tacp->ac_zoneid = acp->ac_zoneid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23651
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23652
	if (acp->ac_local.ss_family == AF_INET) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23653
		tacp->ac_local.ss_family = AF_INET;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23654
		tacp->ac_remote.ss_family = AF_INET;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23655
		TCP_AC_V4LOCAL(tacp) = tp->tcp_ip_src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23656
		TCP_AC_V4REMOTE(tacp) = tp->tcp_remote;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23657
		TCP_AC_V4LPORT(tacp) = tp->tcp_lport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23658
		TCP_AC_V4RPORT(tacp) = tp->tcp_fport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23659
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23660
		tacp->ac_local.ss_family = AF_INET6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23661
		tacp->ac_remote.ss_family = AF_INET6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23662
		TCP_AC_V6LOCAL(tacp) = tp->tcp_ip_src_v6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23663
		TCP_AC_V6REMOTE(tacp) = tp->tcp_remote_v6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23664
		TCP_AC_V6LPORT(tacp) = tp->tcp_lport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23665
		TCP_AC_V6RPORT(tacp) = tp->tcp_fport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23666
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23667
	mp->b_wptr = (uchar_t *)mp->b_rptr + sizeof (uint32_t) + sizeof (*acp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23668
	return (mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23669
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23670
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23671
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23672
 * Print a tcp_ioc_abort_conn_t structure.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23673
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23674
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23675
tcp_ioctl_abort_dump(tcp_ioc_abort_conn_t *acp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23676
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23677
	char lbuf[128];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23678
	char rbuf[128];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23679
	sa_family_t af;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23680
	in_port_t lport, rport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23681
	ushort_t logflags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23682
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23683
	af = acp->ac_local.ss_family;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23684
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23685
	if (af == AF_INET) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23686
		(void) inet_ntop(af, (const void *)&TCP_AC_V4LOCAL(acp),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23687
				lbuf, 128);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23688
		(void) inet_ntop(af, (const void *)&TCP_AC_V4REMOTE(acp),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23689
				rbuf, 128);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23690
		lport = ntohs(TCP_AC_V4LPORT(acp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23691
		rport = ntohs(TCP_AC_V4RPORT(acp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23692
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23693
		(void) inet_ntop(af, (const void *)&TCP_AC_V6LOCAL(acp),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23694
				lbuf, 128);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23695
		(void) inet_ntop(af, (const void *)&TCP_AC_V6REMOTE(acp),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23696
				rbuf, 128);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23697
		lport = ntohs(TCP_AC_V6LPORT(acp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23698
		rport = ntohs(TCP_AC_V6RPORT(acp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23699
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23700
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23701
	logflags = SL_TRACE | SL_NOTE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23702
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23703
	 * Don't print this message to the console if the operation was done
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23704
	 * to a non-global zone.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23705
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23706
	if (acp->ac_zoneid == GLOBAL_ZONEID || acp->ac_zoneid == ALL_ZONES)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23707
		logflags |= SL_CONSOLE;
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 23708
	(void) strlog(TCP_MOD_ID, 0, 1, logflags,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23709
		"TCP_IOC_ABORT_CONN: local = %s:%d, remote = %s:%d, "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23710
		"start = %d, end = %d\n", lbuf, lport, rbuf, rport,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23711
		acp->ac_start, acp->ac_end);
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
 * Called inside tcp_rput when a message built using
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23716
 * tcp_ioctl_abort_build_msg is put into a queue.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23717
 * Note that when we get here there is no wildcard in acp any more.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23718
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23719
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23720
tcp_ioctl_abort_handler(tcp_t *tcp, mblk_t *mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23721
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23722
	tcp_ioc_abort_conn_t *acp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23723
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23724
	acp = (tcp_ioc_abort_conn_t *)(mp->b_rptr + sizeof (uint32_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23725
	if (tcp->tcp_state <= acp->ac_end) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23726
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23727
		 * If we get here, we are already on the correct
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23728
		 * squeue. This ioctl follows the following path
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23729
		 * tcp_wput -> tcp_wput_ioctl -> tcp_ioctl_abort_conn
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23730
		 * ->tcp_ioctl_abort->squeue_fill (if on a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23731
		 * different squeue)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23732
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23733
		int errcode;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23734
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23735
		TCP_AC_GET_ERRCODE(tcp->tcp_state, errcode);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23736
		(void) tcp_clean_death(tcp, errcode, 26);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23737
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23738
	freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23739
}
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
 * Abort all matching connections on a hash chain.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23743
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23744
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23745
tcp_ioctl_abort_bucket(tcp_ioc_abort_conn_t *acp, int index, int *count,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23746
    boolean_t exact)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23747
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23748
	int nmatch, err = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23749
	tcp_t *tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23750
	MBLKP mp, last, listhead = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23751
	conn_t	*tconnp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23752
	connf_t	*connfp = &ipcl_conn_fanout[index];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23753
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23754
startover:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23755
	nmatch = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23756
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23757
	mutex_enter(&connfp->connf_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23758
	for (tconnp = connfp->connf_head; tconnp != NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23759
	    tconnp = tconnp->conn_next) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23760
		tcp = tconnp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23761
		if (TCP_AC_MATCH(acp, tcp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23762
			CONN_INC_REF(tcp->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23763
			mp = tcp_ioctl_abort_build_msg(acp, tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23764
			if (mp == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23765
				err = ENOMEM;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23766
				CONN_DEC_REF(tcp->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23767
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23768
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23769
			mp->b_prev = (mblk_t *)tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23770
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23771
			if (listhead == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23772
				listhead = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23773
				last = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23774
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23775
				last->b_next = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23776
				last = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23777
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23778
			nmatch++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23779
			if (exact)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23780
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23781
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23782
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23783
		/* Avoid holding lock for too long. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23784
		if (nmatch >= 500)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23785
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23786
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23787
	mutex_exit(&connfp->connf_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23788
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23789
	/* Pass mp into the correct tcp */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23790
	while ((mp = listhead) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23791
		listhead = listhead->b_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23792
		tcp = (tcp_t *)mp->b_prev;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23793
		mp->b_next = mp->b_prev = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23794
		squeue_fill(tcp->tcp_connp->conn_sqp, mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23795
		    tcp_input, tcp->tcp_connp, SQTAG_TCP_ABORT_BUCKET);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23796
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23797
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23798
	*count += nmatch;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23799
	if (nmatch >= 500 && err == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23800
		goto startover;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23801
	return (err);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23802
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23803
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23804
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23805
 * Abort all connections that matches the attributes specified in acp.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23806
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23807
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23808
tcp_ioctl_abort(tcp_ioc_abort_conn_t *acp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23809
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23810
	sa_family_t af;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23811
	uint32_t  ports;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23812
	uint16_t *pports;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23813
	int err = 0, count = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23814
	boolean_t exact = B_FALSE; /* set when there is no wildcard */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23815
	int index = -1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23816
	ushort_t logflags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23817
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23818
	af = acp->ac_local.ss_family;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23819
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23820
	if (af == AF_INET) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23821
		if (TCP_AC_V4REMOTE(acp) != INADDR_ANY &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23822
		    TCP_AC_V4LPORT(acp) != 0 && TCP_AC_V4RPORT(acp) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23823
			pports = (uint16_t *)&ports;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23824
			pports[1] = TCP_AC_V4LPORT(acp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23825
			pports[0] = TCP_AC_V4RPORT(acp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23826
			exact = (TCP_AC_V4LOCAL(acp) != INADDR_ANY);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23827
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23828
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23829
		if (!IN6_IS_ADDR_UNSPECIFIED(&TCP_AC_V6REMOTE(acp)) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23830
		    TCP_AC_V6LPORT(acp) != 0 && TCP_AC_V6RPORT(acp) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23831
			pports = (uint16_t *)&ports;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23832
			pports[1] = TCP_AC_V6LPORT(acp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23833
			pports[0] = TCP_AC_V6RPORT(acp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23834
			exact = !IN6_IS_ADDR_UNSPECIFIED(&TCP_AC_V6LOCAL(acp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23835
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23836
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23837
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23838
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23839
	 * For cases where remote addr, local port, and remote port are non-
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23840
	 * wildcards, tcp_ioctl_abort_bucket will only be called once.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23841
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23842
	if (index != -1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23843
		err = tcp_ioctl_abort_bucket(acp, index,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23844
			    &count, exact);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23845
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23846
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23847
		 * loop through all entries for wildcard case
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23848
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23849
		for (index = 0; index < ipcl_conn_fanout_size; index++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23850
			err = tcp_ioctl_abort_bucket(acp, index,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23851
			    &count, exact);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23852
			if (err != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23853
				break;
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
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23857
	logflags = SL_TRACE | SL_NOTE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23858
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23859
	 * Don't print this message to the console if the operation was done
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23860
	 * to a non-global zone.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23861
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23862
	if (acp->ac_zoneid == GLOBAL_ZONEID || acp->ac_zoneid == ALL_ZONES)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23863
		logflags |= SL_CONSOLE;
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 23864
	(void) strlog(TCP_MOD_ID, 0, 1, logflags, "TCP_IOC_ABORT_CONN: "
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23865
	    "aborted %d connection%c\n", count, ((count > 1) ? 's' : ' '));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23866
	if (err == 0 && count == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23867
		err = ENOENT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23868
	return (err);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23869
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23870
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23871
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23872
 * Process the TCP_IOC_ABORT_CONN ioctl request.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23873
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23874
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23875
tcp_ioctl_abort_conn(queue_t *q, mblk_t *mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23876
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23877
	int	err;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23878
	IOCP    iocp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23879
	MBLKP   mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23880
	sa_family_t laf, raf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23881
	tcp_ioc_abort_conn_t *acp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23882
	zone_t *zptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23883
	zoneid_t zoneid = Q_TO_CONN(q)->conn_zoneid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23884
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23885
	iocp = (IOCP)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23886
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23887
	if ((mp1 = mp->b_cont) == NULL ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23888
	    iocp->ioc_count != sizeof (tcp_ioc_abort_conn_t)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23889
		err = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23890
		goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23891
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23892
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23893
	/* check permissions */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23894
	if (secpolicy_net_config(iocp->ioc_cr, B_FALSE) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23895
		err = EPERM;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23896
		goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23897
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23898
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23899
	if (mp1->b_cont != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23900
		freemsg(mp1->b_cont);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23901
		mp1->b_cont = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23902
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23903
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23904
	acp = (tcp_ioc_abort_conn_t *)mp1->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23905
	laf = acp->ac_local.ss_family;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23906
	raf = acp->ac_remote.ss_family;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23907
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23908
	/* check that a zone with the supplied zoneid exists */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23909
	if (acp->ac_zoneid != GLOBAL_ZONEID && acp->ac_zoneid != ALL_ZONES) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23910
		zptr = zone_find_by_id(zoneid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23911
		if (zptr != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23912
			zone_rele(zptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23913
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23914
			err = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23915
			goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23916
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23917
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23918
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23919
	if (acp->ac_start < TCPS_SYN_SENT || acp->ac_end > TCPS_TIME_WAIT ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23920
	    acp->ac_start > acp->ac_end || laf != raf ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23921
	    (laf != AF_INET && laf != AF_INET6)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23922
		err = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23923
		goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23924
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23925
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23926
	tcp_ioctl_abort_dump(acp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23927
	err = tcp_ioctl_abort(acp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23928
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23929
out:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23930
	if (mp1 != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23931
		freemsg(mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23932
		mp->b_cont = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23933
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23934
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23935
	if (err != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23936
		miocnak(q, mp, 0, err);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23937
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23938
		miocack(q, mp, 0, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23939
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23940
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23941
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23942
 * tcp_time_wait_processing() handles processing of incoming packets when
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23943
 * the tcp is in the TIME_WAIT state.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23944
 * A TIME_WAIT tcp that has an associated open TCP stream is never put
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23945
 * on the time wait list.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23946
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23947
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23948
tcp_time_wait_processing(tcp_t *tcp, mblk_t *mp, uint32_t seg_seq,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23949
    uint32_t seg_ack, int seg_len, tcph_t *tcph)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23950
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23951
	int32_t		bytes_acked;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23952
	int32_t		gap;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23953
	int32_t		rgap;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23954
	tcp_opt_t	tcpopt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23955
	uint_t		flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23956
	uint32_t	new_swnd = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23957
	conn_t		*connp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23958
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23959
	BUMP_LOCAL(tcp->tcp_ibsegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23960
	TCP_RECORD_TRACE(tcp, mp, TCP_TRACE_RECV_PKT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23961
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23962
	flags = (unsigned int)tcph->th_flags[0] & 0xFF;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23963
	new_swnd = BE16_TO_U16(tcph->th_win) <<
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23964
	    ((tcph->th_flags[0] & TH_SYN) ? 0 : tcp->tcp_snd_ws);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23965
	if (tcp->tcp_snd_ts_ok) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23966
		if (!tcp_paws_check(tcp, tcph, &tcpopt)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23967
			tcp_xmit_ctl(NULL, tcp, tcp->tcp_snxt,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23968
			    tcp->tcp_rnxt, TH_ACK);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23969
			goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23970
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23971
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23972
	gap = seg_seq - tcp->tcp_rnxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23973
	rgap = tcp->tcp_rwnd - (gap + seg_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23974
	if (gap < 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23975
		BUMP_MIB(&tcp_mib, tcpInDataDupSegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23976
		UPDATE_MIB(&tcp_mib, tcpInDataDupBytes,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23977
		    (seg_len > -gap ? -gap : seg_len));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23978
		seg_len += gap;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23979
		if (seg_len < 0 || (seg_len == 0 && !(flags & TH_FIN))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23980
			if (flags & TH_RST) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23981
				goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23982
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23983
			if ((flags & TH_FIN) && seg_len == -1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23984
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23985
				 * When TCP receives a duplicate FIN in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23986
				 * TIME_WAIT state, restart the 2 MSL timer.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23987
				 * See page 73 in RFC 793. Make sure this TCP
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23988
				 * is already on the TIME_WAIT list. If not,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23989
				 * just restart the timer.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23990
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23991
				if (TCP_IS_DETACHED(tcp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23992
					tcp_time_wait_remove(tcp, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23993
					tcp_time_wait_append(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23994
					TCP_DBGSTAT(tcp_rput_time_wait);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23995
				} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23996
					ASSERT(tcp != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23997
					TCP_TIMER_RESTART(tcp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23998
					    tcp_time_wait_interval);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23999
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24000
				tcp_xmit_ctl(NULL, tcp, tcp->tcp_snxt,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24001
				    tcp->tcp_rnxt, TH_ACK);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24002
				goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24003
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24004
			flags |=  TH_ACK_NEEDED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24005
			seg_len = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24006
			goto process_ack;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24007
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24008
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24009
		/* Fix seg_seq, and chew the gap off the front. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24010
		seg_seq = tcp->tcp_rnxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24011
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24012
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24013
	if ((flags & TH_SYN) && gap > 0 && rgap < 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24014
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24015
		 * Make sure that when we accept the connection, pick
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24016
		 * an ISS greater than (tcp_snxt + ISS_INCR/2) for the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24017
		 * old connection.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24018
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24019
		 * The next ISS generated is equal to tcp_iss_incr_extra
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24020
		 * + ISS_INCR/2 + other components depending on the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24021
		 * value of tcp_strong_iss.  We pre-calculate the new
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24022
		 * ISS here and compare with tcp_snxt to determine if
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24023
		 * we need to make adjustment to tcp_iss_incr_extra.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24024
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24025
		 * The above calculation is ugly and is a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24026
		 * waste of CPU cycles...
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24027
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24028
		uint32_t new_iss = tcp_iss_incr_extra;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24029
		int32_t adj;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24030
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24031
		switch (tcp_strong_iss) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24032
		case 2: {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24033
			/* Add time and MD5 components. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24034
			uint32_t answer[4];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24035
			struct {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24036
				uint32_t ports;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24037
				in6_addr_t src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24038
				in6_addr_t dst;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24039
			} arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24040
			MD5_CTX context;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24041
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24042
			mutex_enter(&tcp_iss_key_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24043
			context = tcp_iss_key;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24044
			mutex_exit(&tcp_iss_key_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24045
			arg.ports = tcp->tcp_ports;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24046
			/* We use MAPPED addresses in tcp_iss_init */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24047
			arg.src = tcp->tcp_ip_src_v6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24048
			if (tcp->tcp_ipversion == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24049
				IN6_IPADDR_TO_V4MAPPED(
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24050
					tcp->tcp_ipha->ipha_dst,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24051
					    &arg.dst);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24052
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24053
				arg.dst =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24054
				    tcp->tcp_ip6h->ip6_dst;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24055
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24056
			MD5Update(&context, (uchar_t *)&arg,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24057
			    sizeof (arg));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24058
			MD5Final((uchar_t *)answer, &context);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24059
			answer[0] ^= answer[1] ^ answer[2] ^ answer[3];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24060
			new_iss += (gethrtime() >> ISS_NSEC_SHT) + answer[0];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24061
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24062
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24063
		case 1:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24064
			/* Add time component and min random (i.e. 1). */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24065
			new_iss += (gethrtime() >> ISS_NSEC_SHT) + 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24066
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24067
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24068
			/* Add only time component. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24069
			new_iss += (uint32_t)gethrestime_sec() * ISS_INCR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24070
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24071
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24072
		if ((adj = (int32_t)(tcp->tcp_snxt - new_iss)) > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24073
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24074
			 * New ISS not guaranteed to be ISS_INCR/2
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24075
			 * ahead of the current tcp_snxt, so add the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24076
			 * difference to tcp_iss_incr_extra.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24077
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24078
			tcp_iss_incr_extra += adj;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24079
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24080
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24081
		 * If tcp_clean_death() can not perform the task now,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24082
		 * drop the SYN packet and let the other side re-xmit.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24083
		 * Otherwise pass the SYN packet back in, since the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24084
		 * old tcp state has been cleaned up or freed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24085
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24086
		if (tcp_clean_death(tcp, 0, 27) == -1)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24087
			goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24088
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24089
		 * We will come back to tcp_rput_data
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24090
		 * on the global queue. Packets destined
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24091
		 * for the global queue will be checked
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24092
		 * with global policy. But the policy for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24093
		 * this packet has already been checked as
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24094
		 * this was destined for the detached
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24095
		 * connection. We need to bypass policy
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24096
		 * check this time by attaching a dummy
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24097
		 * ipsec_in with ipsec_in_dont_check set.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24098
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24099
		if ((connp = ipcl_classify(mp, tcp->tcp_connp->conn_zoneid)) !=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24100
		    NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24101
			TCP_STAT(tcp_time_wait_syn_success);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24102
			tcp_reinput(connp, mp, tcp->tcp_connp->conn_sqp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24103
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24104
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24105
		goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24106
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24107
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24108
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24109
	 * rgap is the amount of stuff received out of window.  A negative
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24110
	 * value is the amount out of window.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24111
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24112
	if (rgap < 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24113
		BUMP_MIB(&tcp_mib, tcpInDataPastWinSegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24114
		UPDATE_MIB(&tcp_mib, tcpInDataPastWinBytes, -rgap);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24115
		/* Fix seg_len and make sure there is something left. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24116
		seg_len += rgap;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24117
		if (seg_len <= 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24118
			if (flags & TH_RST) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24119
				goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24120
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24121
			flags |=  TH_ACK_NEEDED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24122
			seg_len = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24123
			goto process_ack;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24124
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24125
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24126
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24127
	 * Check whether we can update tcp_ts_recent.  This test is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24128
	 * NOT the one in RFC 1323 3.4.  It is from Braden, 1993, "TCP
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24129
	 * Extensions for High Performance: An Update", Internet Draft.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24130
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24131
	if (tcp->tcp_snd_ts_ok &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24132
	    TSTMP_GEQ(tcpopt.tcp_opt_ts_val, tcp->tcp_ts_recent) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24133
	    SEQ_LEQ(seg_seq, tcp->tcp_rack)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24134
		tcp->tcp_ts_recent = tcpopt.tcp_opt_ts_val;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24135
		tcp->tcp_last_rcv_lbolt = lbolt64;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24136
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24137
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24138
	if (seg_seq != tcp->tcp_rnxt && seg_len > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24139
		/* Always ack out of order packets */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24140
		flags |= TH_ACK_NEEDED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24141
		seg_len = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24142
	} else if (seg_len > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24143
		BUMP_MIB(&tcp_mib, tcpInClosed);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24144
		BUMP_MIB(&tcp_mib, tcpInDataInorderSegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24145
		UPDATE_MIB(&tcp_mib, tcpInDataInorderBytes, seg_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24146
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24147
	if (flags & TH_RST) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24148
		(void) tcp_clean_death(tcp, 0, 28);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24149
		goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24150
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24151
	if (flags & TH_SYN) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24152
		tcp_xmit_ctl("TH_SYN", tcp, seg_ack, seg_seq + 1,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24153
		    TH_RST|TH_ACK);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24154
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24155
		 * Do not delete the TCP structure if it is in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24156
		 * TIME_WAIT state.  Refer to RFC 1122, 4.2.2.13.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24157
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24158
		goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24159
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24160
process_ack:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24161
	if (flags & TH_ACK) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24162
		bytes_acked = (int)(seg_ack - tcp->tcp_suna);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24163
		if (bytes_acked <= 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24164
			if (bytes_acked == 0 && seg_len == 0 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24165
			    new_swnd == tcp->tcp_swnd)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24166
				BUMP_MIB(&tcp_mib, tcpInDupAck);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24167
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24168
			/* Acks something not sent */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24169
			flags |= TH_ACK_NEEDED;
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
	if (flags & TH_ACK_NEEDED) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24173
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24174
		 * Time to send an ack for some reason.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24175
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24176
		tcp_xmit_ctl(NULL, tcp, tcp->tcp_snxt,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24177
		    tcp->tcp_rnxt, TH_ACK);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24178
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24179
done:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24180
	if ((mp->b_datap->db_struioflag & STRUIO_EAGER) != 0) {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24181
		DB_CKSUMSTART(mp) = 0;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24182
		mp->b_datap->db_struioflag &= ~STRUIO_EAGER;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24183
		TCP_STAT(tcp_time_wait_syn_fail);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24184
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24185
	freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24186
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24187
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24188
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24189
 * Return zero if the buffers are identical in length and content.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24190
 * This is used for comparing extension header buffers.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24191
 * Note that an extension header would be declared different
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24192
 * even if all that changed was the next header value in that header i.e.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24193
 * what really changed is the next extension header.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24194
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24195
static boolean_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24196
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
 24197
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24198
	if (!b_valid)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24199
		blen = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24200
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24201
	if (alen != blen)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24202
		return (B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24203
	if (alen == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24204
		return (B_FALSE);	/* Both zero length */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24205
	return (bcmp(a, b, alen));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24206
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24207
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24208
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24209
 * Preallocate memory for tcp_savebuf(). Returns B_TRUE if ok.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24210
 * Return B_FALSE if memory allocation fails - don't change any state!
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24211
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24212
static boolean_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24213
tcp_allocbuf(void **dstp, uint_t *dstlenp, boolean_t src_valid,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24214
    void *src, uint_t srclen)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24215
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24216
	void *dst;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24217
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24218
	if (!src_valid)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24219
		srclen = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24220
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24221
	ASSERT(*dstlenp == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24222
	if (src != NULL && srclen != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24223
		dst = mi_alloc(srclen, BPRI_MED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24224
		if (dst == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24225
			return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24226
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24227
		dst = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24228
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24229
	if (*dstp != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24230
		mi_free(*dstp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24231
		*dstp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24232
		*dstlenp = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24233
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24234
	*dstp = dst;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24235
	if (dst != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24236
		*dstlenp = srclen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24237
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24238
		*dstlenp = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24239
	return (B_TRUE);
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
 * Replace what is in *dst, *dstlen with the source.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24244
 * Assumes tcp_allocbuf has already been called.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24245
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24246
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24247
tcp_savebuf(void **dstp, uint_t *dstlenp, boolean_t src_valid,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24248
    void *src, uint_t srclen)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24249
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24250
	if (!src_valid)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24251
		srclen = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24252
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24253
	ASSERT(*dstlenp == srclen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24254
	if (src != NULL && srclen != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24255
		bcopy(src, *dstp, srclen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24256
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24257
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24258
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24259
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24260
 * Allocate a T_SVR4_OPTMGMT_REQ.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24261
 * The caller needs to increment tcp_drop_opt_ack_cnt when sending these so
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24262
 * that tcp_rput_other can drop the acks.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24263
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24264
static mblk_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24265
tcp_setsockopt_mp(int level, int cmd, char *opt, int optlen)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24266
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24267
	mblk_t *mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24268
	struct T_optmgmt_req *tor;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24269
	struct opthdr *oh;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24270
	uint_t size;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24271
	char *optptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24272
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24273
	size = sizeof (*tor) + sizeof (*oh) + optlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24274
	mp = allocb(size, BPRI_MED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24275
	if (mp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24276
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24277
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24278
	mp->b_wptr += size;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24279
	mp->b_datap->db_type = M_PROTO;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24280
	tor = (struct T_optmgmt_req *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24281
	tor->PRIM_type = T_SVR4_OPTMGMT_REQ;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24282
	tor->MGMT_flags = T_NEGOTIATE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24283
	tor->OPT_length = sizeof (*oh) + optlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24284
	tor->OPT_offset = (t_scalar_t)sizeof (*tor);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24285
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24286
	oh = (struct opthdr *)&tor[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24287
	oh->level = level;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24288
	oh->name = cmd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24289
	oh->len = optlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24290
	if (optlen != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24291
		optptr = (char *)&oh[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24292
		bcopy(opt, optptr, optlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24293
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24294
	return (mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24295
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24296
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24297
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24298
 * TCP Timers Implementation.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24299
 */
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24300
timeout_id_t
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24301
tcp_timeout(conn_t *connp, void (*f)(void *), clock_t tim)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24302
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24303
	mblk_t *mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24304
	tcp_timer_t *tcpt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24305
	tcp_t *tcp = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24306
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24307
	ASSERT(connp->conn_sqp != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24308
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24309
	TCP_DBGSTAT(tcp_timeout_calls);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24310
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24311
	if (tcp->tcp_timercache == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24312
		mp = tcp_timermp_alloc(KM_NOSLEEP | KM_PANIC);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24313
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24314
		TCP_DBGSTAT(tcp_timeout_cached_alloc);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24315
		mp = tcp->tcp_timercache;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24316
		tcp->tcp_timercache = mp->b_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24317
		mp->b_next = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24318
		ASSERT(mp->b_wptr == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24319
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24320
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24321
	CONN_INC_REF(connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24322
	tcpt = (tcp_timer_t *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24323
	tcpt->connp = connp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24324
	tcpt->tcpt_proc = f;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24325
	tcpt->tcpt_tid = timeout(tcp_timer_callback, mp, tim);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24326
	return ((timeout_id_t)mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24327
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24328
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24329
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24330
tcp_timer_callback(void *arg)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24331
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24332
	mblk_t *mp = (mblk_t *)arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24333
	tcp_timer_t *tcpt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24334
	conn_t	*connp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24335
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24336
	tcpt = (tcp_timer_t *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24337
	connp = tcpt->connp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24338
	squeue_fill(connp->conn_sqp, mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24339
	    tcp_timer_handler, connp, SQTAG_TCP_TIMER);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24340
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24341
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24342
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24343
tcp_timer_handler(void *arg, mblk_t *mp, void *arg2)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24344
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24345
	tcp_timer_t *tcpt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24346
	conn_t *connp = (conn_t *)arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24347
	tcp_t *tcp = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24348
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24349
	tcpt = (tcp_timer_t *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24350
	ASSERT(connp == tcpt->connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24351
	ASSERT((squeue_t *)arg2 == connp->conn_sqp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24352
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24353
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24354
	 * If the TCP has reached the closed state, don't proceed any
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24355
	 * further. This TCP logically does not exist on the system.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24356
	 * tcpt_proc could for example access queues, that have already
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24357
	 * been qprocoff'ed off. Also see comments at the start of tcp_input
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24358
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24359
	if (tcp->tcp_state != TCPS_CLOSED) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24360
		(*tcpt->tcpt_proc)(connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24361
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24362
		tcp->tcp_timer_tid = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24363
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24364
	tcp_timer_free(connp->conn_tcp, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24365
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24366
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24367
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24368
 * There is potential race with untimeout and the handler firing at the same
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24369
 * time. The mblock may be freed by the handler while we are trying to use
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24370
 * it. But since both should execute on the same squeue, this race should not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24371
 * occur.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24372
 */
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24373
clock_t
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24374
tcp_timeout_cancel(conn_t *connp, timeout_id_t id)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24375
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24376
	mblk_t	*mp = (mblk_t *)id;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24377
	tcp_timer_t *tcpt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24378
	clock_t delta;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24379
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24380
	TCP_DBGSTAT(tcp_timeout_cancel_reqs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24381
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24382
	if (mp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24383
		return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24384
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24385
	tcpt = (tcp_timer_t *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24386
	ASSERT(tcpt->connp == connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24387
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24388
	delta = untimeout(tcpt->tcpt_tid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24389
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24390
	if (delta >= 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24391
		TCP_DBGSTAT(tcp_timeout_canceled);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24392
		tcp_timer_free(connp->conn_tcp, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24393
		CONN_DEC_REF(connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24394
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24395
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24396
	return (delta);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24397
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24398
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24399
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24400
 * Allocate space for the timer event. The allocation looks like mblk, but it is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24401
 * not a proper mblk. To avoid confusion we set b_wptr to NULL.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24402
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24403
 * Dealing with failures: If we can't allocate from the timer cache we try
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24404
 * allocating from dblock caches using allocb_tryhard(). In this case b_wptr
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24405
 * points to b_rptr.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24406
 * If we can't allocate anything using allocb_tryhard(), we perform a last
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24407
 * 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
 24408
 * save the actual allocation size in b_datap.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24409
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24410
mblk_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24411
tcp_timermp_alloc(int kmflags)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24412
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24413
	mblk_t *mp = (mblk_t *)kmem_cache_alloc(tcp_timercache,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24414
	    kmflags & ~KM_PANIC);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24415
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24416
	if (mp != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24417
		mp->b_next = mp->b_prev = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24418
		mp->b_rptr = (uchar_t *)(&mp[1]);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24419
		mp->b_wptr = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24420
		mp->b_datap = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24421
		mp->b_queue = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24422
	} else if (kmflags & KM_PANIC) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24423
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24424
		 * Failed to allocate memory for the timer. Try allocating from
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24425
		 * dblock caches.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24426
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24427
		TCP_STAT(tcp_timermp_allocfail);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24428
		mp = allocb_tryhard(sizeof (tcp_timer_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24429
		if (mp == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24430
			size_t size = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24431
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24432
			 * Memory is really low. Try tryhard allocation.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24433
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24434
			TCP_STAT(tcp_timermp_allocdblfail);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24435
			mp = kmem_alloc_tryhard(sizeof (mblk_t) +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24436
			    sizeof (tcp_timer_t), &size, kmflags);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24437
			mp->b_rptr = (uchar_t *)(&mp[1]);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24438
			mp->b_next = mp->b_prev = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24439
			mp->b_wptr = (uchar_t *)-1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24440
			mp->b_datap = (dblk_t *)size;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24441
			mp->b_queue = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24442
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24443
		ASSERT(mp->b_wptr != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24444
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24445
	TCP_DBGSTAT(tcp_timermp_alloced);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24446
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24447
	return (mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24448
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24449
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24450
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24451
 * Free per-tcp timer cache.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24452
 * It can only contain entries from tcp_timercache.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24453
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24454
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24455
tcp_timermp_free(tcp_t *tcp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24456
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24457
	mblk_t *mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24458
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24459
	while ((mp = tcp->tcp_timercache) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24460
		ASSERT(mp->b_wptr == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24461
		tcp->tcp_timercache = tcp->tcp_timercache->b_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24462
		kmem_cache_free(tcp_timercache, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24463
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24464
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24465
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24466
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24467
 * 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
 24468
 * events there already (currently at most two events are cached).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24469
 * If the event is not allocated from the timer cache, free it right away.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24470
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24471
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24472
tcp_timer_free(tcp_t *tcp, mblk_t *mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24473
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24474
	mblk_t *mp1 = tcp->tcp_timercache;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24475
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24476
	if (mp->b_wptr != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24477
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24478
		 * This allocation is not from a timer cache, free it right
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24479
		 * away.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24480
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24481
		if (mp->b_wptr != (uchar_t *)-1)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24482
			freeb(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24483
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24484
			kmem_free(mp, (size_t)mp->b_datap);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24485
	} else if (mp1 == NULL || mp1->b_next == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24486
		/* Cache this timer block for future allocations */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24487
		mp->b_rptr = (uchar_t *)(&mp[1]);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24488
		mp->b_next = mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24489
		tcp->tcp_timercache = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24490
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24491
		kmem_cache_free(tcp_timercache, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24492
		TCP_DBGSTAT(tcp_timermp_freed);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24493
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24494
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24495
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24496
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24497
 * End of TCP Timers implementation.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24498
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24499
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24500
/*
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24501
 * 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
 24502
 * 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
 24503
 * 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
 24504
 * 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
 24505
 */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24506
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24507
void
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24508
tcp_setqfull(tcp_t *tcp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24509
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24510
	queue_t *q = tcp->tcp_wq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24511
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24512
	if (!(q->q_flag & QFULL)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24513
		mutex_enter(QLOCK(q));
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24514
		if (!(q->q_flag & QFULL)) {
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24515
			/* still need to set QFULL */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24516
			q->q_flag |= QFULL;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24517
			tcp->tcp_flow_stopped = B_TRUE;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24518
			mutex_exit(QLOCK(q));
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24519
			TCP_STAT(tcp_flwctl_on);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24520
		} else {
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24521
			mutex_exit(QLOCK(q));
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24522
		}
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24523
	}
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24524
}
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24525
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24526
void
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24527
tcp_clrqfull(tcp_t *tcp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24528
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24529
	queue_t *q = tcp->tcp_wq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24530
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24531
	if (q->q_flag & QFULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24532
		mutex_enter(QLOCK(q));
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24533
		if (q->q_flag & QFULL) {
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24534
			q->q_flag &= ~QFULL;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24535
			tcp->tcp_flow_stopped = B_FALSE;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24536
			mutex_exit(QLOCK(q));
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24537
			if (q->q_flag & QWANTW)
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24538
				qbackenable(q, 0);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24539
		} else {
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24540
			mutex_exit(QLOCK(q));
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24541
		}
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24542
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24543
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24544
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24545
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24546
 * TCP Kstats implementation
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24547
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24548
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24549
tcp_kstat_init(void)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24550
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24551
	tcp_named_kstat_t template = {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24552
		{ "rtoAlgorithm",	KSTAT_DATA_INT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24553
		{ "rtoMin",		KSTAT_DATA_INT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24554
		{ "rtoMax",		KSTAT_DATA_INT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24555
		{ "maxConn",		KSTAT_DATA_INT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24556
		{ "activeOpens",	KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24557
		{ "passiveOpens",	KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24558
		{ "attemptFails",	KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24559
		{ "estabResets",	KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24560
		{ "currEstab",		KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24561
		{ "inSegs",		KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24562
		{ "outSegs",		KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24563
		{ "retransSegs",	KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24564
		{ "connTableSize",	KSTAT_DATA_INT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24565
		{ "outRsts",		KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24566
		{ "outDataSegs",	KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24567
		{ "outDataBytes",	KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24568
		{ "retransBytes",	KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24569
		{ "outAck",		KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24570
		{ "outAckDelayed",	KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24571
		{ "outUrg",		KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24572
		{ "outWinUpdate",	KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24573
		{ "outWinProbe",	KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24574
		{ "outControl",		KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24575
		{ "outFastRetrans",	KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24576
		{ "inAckSegs",		KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24577
		{ "inAckBytes",		KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24578
		{ "inDupAck",		KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24579
		{ "inAckUnsent",	KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24580
		{ "inDataInorderSegs",	KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24581
		{ "inDataInorderBytes",	KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24582
		{ "inDataUnorderSegs",	KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24583
		{ "inDataUnorderBytes",	KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24584
		{ "inDataDupSegs",	KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24585
		{ "inDataDupBytes",	KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24586
		{ "inDataPartDupSegs",	KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24587
		{ "inDataPartDupBytes",	KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24588
		{ "inDataPastWinSegs",	KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24589
		{ "inDataPastWinBytes",	KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24590
		{ "inWinProbe",		KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24591
		{ "inWinUpdate",	KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24592
		{ "inClosed",		KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24593
		{ "rttUpdate",		KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24594
		{ "rttNoUpdate",	KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24595
		{ "timRetrans",		KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24596
		{ "timRetransDrop",	KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24597
		{ "timKeepalive",	KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24598
		{ "timKeepaliveProbe",	KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24599
		{ "timKeepaliveDrop",	KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24600
		{ "listenDrop",		KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24601
		{ "listenDropQ0",	KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24602
		{ "halfOpenDrop",	KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24603
		{ "outSackRetransSegs",	KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24604
		{ "connTableSize6",	KSTAT_DATA_INT32, 0 }
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24605
	};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24606
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24607
	tcp_mibkp = kstat_create(TCP_MOD_NAME, 0, TCP_MOD_NAME,
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24608
	    "mib2", KSTAT_TYPE_NAMED, NUM_OF_FIELDS(tcp_named_kstat_t), 0);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24609
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24610
	if (tcp_mibkp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24611
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24612
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24613
	template.rtoAlgorithm.value.ui32 = 4;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24614
	template.rtoMin.value.ui32 = tcp_rexmit_interval_min;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24615
	template.rtoMax.value.ui32 = tcp_rexmit_interval_max;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24616
	template.maxConn.value.i32 = -1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24617
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24618
	bcopy(&template, tcp_mibkp->ks_data, sizeof (template));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24619
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24620
	tcp_mibkp->ks_update = tcp_kstat_update;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24621
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24622
	kstat_install(tcp_mibkp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24623
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24624
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24625
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24626
tcp_kstat_fini(void)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24627
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24628
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24629
	if (tcp_mibkp != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24630
		kstat_delete(tcp_mibkp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24631
		tcp_mibkp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24632
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24633
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24634
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24635
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24636
tcp_kstat_update(kstat_t *kp, int rw)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24637
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24638
	tcp_named_kstat_t	*tcpkp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24639
	tcp_t			*tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24640
	connf_t			*connfp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24641
	conn_t			*connp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24642
	int 			i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24643
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24644
	if (!kp || !kp->ks_data)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24645
		return (EIO);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24646
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24647
	if (rw == KSTAT_WRITE)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24648
		return (EACCES);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24649
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24650
	tcpkp = (tcp_named_kstat_t *)kp->ks_data;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24651
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24652
	tcpkp->currEstab.value.ui32 = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24653
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24654
	for (i = 0; i < CONN_G_HASH_SIZE; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24655
		connfp = &ipcl_globalhash_fanout[i];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24656
		connp = NULL;
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24657
		while ((connp =
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24658
		    ipcl_get_next_conn(connfp, connp, IPCL_TCP)) != NULL) {
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24659
			tcp = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24660
			switch (tcp_snmp_state(tcp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24661
			case MIB2_TCP_established:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24662
			case MIB2_TCP_closeWait:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24663
				tcpkp->currEstab.value.ui32++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24664
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24665
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24666
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24667
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24668
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24669
	tcpkp->activeOpens.value.ui32 = tcp_mib.tcpActiveOpens;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24670
	tcpkp->passiveOpens.value.ui32 = tcp_mib.tcpPassiveOpens;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24671
	tcpkp->attemptFails.value.ui32 = tcp_mib.tcpAttemptFails;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24672
	tcpkp->estabResets.value.ui32 = tcp_mib.tcpEstabResets;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24673
	tcpkp->inSegs.value.ui32 = tcp_mib.tcpInSegs;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24674
	tcpkp->outSegs.value.ui32 = tcp_mib.tcpOutSegs;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24675
	tcpkp->retransSegs.value.ui32 =	tcp_mib.tcpRetransSegs;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24676
	tcpkp->connTableSize.value.i32 = tcp_mib.tcpConnTableSize;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24677
	tcpkp->outRsts.value.ui32 = tcp_mib.tcpOutRsts;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24678
	tcpkp->outDataSegs.value.ui32 = tcp_mib.tcpOutDataSegs;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24679
	tcpkp->outDataBytes.value.ui32 = tcp_mib.tcpOutDataBytes;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24680
	tcpkp->retransBytes.value.ui32 = tcp_mib.tcpRetransBytes;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24681
	tcpkp->outAck.value.ui32 = tcp_mib.tcpOutAck;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24682
	tcpkp->outAckDelayed.value.ui32 = tcp_mib.tcpOutAckDelayed;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24683
	tcpkp->outUrg.value.ui32 = tcp_mib.tcpOutUrg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24684
	tcpkp->outWinUpdate.value.ui32 = tcp_mib.tcpOutWinUpdate;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24685
	tcpkp->outWinProbe.value.ui32 = tcp_mib.tcpOutWinProbe;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24686
	tcpkp->outControl.value.ui32 = tcp_mib.tcpOutControl;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24687
	tcpkp->outFastRetrans.value.ui32 = tcp_mib.tcpOutFastRetrans;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24688
	tcpkp->inAckSegs.value.ui32 = tcp_mib.tcpInAckSegs;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24689
	tcpkp->inAckBytes.value.ui32 = tcp_mib.tcpInAckBytes;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24690
	tcpkp->inDupAck.value.ui32 = tcp_mib.tcpInDupAck;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24691
	tcpkp->inAckUnsent.value.ui32 = tcp_mib.tcpInAckUnsent;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24692
	tcpkp->inDataInorderSegs.value.ui32 = tcp_mib.tcpInDataInorderSegs;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24693
	tcpkp->inDataInorderBytes.value.ui32 = tcp_mib.tcpInDataInorderBytes;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24694
	tcpkp->inDataUnorderSegs.value.ui32 = tcp_mib.tcpInDataUnorderSegs;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24695
	tcpkp->inDataUnorderBytes.value.ui32 = tcp_mib.tcpInDataUnorderBytes;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24696
	tcpkp->inDataDupSegs.value.ui32 = tcp_mib.tcpInDataDupSegs;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24697
	tcpkp->inDataDupBytes.value.ui32 = tcp_mib.tcpInDataDupBytes;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24698
	tcpkp->inDataPartDupSegs.value.ui32 = tcp_mib.tcpInDataPartDupSegs;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24699
	tcpkp->inDataPartDupBytes.value.ui32 = tcp_mib.tcpInDataPartDupBytes;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24700
	tcpkp->inDataPastWinSegs.value.ui32 = tcp_mib.tcpInDataPastWinSegs;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24701
	tcpkp->inDataPastWinBytes.value.ui32 = tcp_mib.tcpInDataPastWinBytes;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24702
	tcpkp->inWinProbe.value.ui32 = tcp_mib.tcpInWinProbe;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24703
	tcpkp->inWinUpdate.value.ui32 = tcp_mib.tcpInWinUpdate;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24704
	tcpkp->inClosed.value.ui32 = tcp_mib.tcpInClosed;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24705
	tcpkp->rttNoUpdate.value.ui32 = tcp_mib.tcpRttNoUpdate;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24706
	tcpkp->rttUpdate.value.ui32 = tcp_mib.tcpRttUpdate;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24707
	tcpkp->timRetrans.value.ui32 = tcp_mib.tcpTimRetrans;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24708
	tcpkp->timRetransDrop.value.ui32 = tcp_mib.tcpTimRetransDrop;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24709
	tcpkp->timKeepalive.value.ui32 = tcp_mib.tcpTimKeepalive;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24710
	tcpkp->timKeepaliveProbe.value.ui32 = tcp_mib.tcpTimKeepaliveProbe;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24711
	tcpkp->timKeepaliveDrop.value.ui32 = tcp_mib.tcpTimKeepaliveDrop;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24712
	tcpkp->listenDrop.value.ui32 = tcp_mib.tcpListenDrop;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24713
	tcpkp->listenDropQ0.value.ui32 = tcp_mib.tcpListenDropQ0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24714
	tcpkp->halfOpenDrop.value.ui32 = tcp_mib.tcpHalfOpenDrop;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24715
	tcpkp->outSackRetransSegs.value.ui32 = tcp_mib.tcpOutSackRetransSegs;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24716
	tcpkp->connTableSize6.value.i32 = tcp_mib.tcp6ConnTableSize;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24717
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24718
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24719
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24720
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24721
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24722
tcp_reinput(conn_t *connp, mblk_t *mp, squeue_t *sqp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24723
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24724
	uint16_t	hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24725
	ipha_t		*ipha;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24726
	uint8_t		*nexthdrp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24727
	tcph_t		*tcph;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24728
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24729
	/* Already has an eager */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24730
	if ((mp->b_datap->db_struioflag & STRUIO_EAGER) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24731
		TCP_STAT(tcp_reinput_syn);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24732
		squeue_enter(connp->conn_sqp, mp, connp->conn_recv,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24733
		    connp, SQTAG_TCP_REINPUT_EAGER);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24734
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24735
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24736
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24737
	switch (IPH_HDR_VERSION(mp->b_rptr)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24738
	case IPV4_VERSION:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24739
		ipha = (ipha_t *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24740
		hdr_len = IPH_HDR_LENGTH(ipha);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24741
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24742
	case IPV6_VERSION:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24743
		if (!ip_hdr_length_nexthdr_v6(mp, (ip6_t *)mp->b_rptr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24744
		    &hdr_len, &nexthdrp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24745
			CONN_DEC_REF(connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24746
			freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24747
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24748
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24749
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24750
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24751
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24752
	tcph = (tcph_t *)&mp->b_rptr[hdr_len];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24753
	if ((tcph->th_flags[0] & (TH_SYN|TH_ACK|TH_RST|TH_URG)) == TH_SYN) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24754
		mp->b_datap->db_struioflag |= STRUIO_EAGER;
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24755
		DB_CKSUMSTART(mp) = (intptr_t)sqp;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24756
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24757
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24758
	squeue_fill(connp->conn_sqp, mp, connp->conn_recv, connp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24759
	    SQTAG_TCP_REINPUT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24760
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24761
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24762
static squeue_func_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24763
tcp_squeue_switch(int val)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24764
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24765
	squeue_func_t rval = squeue_fill;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24766
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24767
	switch (val) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24768
	case 1:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24769
		rval = squeue_enter_nodrain;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24770
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24771
	case 2:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24772
		rval = squeue_enter;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24773
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24774
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24775
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24776
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24777
	return (rval);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24778
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24779
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24780
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24781
tcp_squeue_add(squeue_t *sqp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24782
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24783
	tcp_squeue_priv_t *tcp_time_wait = kmem_zalloc(
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24784
		sizeof (tcp_squeue_priv_t), KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24785
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24786
	*squeue_getprivate(sqp, SQPRIVATE_TCP) = (intptr_t)tcp_time_wait;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24787
	tcp_time_wait->tcp_time_wait_tid = timeout(tcp_time_wait_collector,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24788
	    sqp, TCP_TIME_WAIT_DELAY);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24789
}