sctp_conn.c revision 1d8c40254918b6a58c4b2132dafb3e012ccd66f0
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#define _SUN_TPI_VERSION 2
#include <inet/ipclassifier.h>
#include <inet/ipsec_impl.h>
#include "sctp_impl.h"
#include "sctp_addr.h"
/*
* Common accept code. Called by sctp_conn_request.
* cr_pkt is the INIT / INIT ACK packet.
*/
static int
{
int err;
/* acceptor isn't in any fanouts yet, so don't need to hold locks */
&sctp_options);
if (err != 0)
return (err);
if ((sctp_options & SCTP_PRSCTP_OPTION) &&
} else {
}
/* The new sctp_t is fully bound now. */
/* Get initial TSNs */
/* Serial numbers are initialized to the same value as the TSNs */
return (ENOMEM);
/*
* Copy sctp_secret from the listener in case we need to validate
* a possibly delayed cookie.
*/
/*
* After acceptor is inserted in the hash list, it can be found.
* So we need to lock it here.
*/
/*
* No need to check for multicast destination since ip will only pass
* up multicasts to those that have expressed interest
* TODO: what about rejecting broadcasts?
* Also check that source is not a multicast or broadcast address.
*/
/* XXXSCTP */
/*
* listener->sctp_rwnd should be the default window size or a
* window size changed via SO_RCVBUF option.
*/
sizeof (sctp_upcalls_t));
return (0);
}
/* Process the COOKIE packet, mp, directed at the listener 'sctp' */
sctp_t *
{
int err;
/*
* No need to check for duplicate as this is the listener
* and we are holding the lock. This means that no new
* connection can be created out of it. And since the
* fanout already done cannot find a match, it means that
* there is no duplicate.
*/
return (NULL);
}
if (ipvers != IPV4_VERSION) {
/*
* Record ifindex (might be zero) to tie this connection to
* that interface if either the listener was bound or
* if the connection is using link-local addresses.
*/
/*
* XXX broken. bound_if is always overwritten by statement
* below. What is the right thing to do here?
*/
}
ipsec_in_t *ii;
return (NULL);
}
}
/*
* XXX need to fix the cached policy issue here.
* that IPsec can use it for the latched policy
* selector. This is obvioursly wrong as SCTP can
* use different addresses...
*/
if (ipvers == IPV4_VERSION) {
} else {
}
}
return (NULL);
}
if (err) {
return (NULL);
}
/*
* On a clustered note send this notification to the clustering
* subsystem.
*/
if (cl_sctp_connect != NULL) {
return (NULL);
}
/* The clustering module frees these list */
}
/* Connection established, so send up the conn_ind */
return (NULL);
}
sctp_wroff_xtra + sizeof (sctp_data_hdr_t) +
} else {
sctp_wroff_xtra + sizeof (sctp_data_hdr_t) +
}
return (eager);
}
/*
* Connect to a peer - this function inserts the sctp in the
* bind and conn fanouts, sends the INIT, and replies to the client
* with an OK ack.
*/
/* ARGSUSED */
int
{
char buf[INET6_ADDRSTRLEN];
int hdrlen;
/*
* Determine packet type based on type of address passed in
* the request should contain an IPv4 or IPv6 address.
* Make sure that address family matches the type of
* family of the the address passed down
*/
return (EINVAL);
}
case AF_INET:
/* Check for attempt to connect to non-unicast */
ip0dbg(("sctp_connect: non-unicast\n"));
return (EINVAL);
}
return (EAFNOSUPPORT);
/* convert to v6 mapped */
/* Check for attempt to connect to INADDR_ANY */
/*
* SunOS 4.x and 4.3 BSD allow an application
* to connect a TCP socket to INADDR_ANY.
* When they do this, the kernel picks the
* address of one interface and uses it
* instead. The kernel usually ends up
* picking the address of the loopback
* interface. This is an undocumented feature.
* However, we provide the same thing here
* in case any TCP apps that use this feature
* are being ported to SCTP...
*/
} else {
}
} else {
}
break;
case AF_INET6:
/* Check for attempt to connect to non-unicast. */
ip0dbg(("sctp_connect: non-unicast\n"));
return (EINVAL);
}
return (EAFNOSUPPORT);
}
/* check for attempt to connect to unspec */
} else {
if (IN6_IS_ADDR_LINKLOCAL(&dstaddr))
}
break;
default:
return (EAFNOSUPPORT);
}
return (EINVAL);
}
switch (sctp->sctp_state) {
case SCTPS_IDLE: {
int err;
struct sockaddr_storage ss;
/*
* We support a quick connect capability here, allowing
* clients to transition directly from IDLE to COOKIE_WAIT.
* sctp_bindi will pick an unused port, insert the connection
* in the bind hash and transition to BOUND state. SCTP
* picks and uses what it considers the optimal local address
* set (just like specifiying INADDR_ANY to bind()).
*/
sizeof (ss))) != 0) {
return (err);
}
/* FALLTHRU */
}
case SCTPS_BOUND:
/* do the connect */
/* XXX check for attempt to connect to self */
/*
* Don't allow this connection to completely duplicate
* an existing connection.
*
* Ensure that the duplicate check and insertion is atomic.
*/
/* found a duplicate connection */
return (EADDRINUSE);
}
/*
* OK; set up the peer addr (this may grow after we get
* the INIT ACK from the peer with additional addresses).
*/
return (ENOMEM);
}
/* No valid src addr, return. */
return (EADDRNOTAVAIL);
}
/* initialize composite headers */
/*
* Massage a routing header (if present) putting the first hop
* in ip6_dst.
*/
/*
* Turn off the don't fragment bit on the (only) faddr,
* so that if one of the messages exchanged during the
* initialization sequence exceeds the path mtu, it
* at least has a chance to get there. SCTP does no
* fragmentation of initialization messages. The DF bit
* will be turned on again in sctp_send_cookie_echo()
* (but the cookie echo will still be sent with the df bit
* off).
*/
/* Mark this address as alive */
/* This sctp_t is fully bound now. */
/* Send the INIT to the peer */
/*
* sctp_init_mp() could result in modifying the source
* address list, so take the hash lock.
*/
/* let timer retry */
return (0);
}
/*
* On a clustered note send this notification to the clustering
* subsystem.
*/
if (cl_sctp_connect != NULL) {
/* The clustering module frees the lists */
}
/* OK to call IP_PUT() here instead of sctp_add_sendq(). */
return (0);
default:
return (EINVAL);
}
}