sctp_hash.c revision a5407c02d5ed61b29481b9b71f1307d7ebec9e5c
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (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
*/
/*
*/
#include <inet/ipclassifier.h>
#include <inet/ipsec_impl.h>
#include <inet/ipp_common.h>
#include "sctp_impl.h"
#include "sctp_addr.h"
/* Default association hash size. The size must be a power of 2. */
#define SCTP_CONN_HASH_SIZE 8192
/*
* Cluster networking hook for traversing current assoc list.
* This routine is used to extract the current list of live associations
* which must continue to to be dispatched to this node.
*/
void
{
int i;
/* Not a power of two. Round up to nearest power of two */
for (i = 0; i < 31; i++) {
break;
}
}
}
for (i = 0; i < sctps->sctps_conn_hash_size; i++) {
}
for (i = 0; i < SCTP_LISTEN_FANOUT_SIZE; i++) {
}
for (i = 0; i < SCTP_BIND_FANOUT_SIZE; i++) {
}
}
void
{
int i;
for (i = 0; i < sctps->sctps_conn_hash_size; i++) {
}
sizeof (sctp_tf_t));
for (i = 0; i < SCTP_LISTEN_FANOUT_SIZE; i++) {
}
sizeof (sctp_tf_t));
for (i = 0; i < SCTP_BIND_FANOUT_SIZE; i++) {
}
sizeof (sctp_tf_t));
}
/*
* Exported routine for extracting active SCTP associations.
* Like TCP, we terminate the walk if the callback returns non-zero.
*
* Need to walk all sctp_stack_t instances since this clustering
* interface is assumed global for all instances
*/
int
{
netstack_t *ns;
int ret = 0;
ns->netstack_sctp);
}
return (ret);
}
static int
{
continue;
}
sctp->sctp_refcnt++;
return (1);
}
else
return (1);
}
/* list will be freed by cl_callback */
}
return (0);
}
sctp_t *
{
continue;
connp->conn_allzones ||
(iraflags & IRAF_TX_MAC_EXEMPTABLE) &&
(iraflags & IRAF_TX_SHARED_ADDR))))
continue;
/* check for faddr match */
/* check for laddr match */
!= NULL) {
return (sctp);
}
}
}
}
/* no match; continue to the next in the chain */
}
return (sctp);
}
static sctp_t *
{
continue;
connp->conn_allzones ||
(iraflags & IRAF_TX_MAC_EXEMPTABLE) &&
(iraflags & IRAF_TX_SHARED_ADDR))))
continue;
goto done;
}
/* no match; continue to the next in the chain */
}
done:
return (sctp);
}
/* called by ipsec_sctp_pol */
conn_t *
{
/* Not in conn fanout; check listen fanout */
return (NULL);
}
return (sctp->sctp_connp);
}
/*
* This is called from sctp_fanout() with IP header src & dst addresses.
* First call sctp_conn_match() to get a match by passing in src & dst
* addresses from IP header.
* However sctp_conn_match() can return no match under condition such as :
* A host can send an INIT ACK from a different address than the INIT was sent
* to (in a multi-homed env).
* According to RFC4960, a host can send additional addresses in an INIT
* ACK chunk.
* Therefore extract all addresses from the INIT ACK chunk, pass to
* sctp_conn_match() to get a match.
*/
static sctp_t *
{
/*
* If we get a match with the passed-in IP header src & dst addresses,
* quickly return the matched sctp.
*/
return (sctp);
}
/*
* Currently sctph is set to NULL in icmp error fanout case
* (ip_fanout_sctp()).
* The above sctp_conn_match() should handle that, otherwise
* return no match found.
*/
return (NULL);
/*
* Do a pullup again in case the previous one was partially successful,
* so try to complete the pullup here and have a single contiguous
* chunk for processing of entire INIT ACK chunk below.
*/
return (NULL);
}
}
return (NULL);
}
sizeof (*iack);
return (NULL);
}
if (!isv4)
addrbuf = (in6_addr_t **)
return (NULL);
/*
* According to RFC4960 :
* All integer fields in an SCTP packet MUST be
* transmitted in network byte order,
* unless otherwise stated.
* Therefore convert the param type to host byte order.
* Also do not add src address present in IP header
* as it has already been thru sctp_conn_match() above.
*/
switch (param_type) {
case PARM_ADDR4:
IN6_INADDR_TO_V4MAPPED((struct in_addr *)
break;
*faddrpp = (in6_addr_t *)
kmem_zalloc(sizeof (in6_addr_t),
break;
IN6_INADDR_TO_V4MAPPED((struct in_addr *)
nfaddr++;
faddrpp++;
break;
case PARM_ADDR6:
break;
nfaddr++;
faddrpp++;
break;
default:
break;
}
}
if (nfaddr > 0) {
if (isv4) {
if (IN6_IS_ADDR_V4MAPPED(*faddrpp)) {
sizeof (in6_addr_t));
}
}
}
}
}
return (sctp);
}
/*
* Fanout to a sctp instance.
*/
conn_t *
{
/* Not in conn fanout; check listen fanout */
return (NULL);
/*
* On systems running trusted extensions, check if dst
* should accept the packet. "IPV6_VERSION" indicates
* that dst is in 16 byte AF_INET6 format. IPv4-mapped
* IPv6 addresses are supported.
*/
if ((iraflags & IRAF_SYSTEM_LABELED) &&
sctp->sctp_connp)) {
char *,
"connp(1) could not receive mp(2)",
return (NULL);
}
}
/*
* For labeled systems, there's no need to check the
* label here. It's known to be good as we checked
* before allowing the connection to become bound.
*/
return (sctp->sctp_connp);
}
/*
* Fanout for ICMP errors for SCTP
* The caller puts <fport, lport> in the ports parameter.
*/
void
{
/* Assume IP provides aligned packets - otherwise toss */
return;
}
if (!(iraflags & IRAF_IS_IPV4)) {
} else {
}
return;
}
/*
* We check some fields in conn_t without holding a lock.
* This should be fine.
*/
if (((iraflags & IRAF_IS_IPV4) ?
secure) {
return;
}
}
if (sctp->sctp_running) {
} else {
} else {
} else {
}
}
}
}
void
{
if (!tf) {
return;
}
/*
* On a clustered note send this notification to the clustering
* subsystem.
*/
if (cl_sctp_disconnect != NULL) {
}
if (sctp->sctp_conn_hash_next) {
}
} else {
if (sctp->sctp_conn_hash_next) {
== sctp);
}
}
}
void
{
if (sctp->sctp_conn_tfp) {
}
if (!caller_holds_lock) {
} else {
}
}
if (!caller_holds_lock) {
}
}
void
{
if (!tf) {
return;
}
/*
* On a clustered note send this notification to the clustering
* subsystem.
*/
if (cl_sctp_unlisten != NULL) {
/* list will be freed by the clustering module */
}
}
} else {
sctp);
}
}
}
void
{
if (sctp->sctp_listen_tfp) {
}
}
/*
* On a clustered note send this notification to the clustering
* subsystem.
*/
if (cl_sctp_listen != NULL) {
/* list will be freed by the clustering module */
}
}
/*
* Hash list insertion routine for sctp_t structures.
* Inserts entries with the ones bound to a specific IP address first
* followed by those bound to INADDR_ANY.
*/
void
{
}
if (!caller_holds_lock) {
} else {
}
if (sctpnext) {
}
/* For sctp_*_hash_remove */
if (!caller_holds_lock)
}
/*
* Hash list removal routine for sctp_t structures.
*/
void
{
return;
if (sctp->sctp_ptpbhn) {
if (sctpnext) {
}
}
}
/*
* Similar to but different from sctp_conn_match().
*
* Matches sets of addresses as follows: if the argument addr set is
* a complete subset of the corresponding addr set in the sctp_t, it
* is a match.
*
* Caller must hold tf->tf_lock.
*
* Returns with a SCTP_REFHOLD sctp structure. Caller must do a SCTP_REFRELE.
*/
sctp_t *
int min_state)
{
continue;
}
/* check for faddr match */
break;
}
}
/* no faddr match; keep looking */
continue;
}
/*
* There is an existing association with the same peer
* address. So now we need to check if our local address
* set overlaps with the one of the existing association.
* If they overlap, we should return it.
*/
goto done;
}
/* no match; continue searching */
}
done:
}
return (sctp);
}