Bug 1139020: Update SCTP library from upstream to rev 9168 rs=jesup

This commit is contained in:
Randell Jesup 2015-03-05 00:17:42 -05:00
parent 583788c3a7
commit 02c76d0edf
38 changed files with 4052 additions and 3233 deletions

View File

@ -14,3 +14,4 @@ sctp updated to version 8279 from SVN on Thu Sep 20 18:19:24 EDT 2012
sctp updated to version 8397 from SVN on Wed Jan 9 00:41:16 EST 2013
sctp updated to version 8443 from SVN on Sun Mar 31 09:05:07 EDT 2013
sctp updated to version 8815 from SVN on Tue Mar 4 08:50:51 EST 2014
sctp updated to version 9168 from SVN on Tue Mar 3 12:11:40 EST 2015

View File

@ -32,7 +32,7 @@
#ifdef __FreeBSD__
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: head/sys/netinet/sctp.h 254248 2013-08-12 13:52:15Z tuexen $");
__FBSDID("$FreeBSD: head/sys/netinet/sctp.h 269945 2014-08-13 15:50:16Z tuexen $");
#endif
#ifndef _NETINET_SCTP_H_
@ -53,13 +53,13 @@ __FBSDID("$FreeBSD: head/sys/netinet/sctp.h 254248 2013-08-12 13:52:15Z tuexen $
#endif
/*
* SCTP protocol - RFC2960.
* SCTP protocol - RFC4960.
*/
struct sctphdr {
uint16_t src_port; /* source port */
uint16_t dest_port; /* destination port */
uint32_t v_tag; /* verification tag of packet */
uint32_t checksum; /* Adler32 C-Sum */
uint32_t checksum; /* CRC32C checksum */
/* chunks follow... */
} SCTP_PACKED;
@ -131,6 +131,13 @@ struct sctp_paramhdr {
#define SCTP_DEFAULT_PRINFO 0x00000022
#define SCTP_PEER_ADDR_THLDS 0x00000023
#define SCTP_REMOTE_UDP_ENCAPS_PORT 0x00000024
#define SCTP_ECN_SUPPORTED 0x00000025
#define SCTP_PR_SUPPORTED 0x00000026
#define SCTP_AUTH_SUPPORTED 0x00000027
#define SCTP_ASCONF_SUPPORTED 0x00000028
#define SCTP_RECONFIG_SUPPORTED 0x00000029
#define SCTP_NRSACK_SUPPORTED 0x00000030
#define SCTP_PKTDROP_SUPPORTED 0x00000031
/*
* read-only options
@ -143,6 +150,8 @@ struct sctp_paramhdr {
#define SCTP_GET_ASSOC_NUMBER 0x00000104 /* ro */
#define SCTP_GET_ASSOC_ID_LIST 0x00000105 /* ro */
#define SCTP_TIMEOUTS 0x00000106
#define SCTP_PR_STREAM_STATUS 0x00000107
#define SCTP_PR_ASSOC_STATUS 0x00000108
/*
* user socket options: BSD implementation specific
@ -379,6 +388,12 @@ struct sctp_paramhdr {
/*
* error cause parameters (user visible)
*/
struct sctp_gen_error_cause {
uint16_t code;
uint16_t length;
uint8_t info[];
} SCTP_PACKED;
struct sctp_error_cause {
uint16_t code;
uint16_t length;
@ -416,6 +431,11 @@ struct sctp_error_unrecognized_chunk {
struct sctp_chunkhdr ch;/* header from chunk in error */
} SCTP_PACKED;
struct sctp_error_no_user_data {
struct sctp_error_cause cause; /* code=SCTP_CAUSE_NO_USER_DATA */
uint32_t tsn; /* TSN of the empty data chunk */
} SCTP_PACKED;
/*
* Main SCTP chunk types we place these here so natd and f/w's in user land
* can find them.

View File

@ -32,7 +32,7 @@
#ifdef __FreeBSD__
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: head/sys/netinet/sctp_asconf.c 257803 2013-11-07 17:08:09Z tuexen $");
__FBSDID("$FreeBSD: head/sys/netinet/sctp_asconf.c 277347 2015-01-18 20:53:20Z tuexen $");
#endif
#include <netinet/sctp_os.h>
@ -153,7 +153,7 @@ sctp_process_asconf_add_ip(struct sockaddr *src, struct sctp_asconf_paramhdr *ap
{
struct sctp_nets *net;
struct mbuf *m_reply = NULL;
struct sockaddr_storage sa_store;
union sctp_sockstore store;
struct sctp_paramhdr *ph;
uint16_t param_type, aparam_length;
#if defined(INET) || defined(INET6)
@ -177,7 +177,7 @@ sctp_process_asconf_add_ip(struct sockaddr *src, struct sctp_asconf_paramhdr *ap
#if defined(INET) || defined(INET6)
param_length = ntohs(ph->param_length);
#endif
sa = (struct sockaddr *)&sa_store;
sa = &store.sa;
switch (param_type) {
#ifdef INET
case SCTP_IPV4_ADDRESS:
@ -186,7 +186,7 @@ sctp_process_asconf_add_ip(struct sockaddr *src, struct sctp_asconf_paramhdr *ap
return (NULL);
}
v4addr = (struct sctp_ipv4addr_param *)ph;
sin = (struct sockaddr_in *)&sa_store;
sin = &store.sin;
bzero(sin, sizeof(*sin));
sin->sin_family = AF_INET;
#ifdef HAVE_SIN_LEN
@ -211,7 +211,7 @@ sctp_process_asconf_add_ip(struct sockaddr *src, struct sctp_asconf_paramhdr *ap
return (NULL);
}
v6addr = (struct sctp_ipv6addr_param *)ph;
sin6 = (struct sockaddr_in6 *)&sa_store;
sin6 = &store.sin6;
bzero(sin6, sizeof(*sin6));
sin6->sin6_family = AF_INET6;
#ifdef HAVE_SIN6_LEN
@ -307,7 +307,7 @@ sctp_process_asconf_delete_ip(struct sockaddr *src,
struct sctp_tcb *stcb, int response_required)
{
struct mbuf *m_reply = NULL;
struct sockaddr_storage sa_store;
union sctp_sockstore store;
struct sctp_paramhdr *ph;
uint16_t param_type, aparam_length;
#if defined(INET) || defined(INET6)
@ -331,7 +331,7 @@ sctp_process_asconf_delete_ip(struct sockaddr *src,
#if defined(INET) || defined(INET6)
param_length = ntohs(ph->param_length);
#endif
sa = (struct sockaddr *)&sa_store;
sa = &store.sa;
switch (param_type) {
#ifdef INET
case SCTP_IPV4_ADDRESS:
@ -340,7 +340,7 @@ sctp_process_asconf_delete_ip(struct sockaddr *src,
return (NULL);
}
v4addr = (struct sctp_ipv4addr_param *)ph;
sin = (struct sockaddr_in *)&sa_store;
sin = &store.sin;
bzero(sin, sizeof(*sin));
sin->sin_family = AF_INET;
#ifdef HAVE_SIN_LEN
@ -362,7 +362,7 @@ sctp_process_asconf_delete_ip(struct sockaddr *src,
return (NULL);
}
v6addr = (struct sctp_ipv6addr_param *)ph;
sin6 = (struct sockaddr_in6 *)&sa_store;
sin6 = &store.sin6;
bzero(sin6, sizeof(*sin6));
sin6->sin6_family = AF_INET6;
#ifdef HAVE_SIN6_LEN
@ -429,7 +429,7 @@ sctp_process_asconf_delete_ip(struct sockaddr *src,
aparam_length);
} else {
if (response_required) {
m_reply = sctp_asconf_success_response(aph->correlation_id);
m_reply = sctp_asconf_success_response(aph->correlation_id);
}
/* notify upper layer */
sctp_ulp_notify(SCTP_NOTIFY_ASCONF_DELETE_IP, stcb, 0, sa, SCTP_SO_NOT_LOCKED);
@ -443,7 +443,7 @@ sctp_process_asconf_set_primary(struct sockaddr *src,
struct sctp_tcb *stcb, int response_required)
{
struct mbuf *m_reply = NULL;
struct sockaddr_storage sa_store;
union sctp_sockstore store;
struct sctp_paramhdr *ph;
uint16_t param_type, aparam_length;
#if defined(INET) || defined(INET6)
@ -466,7 +466,7 @@ sctp_process_asconf_set_primary(struct sockaddr *src,
#if defined(INET) || defined(INET6)
param_length = ntohs(ph->param_length);
#endif
sa = (struct sockaddr *)&sa_store;
sa = &store.sa;
switch (param_type) {
#ifdef INET
case SCTP_IPV4_ADDRESS:
@ -475,7 +475,7 @@ sctp_process_asconf_set_primary(struct sockaddr *src,
return (NULL);
}
v4addr = (struct sctp_ipv4addr_param *)ph;
sin = (struct sockaddr_in *)&sa_store;
sin = &store.sin;
bzero(sin, sizeof(*sin));
sin->sin_family = AF_INET;
#ifdef HAVE_SIN_LEN
@ -495,7 +495,7 @@ sctp_process_asconf_set_primary(struct sockaddr *src,
return (NULL);
}
v6addr = (struct sctp_ipv6addr_param *)ph;
sin6 = (struct sockaddr_in6 *)&sa_store;
sin6 = &store.sin6;
bzero(sin6, sizeof(*sin6));
sin6->sin6_family = AF_INET6;
#ifdef HAVE_SIN6_LEN
@ -552,11 +552,11 @@ sctp_process_asconf_set_primary(struct sockaddr *src,
are transmitted to the new primary destination. (by micchie)
*/
if ((sctp_is_mobility_feature_on(stcb->sctp_ep,
SCTP_MOBILITY_BASE) ||
SCTP_MOBILITY_BASE) ||
sctp_is_mobility_feature_on(stcb->sctp_ep,
SCTP_MOBILITY_FASTHANDOFF)) &&
SCTP_MOBILITY_FASTHANDOFF)) &&
sctp_is_mobility_feature_on(stcb->sctp_ep,
SCTP_MOBILITY_PRIM_DELETED) &&
SCTP_MOBILITY_PRIM_DELETED) &&
(stcb->asoc.primary_destination->dest_state &
SCTP_ADDR_UNCONFIRMED) == 0) {
@ -601,7 +601,7 @@ sctp_handle_asconf(struct mbuf *m, unsigned int offset,
uint32_t serial_num;
struct mbuf *n, *m_ack, *m_result, *m_tail;
struct sctp_asconf_ack_chunk *ack_cp;
struct sctp_asconf_paramhdr *aph, *ack_aph;
struct sctp_asconf_paramhdr *aph;
struct sctp_ipv6addr_param *p_addr;
unsigned int asconf_limit, cnt;
int error = 0; /* did an error occur? */
@ -686,13 +686,6 @@ sctp_handle_asconf(struct mbuf *m, unsigned int offset,
}
/* param_length is already validated in process_control... */
offset += ntohs(p_addr->ph.param_length); /* skip lookup addr */
/* get pointer to first asconf param in ASCONF-ACK */
ack_aph = (struct sctp_asconf_paramhdr *)(mtod(m_ack, caddr_t) + sizeof(struct sctp_asconf_ack_chunk));
if (ack_aph == NULL) {
SCTPDBG(SCTP_DEBUG_ASCONF1, "Gak in asconf2\n");
return;
}
/* get pointer to first asconf param in ASCONF */
aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(m, offset, sizeof(struct sctp_asconf_paramhdr), (uint8_t *)&aparam_buf);
if (aph == NULL) {
@ -731,13 +724,11 @@ sctp_handle_asconf(struct mbuf *m, unsigned int offset,
}
switch (param_type) {
case SCTP_ADD_IP_ADDRESS:
asoc->peer_supports_asconf = 1;
m_result = sctp_process_asconf_add_ip(src, aph, stcb,
(cnt < SCTP_BASE_SYSCTL(sctp_hb_maxburst)), error);
cnt++;
break;
case SCTP_DEL_IP_ADDRESS:
asoc->peer_supports_asconf = 1;
m_result = sctp_process_asconf_delete_ip(src, aph, stcb,
error);
break;
@ -745,7 +736,6 @@ sctp_handle_asconf(struct mbuf *m, unsigned int offset,
/* not valid in an ASCONF chunk */
break;
case SCTP_SET_PRIM_ADDR:
asoc->peer_supports_asconf = 1;
m_result = sctp_process_asconf_set_primary(src, aph,
stcb, error);
break;
@ -936,8 +926,6 @@ sctp_addr_match(struct sctp_paramhdr *ph, struct sockaddr *sa)
void
sctp_asconf_cleanup(struct sctp_tcb *stcb, struct sctp_nets *net)
{
/* mark peer as ASCONF incapable */
stcb->asoc.peer_supports_asconf = 0;
/*
* clear out any existing asconfs going out
*/
@ -1099,7 +1087,7 @@ sctp_path_check_and_react(struct sctp_tcb *stcb, struct sctp_ifa *newifa)
}
/* Retransmit unacknowledged DATA chunks immediately */
if (sctp_is_mobility_feature_on(stcb->sctp_ep,
SCTP_MOBILITY_FASTHANDOFF)) {
SCTP_MOBILITY_FASTHANDOFF)) {
sctp_net_immediate_retrans(stcb, net);
}
/* also, SET PRIMARY is maybe already sent */
@ -1157,7 +1145,7 @@ sctp_path_check_and_react(struct sctp_tcb *stcb, struct sctp_ifa *newifa)
continue;
/* Retransmit unacknowledged DATA chunks immediately */
if (sctp_is_mobility_feature_on(stcb->sctp_ep,
SCTP_MOBILITY_FASTHANDOFF)) {
SCTP_MOBILITY_FASTHANDOFF)) {
sctp_net_immediate_retrans(stcb, net);
}
/* Send SET PRIMARY for this new address */
@ -1193,9 +1181,9 @@ sctp_asconf_addr_mgmt_ack(struct sctp_tcb *stcb, struct sctp_ifa *addr, uint32_t
#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Userspace__)
if (sctp_is_mobility_feature_on(stcb->sctp_ep,
SCTP_MOBILITY_BASE) ||
SCTP_MOBILITY_BASE) ||
sctp_is_mobility_feature_on(stcb->sctp_ep,
SCTP_MOBILITY_FASTHANDOFF)) {
SCTP_MOBILITY_FASTHANDOFF)) {
sctp_path_check_and_react(stcb, addr);
return;
}
@ -1281,7 +1269,7 @@ sctp_asconf_queue_mgmt(struct sctp_tcb *stcb, struct sctp_ifa *ifa,
{
struct sockaddr_in6 *sin6;
sin6 = (struct sockaddr_in6 *)&ifa->address.sa;
sin6 = &ifa->address.sin6;
aa->ap.addrp.ph.param_type = SCTP_IPV6_ADDRESS;
aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv6addr_param));
aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) +
@ -1296,7 +1284,7 @@ sctp_asconf_queue_mgmt(struct sctp_tcb *stcb, struct sctp_ifa *ifa,
{
struct sockaddr_in *sin;
sin= (struct sockaddr_in *)&ifa->address.sa;
sin = &ifa->address.sin;
aa->ap.addrp.ph.param_type = SCTP_IPV4_ADDRESS;
aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv4addr_param));
aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) +
@ -1348,7 +1336,7 @@ sctp_asconf_queue_add(struct sctp_tcb *stcb, struct sctp_ifa *ifa,
int pending_delete_queued = 0;
/* see if peer supports ASCONF */
if (stcb->asoc.peer_supports_asconf == 0) {
if (stcb->asoc.asconf_supported == 0) {
return (-1);
}
@ -1434,13 +1422,12 @@ sctp_asconf_queue_sa_delete(struct sctp_tcb *stcb, struct sockaddr *sa)
{
struct sctp_ifa *ifa;
struct sctp_asconf_addr *aa, *aa_next;
uint32_t vrf_id;
if (stcb == NULL) {
return (-1);
}
/* see if peer supports ASCONF */
if (stcb->asoc.peer_supports_asconf == 0) {
if (stcb->asoc.asconf_supported == 0) {
return (-1);
}
/* make sure the request isn't already in the queue */
@ -1466,12 +1453,7 @@ sctp_asconf_queue_sa_delete(struct sctp_tcb *stcb, struct sockaddr *sa)
} /* for each aa */
/* find any existing ifa-- NOTE ifa CAN be allowed to be NULL */
if (stcb) {
vrf_id = stcb->asoc.vrf_id;
} else {
vrf_id = SCTP_DEFAULT_VRFID;
}
ifa = sctp_find_ifa_by_addr(sa, vrf_id, SCTP_ADDR_NOT_LOCKED);
ifa = sctp_find_ifa_by_addr(sa, stcb->asoc.vrf_id, SCTP_ADDR_NOT_LOCKED);
/* adding new request to the queue */
SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa),
@ -1560,7 +1542,7 @@ sctp_asconf_find_param(struct sctp_tcb *stcb, uint32_t correlation_id)
* notifications based on the error response
*/
static void
sctp_asconf_process_error(struct sctp_tcb *stcb,
sctp_asconf_process_error(struct sctp_tcb *stcb SCTP_UNUSED,
struct sctp_asconf_paramhdr *aph)
{
struct sctp_error_cause *eh;
@ -1598,10 +1580,7 @@ sctp_asconf_process_error(struct sctp_tcb *stcb,
switch (param_type) {
case SCTP_ADD_IP_ADDRESS:
case SCTP_DEL_IP_ADDRESS:
stcb->asoc.peer_supports_asconf = 0;
break;
case SCTP_SET_PRIM_ADDR:
stcb->asoc.peer_supports_asconf = 0;
break;
default:
break;
@ -1637,8 +1616,6 @@ sctp_asconf_process_param_ack(struct sctp_tcb *stcb,
SCTPDBG(SCTP_DEBUG_ASCONF1,
"process_param_ack: set primary IP address\n");
/* nothing to do... peer may start using this addr */
if (flag == 0)
stcb->asoc.peer_supports_asconf = 0;
break;
default:
/* should NEVER happen */
@ -1656,11 +1633,11 @@ sctp_asconf_process_param_ack(struct sctp_tcb *stcb,
* cleanup from a bad asconf ack parameter
*/
static void
sctp_asconf_ack_clear(struct sctp_tcb *stcb)
sctp_asconf_ack_clear(struct sctp_tcb *stcb SCTP_UNUSED)
{
/* assume peer doesn't really know how to do asconfs */
stcb->asoc.peer_supports_asconf = 0;
/* XXX we could free the pending queue here */
}
void
@ -1900,14 +1877,26 @@ sctp_addr_mgmt_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
* this is boundall or subset bound w/ASCONF allowed
*/
/* first, make sure it's a good address family */
/* first, make sure that the address is IPv4 or IPv6 and not jailed */
switch (ifa->address.sa.sa_family) {
#ifdef INET6
case AF_INET6:
#if defined(__FreeBSD__)
if (prison_check_ip6(inp->ip_inp.inp.inp_cred,
&ifa->address.sin6.sin6_addr) != 0) {
return;
}
#endif
break;
#endif
#ifdef INET
case AF_INET:
#if defined(__FreeBSD__)
if (prison_check_ip4(inp->ip_inp.inp.inp_cred,
&ifa->address.sin.sin_addr) != 0) {
return;
}
#endif
break;
#endif
default:
@ -1938,7 +1927,7 @@ sctp_addr_mgmt_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
{
struct sockaddr_in6 *sin6;
sin6 = (struct sockaddr_in6 *)&ifa->address.sin6;
sin6 = &ifa->address.sin6;
if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
/* we skip unspecifed addresses */
return;
@ -1971,7 +1960,7 @@ sctp_addr_mgmt_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
SCTP_IPV6_V6ONLY(inp6))
return;
sin = (struct sockaddr_in *)&ifa->address.sa;
sin = &ifa->address.sin;
if (sin->sin_addr.s_addr == 0) {
/* we skip unspecifed addresses */
return;
@ -1991,7 +1980,7 @@ sctp_addr_mgmt_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
/* queue an asconf for this address add/delete */
if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_DO_ASCONF)) {
/* does the peer do asconf? */
if (stcb->asoc.peer_supports_asconf) {
if (stcb->asoc.asconf_supported) {
/* queue an asconf for this addr */
status = sctp_asconf_queue_add(stcb, ifa, type);
@ -2129,11 +2118,17 @@ sctp_asconf_iterator_stcb(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
else
continue;
}
sin6 = (struct sockaddr_in6 *)&ifa->address.sin6;
sin6 = &ifa->address.sin6;
if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
/* we skip unspecifed addresses */
continue;
}
#if defined(__FreeBSD__)
if (prison_check_ip6(inp->ip_inp.inp.inp_cred,
&sin6->sin6_addr) != 0) {
continue;
}
#endif
if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
if (stcb->asoc.scope.local_scope == 0) {
continue;
@ -2159,11 +2154,17 @@ sctp_asconf_iterator_stcb(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
SCTP_IPV6_V6ONLY(inp6))
continue;
sin = (struct sockaddr_in *)&ifa->address.sa;
sin = &ifa->address.sin;
if (sin->sin_addr.s_addr == 0) {
/* we skip unspecifed addresses */
continue;
}
#if defined(__FreeBSD__)
if (prison_check_ip4(inp->ip_inp.inp.inp_cred,
&sin->sin_addr) != 0) {
continue;
}
#endif
if (stcb->asoc.scope.ipv4_local_scope == 0 &&
IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) {
continue;
@ -2221,7 +2222,7 @@ sctp_asconf_iterator_stcb(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
} else if (type == SCTP_SET_PRIM_ADDR) {
if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) {
/* must validate the ifa is in the ep */
if (sctp_is_addr_in_ep(stcb->sctp_ep,ifa) == 0) {
if (sctp_is_addr_in_ep(stcb->sctp_ep, ifa) == 0) {
continue;
}
} else {
@ -2233,7 +2234,7 @@ sctp_asconf_iterator_stcb(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
}
/* queue an asconf for this address add/delete */
if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_DO_ASCONF) &&
stcb->asoc.peer_supports_asconf) {
stcb->asoc.asconf_supported == 1) {
/* queue an asconf for this addr */
status = sctp_asconf_queue_add(stcb, ifa, type);
/*
@ -2284,7 +2285,7 @@ sctp_asconf_iterator_end(void *ptr, uint32_t val SCTP_UNUSED)
int32_t
sctp_set_primary_ip_address_sa(struct sctp_tcb *stcb, struct sockaddr *sa)
{
uint32_t vrf_id;
uint32_t vrf_id;
struct sctp_ifa *ifa;
/* find the ifa for the desired set primary */
@ -2472,11 +2473,17 @@ sctp_find_valid_localaddr(struct sctp_tcb *stcb, int addr_locked)
if (stcb->asoc.scope.ipv4_addr_legal) {
struct sockaddr_in *sin;
sin = (struct sockaddr_in *)&sctp_ifa->address.sa;
sin = &sctp_ifa->address.sin;
if (sin->sin_addr.s_addr == 0) {
/* skip unspecifed addresses */
continue;
}
#if defined(__FreeBSD__)
if (prison_check_ip4(stcb->sctp_ep->ip_inp.inp.inp_cred,
&sin->sin_addr) != 0) {
continue;
}
#endif
if (stcb->asoc.scope.ipv4_local_scope == 0 &&
IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))
continue;
@ -2500,11 +2507,17 @@ sctp_find_valid_localaddr(struct sctp_tcb *stcb, int addr_locked)
continue;
}
sin6 = (struct sockaddr_in6 *)&sctp_ifa->address.sa;
sin6 = &sctp_ifa->address.sin6;
if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
/* we skip unspecifed addresses */
continue;
}
#if defined(__FreeBSD__)
if (prison_check_ip6(stcb->sctp_ep->ip_inp.inp.inp_cred,
&sin6->sin6_addr) != 0) {
continue;
}
#endif
if (stcb->asoc.scope.local_scope == 0 &&
IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
continue;
@ -2762,16 +2775,13 @@ sctp_process_initack_addresses(struct sctp_tcb *stcb, struct mbuf *m,
struct sctp_paramhdr tmp_param, *ph;
uint16_t plen, ptype;
struct sctp_ifa *sctp_ifa;
union sctp_sockstore store;
#ifdef INET6
struct sctp_ipv6addr_param addr6_store;
struct sockaddr_in6 sin6;
#endif
#ifdef INET
struct sctp_ipv4addr_param addr4_store;
struct sockaddr_in sin;
#endif
struct sockaddr *sa;
uint32_t vrf_id;
SCTPDBG(SCTP_DEBUG_ASCONF2, "processing init-ack addresses\n");
if (stcb == NULL) /* Un-needed check for SA */
@ -2783,25 +2793,6 @@ sctp_process_initack_addresses(struct sctp_tcb *stcb, struct mbuf *m,
if ((offset + sizeof(struct sctp_paramhdr)) > length) {
return;
}
/* init the addresses */
#ifdef INET6
bzero(&sin6, sizeof(sin6));
sin6.sin6_family = AF_INET6;
#ifdef HAVE_SIN6_LEN
sin6.sin6_len = sizeof(sin6);
#endif
sin6.sin6_port = stcb->rport;
#endif
#ifdef INET
bzero(&sin, sizeof(sin));
sin.sin_family = AF_INET;
#ifdef HAVE_SIN_LEN
sin.sin_len = sizeof(sin);
#endif
sin.sin_port = stcb->rport;
#endif
/* go through the addresses in the init-ack */
ph = (struct sctp_paramhdr *)
sctp_m_getptr(m, offset, sizeof(struct sctp_paramhdr),
@ -2824,9 +2815,13 @@ sctp_process_initack_addresses(struct sctp_tcb *stcb, struct mbuf *m,
a6p == NULL) {
return;
}
memcpy(&sin6.sin6_addr, a6p->addr,
sizeof(struct in6_addr));
sa = (struct sockaddr *)&sin6;
memset(&store, 0, sizeof(union sctp_sockstore));
store.sin6.sin6_family = AF_INET6;
#ifdef HAVE_SIN6_LEN
store.sin6.sin6_len = sizeof(struct sockaddr_in6);
#endif
store.sin6.sin6_port = stcb->rport;
memcpy(&store.sin6.sin6_addr, a6p->addr, sizeof(struct in6_addr));
break;
}
#endif
@ -2843,8 +2838,13 @@ sctp_process_initack_addresses(struct sctp_tcb *stcb, struct mbuf *m,
a4p == NULL) {
return;
}
sin.sin_addr.s_addr = a4p->addr;
sa = (struct sockaddr *)&sin;
memset(&store, 0, sizeof(union sctp_sockstore));
store.sin.sin_family = AF_INET;
#ifdef HAVE_SIN_LEN
store.sin.sin_len = sizeof(struct sockaddr_in);
#endif
store.sin.sin_port = stcb->rport;
store.sin.sin_addr.s_addr = a4p->addr;
break;
}
#endif
@ -2853,12 +2853,7 @@ sctp_process_initack_addresses(struct sctp_tcb *stcb, struct mbuf *m,
}
/* see if this address really (still) exists */
if (stcb) {
vrf_id = stcb->asoc.vrf_id;
} else {
vrf_id = SCTP_DEFAULT_VRFID;
}
sctp_ifa = sctp_find_ifa_by_addr(sa, vrf_id,
sctp_ifa = sctp_find_ifa_by_addr(&store.sa, stcb->asoc.vrf_id,
SCTP_ADDR_NOT_LOCKED);
if (sctp_ifa == NULL) {
/* address doesn't exist anymore */
@ -2867,9 +2862,9 @@ sctp_process_initack_addresses(struct sctp_tcb *stcb, struct mbuf *m,
/* are ASCONFs allowed ? */
if ((sctp_is_feature_on(stcb->sctp_ep,
SCTP_PCB_FLAGS_DO_ASCONF)) &&
stcb->asoc.peer_supports_asconf) {
stcb->asoc.asconf_supported) {
/* queue an ASCONF DEL_IP_ADDRESS */
status = sctp_asconf_queue_sa_delete(stcb, sa);
status = sctp_asconf_queue_sa_delete(stcb, &store.sa);
/*
* if queued ok, and in correct state, send
* out the ASCONF.
@ -2903,7 +2898,7 @@ next_addr:
if ((offset + sizeof(struct sctp_paramhdr)) > length)
return;
ph = (struct sctp_paramhdr *)sctp_m_getptr(m, offset,
sizeof(struct sctp_paramhdr), (uint8_t *) & tmp_param);
sizeof(struct sctp_paramhdr), (uint8_t *)&tmp_param);
} /* while */
}
@ -3115,7 +3110,13 @@ sctp_check_address_list_all(struct sctp_tcb *stcb, struct mbuf *m, int offset,
switch (sctp_ifa->address.sa.sa_family) {
#ifdef INET
case AF_INET:
sin = (struct sockaddr_in *)&sctp_ifa->address.sin;
sin = &sctp_ifa->address.sin;
#if defined(__FreeBSD__)
if (prison_check_ip4(stcb->sctp_ep->ip_inp.inp.inp_cred,
&sin->sin_addr) != 0) {
continue;
}
#endif
if ((ipv4_scope == 0) &&
(IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))) {
/* private address not in scope */
@ -3125,7 +3126,13 @@ sctp_check_address_list_all(struct sctp_tcb *stcb, struct mbuf *m, int offset,
#endif
#ifdef INET6
case AF_INET6:
sin6 = (struct sockaddr_in6 *)&sctp_ifa->address.sin6;
sin6 = &sctp_ifa->address.sin6;
#if defined(__FreeBSD__)
if (prison_check_ip6(stcb->sctp_ep->ip_inp.inp.inp_cred,
&sin6->sin6_addr) != 0) {
continue;
}
#endif
if ((local_scope == 0) &&
(IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))) {
continue;
@ -3202,7 +3209,7 @@ sctp_addr_mgmt_ep_sa(struct sctp_inpcb *inp, struct sockaddr *sa,
#endif
if (sctp_ifap) {
ifa = sctp_ifap;
} else if (type == SCTP_ADD_IP_ADDRESS) {
} else if (type == SCTP_ADD_IP_ADDRESS) {
/* For an add the address MUST be on the system */
ifa = sctp_find_ifa_by_addr(sa, vrf_id, SCTP_ADDR_NOT_LOCKED);
} else if (type == SCTP_DEL_IP_ADDRESS) {
@ -3360,6 +3367,11 @@ sctp_asconf_send_nat_state_update(struct sctp_tcb *stcb,
TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next);
break;
#endif
default:
SCTPDBG(SCTP_DEBUG_ASCONF1,
"sctp_asconf_send_nat_state_update: unknown address family\n");
SCTP_FREE(aa, SCTP_M_ASC_ADDR);
return;
}
SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa),
SCTP_M_ASC_ADDR);
@ -3393,6 +3405,11 @@ sctp_asconf_send_nat_state_update(struct sctp_tcb *stcb,
TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next);
break;
#endif
default:
SCTPDBG(SCTP_DEBUG_ASCONF1,
"sctp_asconf_send_nat_state_update: unknown address family\n");
SCTP_FREE(aa, SCTP_M_ASC_ADDR);
return;
}
/* Now we must hunt the addresses and add all global addresses */
if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
@ -3413,6 +3430,12 @@ sctp_asconf_send_nat_state_update(struct sctp_tcb *stcb,
#ifdef INET
case AF_INET:
to = &sctp_ifap->address.sin;
#if defined(__FreeBSD__)
if (prison_check_ip4(stcb->sctp_ep->ip_inp.inp.inp_cred,
&to->sin_addr) != 0) {
continue;
}
#endif
if (IN4_ISPRIVATE_ADDRESS(&to->sin_addr)) {
continue;
}
@ -3424,6 +3447,12 @@ sctp_asconf_send_nat_state_update(struct sctp_tcb *stcb,
#ifdef INET6
case AF_INET6:
to6 = &sctp_ifap->address.sin6;
#if defined(__FreeBSD__)
if (prison_check_ip6(stcb->sctp_ep->ip_inp.inp.inp_cred,
&to6->sin6_addr) != 0) {
continue;
}
#endif
if (IN6_IS_ADDR_LOOPBACK(&to6->sin6_addr)) {
continue;
}

View File

@ -32,7 +32,7 @@
#ifdef __FreeBSD__
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: head/sys/netinet/sctp_auth.c 257804 2013-11-07 18:50:11Z tuexen $");
__FBSDID("$FreeBSD: head/sys/netinet/sctp_auth.c 271673 2014-09-16 14:20:33Z tuexen $");
#endif
#include <netinet/sctp_os.h>
@ -135,11 +135,6 @@ sctp_auth_delete_chunk(uint8_t chunk, sctp_auth_chklist_t *list)
if (list == NULL)
return (-1);
/* is chunk restricted? */
if ((chunk == SCTP_ASCONF) ||
(chunk == SCTP_ASCONF_ACK)) {
return (-1);
}
if (list->chunks[chunk] == 1) {
list->chunks[chunk] = 0;
list->num_chunks--;
@ -159,16 +154,6 @@ sctp_auth_get_chklist_size(const sctp_auth_chklist_t *list)
return (list->num_chunks);
}
/*
* set the default list of chunks requiring AUTH
*/
void
sctp_auth_set_default_chunks(sctp_auth_chklist_t *list)
{
(void)sctp_auth_add_chunk(SCTP_ASCONF, list);
(void)sctp_auth_add_chunk(SCTP_ASCONF_ACK, list);
}
/*
* return the current number and list of required chunks caller must
* guarantee ptr has space for up to 256 bytes
@ -397,9 +382,9 @@ sctp_compare_key(sctp_key_t *key1, sctp_key_t *key2)
val1 = (i < (maxlen - key1len)) ? 0 : *(key_1++);
val2 = (i < (maxlen - key2len)) ? 0 : *(key_2++);
if (val1 > val2) {
return (1);
return (1);
} else if (val1 < val2) {
return (-1);
return (-1);
}
}
/* keys are equal value, so check lengths */
@ -648,7 +633,7 @@ sctp_copy_skeylist(const struct sctp_keyhead *src, struct sctp_keyhead *dest)
sctp_hmaclist_t *
sctp_alloc_hmaclist(uint8_t num_hmacs)
sctp_alloc_hmaclist(uint16_t num_hmacs)
{
sctp_hmaclist_t *new_list;
int alloc_size;
@ -800,7 +785,7 @@ sctp_verify_hmac_param (struct sctp_auth_hmac_algo *hmacs, uint32_t num_hmacs)
for (i = 0; i < num_hmacs; i++) {
if (ntohs(hmacs->hmac_ids[i]) == SCTP_AUTH_HMAC_ID_SHA1) {
return (0);
return (0);
}
}
return (-1);
@ -1479,8 +1464,8 @@ sctp_auth_get_cookie_params(struct sctp_tcb *stcb, struct mbuf *m,
p_random = (struct sctp_auth_random *)phdr;
random_len = plen - sizeof(*p_random);
} else if (ptype == SCTP_HMAC_LIST) {
int num_hmacs;
int i;
uint16_t num_hmacs;
uint16_t i;
if (plen > sizeof(hmacs_store))
break;
@ -1554,7 +1539,7 @@ sctp_auth_get_cookie_params(struct sctp_tcb *stcb, struct mbuf *m,
}
}
if (stcb->asoc.authinfo.random != NULL)
sctp_free_key(stcb->asoc.authinfo.random);
sctp_free_key(stcb->asoc.authinfo.random);
stcb->asoc.authinfo.random = new_key;
stcb->asoc.authinfo.random_len = random_len;
sctp_clear_cachedkeys(stcb, stcb->asoc.authinfo.assoc_keyid);
@ -1818,6 +1803,7 @@ sctp_notify_authentication(struct sctp_tcb *stcb, uint32_t indication,
SCTP_BUF_LEN(m_notify) = 0;
auth = mtod(m_notify, struct sctp_authkey_event *);
memset(auth, 0, sizeof(struct sctp_authkey_event));
auth->auth_type = SCTP_AUTHENTICATION_EVENT;
auth->auth_flags = 0;
auth->auth_length = sizeof(*auth);
@ -1975,8 +1961,7 @@ sctp_validate_init_auth_params(struct mbuf *m, int offset, int limit)
"SCTP: peer sent chunk list w/o AUTH\n");
return (-1);
}
if (!SCTP_BASE_SYSCTL(sctp_asconf_auth_nochk) && peer_supports_asconf &&
!peer_supports_auth) {
if (peer_supports_asconf && !peer_supports_auth) {
SCTPDBG(SCTP_DEBUG_AUTH1,
"SCTP: peer supports ASCONF but not AUTH\n");
return (-1);

View File

@ -32,7 +32,7 @@
#ifdef __FreeBSD__
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: head/sys/netinet/sctp_auth.h 257804 2013-11-07 18:50:11Z tuexen $");
__FBSDID("$FreeBSD: head/sys/netinet/sctp_auth.h 271673 2014-09-16 14:20:33Z tuexen $");
#endif
#ifndef _NETINET_SCTP_AUTH_H_
@ -116,7 +116,6 @@ extern sctp_auth_chklist_t *sctp_copy_chunklist(sctp_auth_chklist_t *chklist);
extern int sctp_auth_add_chunk(uint8_t chunk, sctp_auth_chklist_t *list);
extern int sctp_auth_delete_chunk(uint8_t chunk, sctp_auth_chklist_t *list);
extern size_t sctp_auth_get_chklist_size(const sctp_auth_chklist_t *list);
extern void sctp_auth_set_default_chunks(sctp_auth_chklist_t *list);
extern int sctp_serialize_auth_chunks(const sctp_auth_chklist_t *list,
uint8_t *ptr);
extern int sctp_pack_auth_chunks(const sctp_auth_chklist_t *list,
@ -150,7 +149,7 @@ extern void sctp_auth_key_release(struct sctp_tcb *stcb, uint16_t keyid,
/* hmac list handling */
extern sctp_hmaclist_t *sctp_alloc_hmaclist(uint8_t num_hmacs);
extern sctp_hmaclist_t *sctp_alloc_hmaclist(uint16_t num_hmacs);
extern void sctp_free_hmaclist(sctp_hmaclist_t *list);
extern int sctp_auth_add_hmacid(sctp_hmaclist_t *list, uint16_t hmac_id);
extern sctp_hmaclist_t *sctp_copy_hmaclist(sctp_hmaclist_t *list);

View File

@ -32,7 +32,7 @@
#ifdef __FreeBSD__
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: head/sys/netinet/sctp_bsd_addr.c 258765 2013-11-30 12:51:19Z tuexen $");
__FBSDID("$FreeBSD: head/sys/netinet/sctp_bsd_addr.c 276914 2015-01-10 20:49:57Z tuexen $");
#endif
#include <netinet/sctp_os.h>
@ -48,14 +48,9 @@ __FBSDID("$FreeBSD: head/sys/netinet/sctp_bsd_addr.c 258765 2013-11-30 12:51:19Z
#include <netinet/sctp_asconf.h>
#include <netinet/sctp_sysctl.h>
#include <netinet/sctp_indata.h>
#if defined(ANDROID)
#include <unistd.h>
#include <ifaddrs-android-ext.h>
#else
#if defined(__FreeBSD__)
#include <sys/unistd.h>
#endif
#endif
/* Declare all of our malloc named types */
#ifndef __Panda__
@ -360,7 +355,7 @@ sctp_init_ifns_for_vrf(int vrfid)
continue;
}
ifa = (struct ifaddrs*)malloc(sizeof(struct ifaddrs));
ifa->ifa_name = strdup(pAdapt->AdapterName);
ifa->ifa_name = _strdup(pAdapt->AdapterName);
ifa->ifa_flags = pAdapt->Flags;
ifa->ifa_addr = (struct sockaddr *)malloc(sizeof(struct sockaddr_in));
memcpy(ifa->ifa_addr, pUnicast->Address.lpSockaddr, sizeof(struct sockaddr_in));
@ -408,7 +403,7 @@ sctp_init_ifns_for_vrf(int vrfid)
if (pAdapt->IfType == IF_TYPE_IEEE80211 || pAdapt->IfType == IF_TYPE_ETHERNET_CSMACD) {
for (pUnicast = pAdapt->FirstUnicastAddress; pUnicast; pUnicast = pUnicast->Next) {
ifa = (struct ifaddrs*)malloc(sizeof(struct ifaddrs));
ifa->ifa_name = strdup(pAdapt->AdapterName);
ifa->ifa_name = _strdup(pAdapt->AdapterName);
ifa->ifa_flags = pAdapt->Flags;
ifa->ifa_addr = (struct sockaddr *)malloc(sizeof(struct sockaddr_in6));
memcpy(ifa->ifa_addr, pUnicast->Address.lpSockaddr, sizeof(struct sockaddr_in6));
@ -750,7 +745,7 @@ sctp_addr_change(struct ifaddr *ifa, int cmd)
ifa->ifa_ifp->if_index,
ifa->ifa_ifp->if_xname);
#endif
/* We don't bump refcount here so when it completes
* the final delete will happen.
*/
@ -842,24 +837,41 @@ sctp_get_mbuf_for_msg(unsigned int space_needed, int want_header,
}
if (SCTP_BUF_IS_EXTENDED(m) == 0) {
sctp_m_freem(m);
return (NULL);
sctp_m_freem(m);
return (NULL);
}
}
SCTP_BUF_LEN(m) = 0;
SCTP_BUF_NEXT(m) = SCTP_BUF_NEXT_PKT(m) = NULL;
#if defined(__Userspace__)
/* __Userspace__
* Check if anything need to be done to ensure logging works
*/
#endif
#ifdef SCTP_MBUF_LOGGING
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) {
if (SCTP_BUF_IS_EXTENDED(m)) {
sctp_log_mb(m, SCTP_MBUF_IALLOC);
sctp_log_mb(m, SCTP_MBUF_IALLOC);
}
#endif
#elif defined(__FreeBSD__) && __FreeBSD_version > 1100052
m = m_getm2(NULL, space_needed, how, type, want_header ? M_PKTHDR : 0);
if (m == NULL) {
/* bad, no memory */
return (m);
}
if (allonebuf) {
if (SCTP_BUF_SIZE(m) < space_needed) {
m_freem(m);
return (NULL);
}
}
if (SCTP_BUF_NEXT(m)) {
sctp_m_freem(SCTP_BUF_NEXT(m));
SCTP_BUF_NEXT(m) = NULL;
}
#ifdef SCTP_MBUF_LOGGING
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) {
sctp_log_mb(m, SCTP_MBUF_IALLOC);
}
#endif
#elif defined(__FreeBSD__) && __FreeBSD_version > 602000
m = m_getm2(NULL, space_needed, how, type, want_header ? M_PKTHDR : 0);
@ -883,14 +895,12 @@ sctp_get_mbuf_for_msg(unsigned int space_needed, int want_header,
}
}
if (SCTP_BUF_NEXT(m)) {
sctp_m_freem( SCTP_BUF_NEXT(m));
sctp_m_freem(SCTP_BUF_NEXT(m));
SCTP_BUF_NEXT(m) = NULL;
}
#ifdef SCTP_MBUF_LOGGING
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) {
if (SCTP_BUF_IS_EXTENDED(m)) {
sctp_log_mb(m, SCTP_MBUF_IALLOC);
}
sctp_log_mb(m, SCTP_MBUF_IALLOC);
}
#endif
#else
@ -951,9 +961,7 @@ sctp_get_mbuf_for_msg(unsigned int space_needed, int want_header,
SCTP_BUF_NEXT(m) = SCTP_BUF_NEXT_PKT(m) = NULL;
#ifdef SCTP_MBUF_LOGGING
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) {
if (SCTP_BUF_IS_EXTENDED(m)) {
sctp_log_mb(m, SCTP_MBUF_IALLOC);
}
sctp_log_mb(m, SCTP_MBUF_IALLOC);
}
#endif
#endif

View File

@ -64,10 +64,8 @@ extern int ticks;
/*
* SCTP_TIMERQ_LOCK protects:
* - SCTP_BASE_INFO(callqueue)
* - sctp_os_timer_current: current timer in process
* - sctp_os_timer_next: next timer to check
*/
static sctp_os_timer_t *sctp_os_timer_current = NULL;
static sctp_os_timer_t *sctp_os_timer_next = NULL;
void
@ -153,11 +151,9 @@ sctp_handle_tick(int delta)
c_func = c->c_func;
c_arg = c->c_arg;
c->c_flags &= ~SCTP_CALLOUT_PENDING;
sctp_os_timer_current = c;
SCTP_TIMERQ_UNLOCK();
c_func(c_arg);
SCTP_TIMERQ_LOCK();
sctp_os_timer_current = NULL;
c = sctp_os_timer_next;
} else {
c = TAILQ_NEXT(c, tqe);

View File

@ -32,7 +32,7 @@
#ifdef __FreeBSD__
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: head/sys/netinet/sctp_cc_functions.c 240158 2012-09-06 07:03:56Z tuexen $");
__FBSDID("$FreeBSD: head/sys/netinet/sctp_cc_functions.c 271672 2014-09-16 13:48:46Z tuexen $");
#endif
#include <netinet/sctp_os.h>
@ -1218,12 +1218,9 @@ sctp_cwnd_update_after_packet_dropped(struct sctp_tcb *stcb,
uint32_t *bottle_bw, uint32_t *on_queue)
{
uint32_t bw_avail;
int rtt;
unsigned int incr;
int old_cwnd = net->cwnd;
/* need real RTT in msd for this calc */
rtt = net->rtt / 1000;
/* get bottle neck bw */
*bottle_bw = ntohl(cp->bottle_bw);
/* and whats on queue */
@ -1232,10 +1229,11 @@ sctp_cwnd_update_after_packet_dropped(struct sctp_tcb *stcb,
* adjust the on-queue if our flight is more it could be
* that the router has not yet gotten data "in-flight" to it
*/
if (*on_queue < net->flight_size)
if (*on_queue < net->flight_size) {
*on_queue = net->flight_size;
/* calculate the available space */
bw_avail = (*bottle_bw * rtt) / 1000;
}
/* rtt is measured in micro seconds, bottle_bw in bytes per second */
bw_avail = (uint32_t)(((uint64_t)(*bottle_bw) * net->rtt) / (uint64_t)1000000);
if (bw_avail > *bottle_bw) {
/*
* Cap the growth to no more than the bottle neck.
@ -1253,8 +1251,8 @@ sctp_cwnd_update_after_packet_dropped(struct sctp_tcb *stcb,
* else to be "added to the fire".
*/
int seg_inflight, seg_onqueue, my_portion;
net->partial_bytes_acked = 0;
net->partial_bytes_acked = 0;
/* how much are we over queue size? */
incr = *on_queue - bw_avail;
if (stcb->asoc.seen_a_sack_this_pkt) {

View File

@ -32,7 +32,7 @@
#ifdef __FreeBSD__
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: head/sys/netinet/sctp_constants.h 256556 2013-10-15 20:21:27Z tuexen $");
__FBSDID("$FreeBSD: head/sys/netinet/sctp_constants.h 271204 2014-09-06 19:12:14Z tuexen $");
#endif
#ifndef _NETINET_SCTP_CONSTANTS_H_
@ -41,20 +41,10 @@ __FBSDID("$FreeBSD: head/sys/netinet/sctp_constants.h 256556 2013-10-15 20:21:27
#if defined(__Userspace_os_Windows)
extern void getwintimeofday(struct timeval *tv);
#endif
/* IANA assigned port number for SCTP over UDP encapsulation */
#ifdef __FreeBSD__
/* For freebsd we cannot bind the port at
* startup. Otherwise what will happen is
* we really won't be bound. The user must
* put it into the sysctl... or we need
* to build a special timer for this to allow
* us to wait 1 second or so after the system
* comes up.
*/
#define SCTP_OVER_UDP_TUNNELING_PORT 0
#else
#define SCTP_OVER_UDP_TUNNELING_PORT 9899
#endif
/* Number of packets to get before sack sent by default */
#define SCTP_DEFAULT_SACK_FREQ 2
@ -282,42 +272,9 @@ extern void getwintimeofday(struct timeval *tv);
/* how many addresses per assoc remote and local */
#define SCTP_SCALE_FOR_ADDR 2
/* default AUTO_ASCONF mode enable(1)/disable(0) value (sysctl) */
#if defined(__APPLE__)
#if !defined(SCTP_APPLE_AUTO_ASCONF)
#define SCTP_DEFAULT_AUTO_ASCONF 0
#else
#define SCTP_DEFAULT_AUTO_ASCONF 1
#endif
#else
#define SCTP_DEFAULT_AUTO_ASCONF 1
#endif
/* default MULTIPLE_ASCONF mode enable(1)/disable(0) value (sysctl) */
#define SCTP_DEFAULT_MULTIPLE_ASCONFS 0
/* default MOBILITY_BASE mode enable(1)/disable(0) value (sysctl) */
#if defined(__APPLE__)
#if !defined(SCTP_APPLE_MOBILITY_BASE)
#define SCTP_DEFAULT_MOBILITY_BASE 0
#else
#define SCTP_DEFAULT_MOBILITY_BASE 1
#endif
#else
#define SCTP_DEFAULT_MOBILITY_BASE 0
#endif
/* default MOBILITY_FASTHANDOFF mode enable(1)/disable(0) value (sysctl) */
#if defined(__APPLE__)
#if !defined(SCTP_APPLE_MOBILITY_FASTHANDOFF)
#define SCTP_DEFAULT_MOBILITY_FASTHANDOFF 0
#else
#define SCTP_DEFAULT_MOBILITY_FASTHANDOFF 1
#endif
#else
#define SCTP_DEFAULT_MOBILITY_FASTHANDOFF 0
#endif
/*
* Theshold for rwnd updates, we have to read (sb_hiwat >>
* SCTP_RWND_HIWAT_SHIFT) before we will look to see if we need to send a
@ -819,6 +776,9 @@ extern void getwintimeofday(struct timeval *tv);
*/
#define SCTP_DEFAULT_SPLIT_POINT_MIN 2904
/* Maximum length of diagnostic information in error causes */
#define SCTP_DIAG_INFO_LEN 64
/* ABORT CODES and other tell-tale location
* codes are generated by adding the below
* to the instance id.

View File

@ -32,7 +32,7 @@
#ifdef __FreeBSD__
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: head/sys/netinet/sctp_header.h 240198 2012-09-07 13:36:42Z tuexen $");
__FBSDID("$FreeBSD: head/sys/netinet/sctp_header.h 273168 2014-10-16 15:36:04Z tuexen $");
#endif
#ifndef _NETINET_SCTP_HEADER_H_
@ -94,12 +94,6 @@ struct sctp_supported_addr_param {
uint16_t addr_type[2]; /* array of supported address types */
} SCTP_PACKED;
/* ECN parameter */
struct sctp_ecn_supported_param {
struct sctp_paramhdr ph;/* type=SCTP_ECN_CAPABLE */
} SCTP_PACKED;
/* heartbeat info parameter */
struct sctp_heartbeat_info_param {
struct sctp_paramhdr ph;
@ -474,6 +468,11 @@ struct sctp_pktdrop_chunk {
/**********STREAM RESET STUFF ******************/
struct sctp_stream_reset_request {
struct sctp_paramhdr ph;
uint32_t request_seq;
} SCTP_PACKED;
struct sctp_stream_reset_out_request {
struct sctp_paramhdr ph;
uint32_t request_seq; /* monotonically increasing seq no */
@ -488,7 +487,6 @@ struct sctp_stream_reset_in_request {
uint16_t list_of_streams[]; /* if not all list of streams */
} SCTP_PACKED;
struct sctp_stream_reset_tsn_request {
struct sctp_paramhdr ph;
uint32_t request_seq;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -32,7 +32,7 @@
#ifdef __FreeBSD__
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: head/sys/netinet/sctp_input.h 240198 2012-09-07 13:36:42Z tuexen $");
__FBSDID("$FreeBSD: head/sys/netinet/sctp_input.h 273168 2014-10-16 15:36:04Z tuexen $");
#endif
#ifndef _NETINET_SCTP_INPUT_H_
@ -52,7 +52,7 @@ sctp_common_input_processing(struct mbuf **, int, int, int,
#endif
uint32_t, uint16_t);
struct sctp_stream_reset_out_request *
struct sctp_stream_reset_request *
sctp_find_stream_reset(struct sctp_tcb *stcb, uint32_t seq,
struct sctp_tmit_chunk **bchk);

View File

@ -103,7 +103,6 @@ typedef HANDLE userland_thread_t;
#define n_time unsigned __int32
#define sa_family_t unsigned __int8
#define ssize_t __int64
#define IFNAMSIZ 64
#define __func__ __FUNCTION__
#ifndef EWOULDBLOCK
@ -220,12 +219,10 @@ typedef char* caddr_t;
#define bzero(buf, len) memset(buf, 0, len)
#define bcopy(srcKey, dstKey, len) memcpy(dstKey, srcKey, len)
#if _MSC_VER < 1900
#define snprintf(data, size, format, name) _snprintf_s(data, size, _TRUNCATE, format, name)
#define snprintf(data, size, format, ...) _snprintf_s(data, size, _TRUNCATE, format, __VA_ARGS__)
#endif
#define inline __inline
#define __inline__ __inline
#define random() rand()
#define srandom(s) srand(s)
#define MSG_EOR 0x8 /* data completes record */
#define MSG_DONTWAIT 0x80 /* this message should be nonblocking */
@ -267,6 +264,32 @@ typedef char* caddr_t;
#define SCTP_GET_IF_INDEX_FROM_ROUTE(ro) 1 /* compiles... TODO use routing socket to determine */
#define BIG_ENDIAN 1
#define LITTLE_ENDIAN 0
#ifdef WORDS_BIGENDIAN
#define BYTE_ORDER BIG_ENDIAN
#else
#define BYTE_ORDER LITTLE_ENDIAN
#endif
#else /* !defined(Userspace_os_Windows) */
#include <sys/cdefs.h> /* needed? added from old __FreeBSD__ */
#include <sys/socket.h>
#if defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD) || defined(__Userspace_os_Linux) || defined(__Userspace_os_NetBSD) || defined(__Userspace_os_OpenBSD) || defined(__Userspace_os_NaCl)
#include <pthread.h>
#endif
typedef pthread_mutex_t userland_mutex_t;
typedef pthread_cond_t userland_cond_t;
typedef pthread_t userland_thread_t;
#endif
#if defined(__Userspace_os_Windows) || defined(__Userspace_os_NaCl)
#define IFNAMSIZ 64
#define random() rand()
#define srandom(s) srand(s)
#define timeradd(tvp, uvp, vvp) \
do { \
(vvp)->tv_sec = (tvp)->tv_sec + (uvp)->tv_sec; \
@ -287,30 +310,57 @@ typedef char* caddr_t;
} \
} while (0)
#define BIG_ENDIAN 1
#define LITTLE_ENDIAN 0
#ifdef WORDS_BIGENDIAN
#define BYTE_ORDER BIG_ENDIAN
#else
#define BYTE_ORDER LITTLE_ENDIAN
#endif
/*#include <packon.h>
#pragma pack(push, 1)*/
struct ip {
u_char ip_hl:4, ip_v:4;
u_char ip_tos;
u_short ip_len;
u_short ip_id;
u_short ip_off;
#define IP_RP 0x8000
#define IP_DF 0x4000
#define IP_MF 0x2000
#define IP_OFFMASK 0x1fff
u_char ip_ttl;
u_char ip_p;
u_short ip_sum;
struct in_addr ip_src, ip_dst;
};
struct ifaddrs {
struct ifaddrs *ifa_next;
char *ifa_name;
unsigned int ifa_flags;
struct sockaddr *ifa_addr;
struct sockaddr *ifa_netmask;
struct sockaddr *ifa_dstaddr;
void *ifa_data;
};
struct udphdr {
uint16_t uh_sport;
uint16_t uh_dport;
uint16_t uh_ulen;
uint16_t uh_sum;
};
struct iovec {
ULONG len;
CHAR FAR *buf;
unsigned long len;
char *buf;
};
#define iov_base buf
#define iov_len len
struct ifa_msghdr {
unsigned __int16 ifam_msglen;
uint16_t ifam_msglen;
unsigned char ifam_version;
unsigned char ifam_type;
__int32 ifam_addrs;
__int32 ifam_flags;
unsigned __int16 ifam_index;
__int32 ifam_metric;
uint32_t ifam_addrs;
uint32_t ifam_flags;
uint16_t ifam_index;
uint32_t ifam_metric;
};
struct ifdevmtu {
@ -343,7 +393,7 @@ struct ifreq {
char* ifru_data;
struct ifdevmtu ifru_devmtu;
struct ifkpi ifru_kpi;
unsigned __int32 ifru_wake_flags;
uint32_t ifru_wake_flags;
} ifr_ifru;
#define ifr_addr ifr_ifru.ifru_addr
#define ifr_dstaddr ifr_ifru.ifru_dstaddr
@ -361,55 +411,13 @@ struct ifreq {
#define ifr_wake_flags ifr_ifru.ifru_wake_flags
};
/*#include <packon.h>
#pragma pack(push, 1)*/
struct ip {
u_char ip_hl:4, ip_v:4;
u_char ip_tos;
u_short ip_len;
u_short ip_id;
u_short ip_off;
#define IP_RP 0x8000
#define IP_DF 0x4000
#define IP_MF 0x2000
#define IP_OFFMASK 0x1fff
u_char ip_ttl;
u_char ip_p;
u_short ip_sum;
struct in_addr ip_src, ip_dst;
};
struct ifaddrs {
struct ifaddrs *ifa_next;
char *ifa_name;
unsigned int ifa_flags;
struct sockaddr *ifa_addr;
struct sockaddr *ifa_netmask;
struct sockaddr *ifa_dstaddr;
void *ifa_data;
};
struct udphdr {
unsigned __int16 uh_sport;
unsigned __int16 uh_dport;
unsigned __int16 uh_ulen;
unsigned __int16 uh_sum;
};
#endif
#if defined(__Userspace_os_Windows)
int Win_getifaddrs(struct ifaddrs**);
#define getifaddrs(interfaces) (int)Win_getifaddrs(interfaces)
int win_if_nametoindex(const char *);
#define if_nametoindex(x) win_if_nametoindex(x)
#else /* !defined(Userspace_os_Windows) */
#include <sys/cdefs.h> /* needed? added from old __FreeBSD__ */
#include <sys/socket.h>
#if defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD) || defined(__Userspace_os_Linux) || defined(__Userspace_os_NetBSD) || defined(__Userspace_os_OpenBSD) || defined(ANDROID)
#include <pthread.h>
#endif
typedef pthread_mutex_t userland_mutex_t;
typedef pthread_cond_t userland_cond_t;
typedef pthread_t userland_thread_t;
#endif
#define mtx_lock(arg1)
@ -471,11 +479,13 @@ struct sx {int dummy;};
* userspace as well? */
/* on FreeBSD, this results in a redefintion of struct route */
/* #include <net/route.h> */
#if !defined(__Userspace_os_Windows)
#if !defined(__Userspace_os_Windows) && !defined(__Userspace_os_NaCl)
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#endif
#if defined(HAVE_NETINET_IP_ICMP_H)
#include <netinet/ip_icmp.h>
#else
#include <user_ip_icmp.h>
@ -486,7 +496,7 @@ struct sx {int dummy;};
/* for getifaddrs */
#include <sys/types.h>
#if !defined(__Userspace_os_Windows)
#if !defined(ANDROID) && (defined(INET) || defined(INET6))
#if defined(INET) || defined(INET6)
#include <ifaddrs.h>
#endif
@ -1093,7 +1103,7 @@ sctp_get_mbuf_for_msg(unsigned int space_needed, int want_header, int how, int a
/* with the current included files, this is defined in Linux but
* in FreeBSD, it is behind a _KERNEL in sys/socket.h ...
*/
#if defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD) || defined(__Userspace_os_OpenBSD)
#if defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD) || defined(__Userspace_os_OpenBSD) || defined(__Userspace_os_NaCl)
/* stolen from /usr/include/sys/socket.h */
#define CMSG_ALIGN(n) _ALIGN(n)
#elif defined(__Userspace_os_NetBSD)
@ -1151,4 +1161,12 @@ sctp_get_mbuf_for_msg(unsigned int space_needed, int want_header, int how, int a
#define TAILQ_FOREACH_SAFE TAILQ_FOREACH_MUTABLE
#define LIST_FOREACH_SAFE LIST_FOREACH_MUTABLE
#endif
#if defined(__Userspace_os_NaCl)
#define timercmp(tvp, uvp, cmp) \
(((tvp)->tv_sec == (uvp)->tv_sec) ? \
((tvp)->tv_usec cmp (uvp)->tv_usec) : \
((tvp)->tv_sec cmp (uvp)->tv_sec))
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@ -32,7 +32,7 @@
#ifdef __FreeBSD__
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: head/sys/netinet/sctp_output.h 246595 2013-02-09 17:26:14Z tuexen $");
__FBSDID("$FreeBSD: head/sys/netinet/sctp_output.h 272751 2014-10-08 15:30:59Z tuexen $");
#endif
#ifndef _NETINET_SCTP_OUTPUT_H_
@ -208,8 +208,8 @@ sctp_add_stream_reset_result_tsn(struct sctp_tmit_chunk *,
uint32_t, uint32_t, uint32_t, uint32_t);
int
sctp_send_str_reset_req(struct sctp_tcb *, int , uint16_t *, uint8_t, uint8_t,
uint8_t, uint8_t, uint16_t, uint16_t, uint8_t);
sctp_send_str_reset_req(struct sctp_tcb *, uint16_t , uint16_t *, uint8_t,
uint8_t, uint8_t, uint8_t, uint16_t, uint16_t, uint8_t);
void
sctp_send_abort(struct mbuf *, int, struct sockaddr *, struct sockaddr *,

View File

@ -32,7 +32,7 @@
#ifdef __FreeBSD__
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: head/sys/netinet/sctp_pcb.c 258765 2013-11-30 12:51:19Z tuexen $");
__FBSDID("$FreeBSD: head/sys/netinet/sctp_pcb.c 277031 2015-01-11 21:55:30Z tuexen $");
#endif
#include <netinet/sctp_os.h>
@ -52,9 +52,11 @@ __FBSDID("$FreeBSD: head/sys/netinet/sctp_pcb.c 258765 2013-11-30 12:51:19Z tuex
#if defined(__FreeBSD__) && __FreeBSD_version >= 803000
#include <netinet/sctp_dtrace_define.h>
#endif
#if defined(INET) || defined(INET6)
#if !defined(__Userspace_os_Windows)
#include <netinet/udp.h>
#endif
#endif
#ifdef INET6
#if defined(__Userspace__)
#include "user_ip6_var.h"
@ -222,8 +224,8 @@ sctp_allocate_vrf(int vrf_id)
}
SCTP_MALLOC(vrf, struct sctp_vrf *, sizeof(struct sctp_vrf),
SCTP_M_VRF);
if (vrf == NULL) {
/* No memory */
if (vrf == NULL) {
/* No memory */
#ifdef INVARIANTS
panic("No memory for VRF:%d", vrf_id);
#endif
@ -241,7 +243,7 @@ sctp_allocate_vrf(int vrf_id)
vrf->vrf_addr_hash = SCTP_HASH_INIT(SCTP_VRF_ADDR_HASH_SIZE,
&vrf->vrf_addr_hashmark);
if (vrf->vrf_addr_hash == NULL) {
/* No memory */
/* No memory */
#ifdef INVARIANTS
panic("No memory for VRF:%d", vrf_id);
#endif
@ -654,7 +656,7 @@ sctp_add_addr_to_vrf(uint32_t vrf_id, void *ifn, uint32_t ifn_index,
sctp_remove_ifa_from_ifn(sctp_ifap);
/* move the address over to the new ifn */
sctp_add_ifa_to_ifn(sctp_ifnp, sctp_ifap);
goto exit_stage_left;
goto exit_stage_left;
} else {
/* repair ifnp which was NULL ? */
sctp_ifap->localifa_flags = SCTP_ADDR_VALID;
@ -711,7 +713,7 @@ sctp_add_addr_to_vrf(uint32_t vrf_id, void *ifn, uint32_t ifn_index,
{
struct sockaddr_in *sin;
sin = (struct sockaddr_in *)&sctp_ifap->address.sin;
sin = &sctp_ifap->address.sin;
if (SCTP_IFN_IS_IFT_LOOP(sctp_ifap->ifn_p) ||
(IN4_ISLOOPBACK_ADDRESS(&sin->sin_addr))) {
sctp_ifap->src_is_loop = 1;
@ -731,7 +733,7 @@ sctp_add_addr_to_vrf(uint32_t vrf_id, void *ifn, uint32_t ifn_index,
/* ok to use deprecated addresses? */
struct sockaddr_in6 *sin6;
sin6 = (struct sockaddr_in6 *)&sctp_ifap->address.sin6;
sin6 = &sctp_ifap->address.sin6;
if (SCTP_IFN_IS_IFT_LOOP(sctp_ifap->ifn_p) ||
(IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr))) {
sctp_ifap->src_is_loop = 1;
@ -865,7 +867,13 @@ sctp_del_addr_from_vrf(uint32_t vrf_id, struct sockaddr *addr,
}
SCTPDBG(SCTP_DEBUG_PCB4, "Deleting ifa %p\n", (void *)sctp_ifap);
sctp_ifap->localifa_flags &= SCTP_ADDR_VALID;
sctp_ifap->localifa_flags |= SCTP_BEING_DELETED;
/*
* We don't set the flag. This means that the structure will
* hang around in EP's that have bound specific to it until
* they close. This gives us TCP like behavior if someone
* removes an address (or for that matter adds it right back).
*/
/* sctp_ifap->localifa_flags |= SCTP_BEING_DELETED; */
vrf->total_ifa_count--;
LIST_REMOVE(sctp_ifap, next_bucket);
sctp_remove_ifa_from_ifn(sctp_ifap);
@ -986,6 +994,12 @@ sctp_does_stcb_own_this_addr(struct sctp_tcb *stcb, struct sockaddr *to)
IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) {
continue;
}
#if defined(__FreeBSD__)
if (prison_check_ip4(stcb->sctp_ep->ip_inp.inp.inp_cred,
&sin->sin_addr) != 0) {
continue;
}
#endif
if (sin->sin_addr.s_addr == rsin->sin_addr.s_addr) {
SCTP_IPI_ADDR_RUNLOCK();
return (1);
@ -1002,6 +1016,12 @@ sctp_does_stcb_own_this_addr(struct sctp_tcb *stcb, struct sockaddr *to)
#endif
sin6 = &sctp_ifa->address.sin6;
rsin6 = (struct sockaddr_in6 *)to;
#if defined(__FreeBSD__)
if (prison_check_ip6(stcb->sctp_ep->ip_inp.inp.inp_cred,
&sin6->sin6_addr) != 0) {
continue;
}
#endif
if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
if (local_scope == 0)
continue;
@ -1077,7 +1097,7 @@ sctp_does_stcb_own_this_addr(struct sctp_tcb *stcb, struct sockaddr *to)
{
struct sockaddr_in *sin, *rsin;
sin = (struct sockaddr_in *)&laddr->ifa->address.sin;
sin = &laddr->ifa->address.sin;
rsin = (struct sockaddr_in *)to;
if (sin->sin_addr.s_addr == rsin->sin_addr.s_addr) {
SCTP_IPI_ADDR_RUNLOCK();
@ -1091,7 +1111,7 @@ sctp_does_stcb_own_this_addr(struct sctp_tcb *stcb, struct sockaddr *to)
{
struct sockaddr_in6 *sin6, *rsin6;
sin6 = (struct sockaddr_in6 *)&laddr->ifa->address.sin6;
sin6 = &laddr->ifa->address.sin6;
rsin6 = (struct sockaddr_in6 *)to;
if (SCTP6_ARE_ADDR_EQUAL(sin6, rsin6)) {
SCTP_IPI_ADDR_RUNLOCK();
@ -1106,7 +1126,7 @@ sctp_does_stcb_own_this_addr(struct sctp_tcb *stcb, struct sockaddr *to)
{
struct sockaddr_conn *sconn, *rsconn;
sconn = (struct sockaddr_conn *)&laddr->ifa->address.sconn;
sconn = &laddr->ifa->address.sconn;
rsconn = (struct sockaddr_conn *)to;
if (sconn->sconn_addr == rsconn->sconn_addr) {
SCTP_IPI_ADDR_RUNLOCK();
@ -1201,6 +1221,41 @@ sctp_tcb_special_locate(struct sctp_inpcb **inp_p, struct sockaddr *from,
SCTP_INP_RUNLOCK(inp);
continue;
}
#if defined(__FreeBSD__)
switch (to->sa_family) {
#ifdef INET
case AF_INET:
{
struct sockaddr_in *sin;
sin = (struct sockaddr_in *)to;
if (prison_check_ip4(inp->ip_inp.inp.inp_cred,
&sin->sin_addr) != 0) {
SCTP_INP_RUNLOCK(inp);
continue;
}
break;
}
#endif
#ifdef INET6
case AF_INET6:
{
struct sockaddr_in6 *sin6;
sin6 = (struct sockaddr_in6 *)to;
if (prison_check_ip6(inp->ip_inp.inp.inp_cred,
&sin6->sin6_addr) != 0) {
SCTP_INP_RUNLOCK(inp);
continue;
}
break;
}
#endif
default:
SCTP_INP_RUNLOCK(inp);
continue;
}
#endif
#ifdef SCTP_MVRF
fnd = 0;
for (i = 0; i < inp->num_vrfs; i++) {
@ -1634,10 +1689,7 @@ sctp_findassociation_ep_addr(struct sctp_inpcb **inp_p, struct sockaddr *remote,
goto null_return;
}
head = &inp->sctp_tcbhash[SCTP_PCBHASH_ALLADDR(rport,
inp->sctp_hashmark)];
if (head == NULL) {
goto null_return;
}
inp->sctp_hashmark)];
LIST_FOREACH(stcb, head, sctp_tcbhash) {
if (stcb->rport != rport) {
/* remote port does not match */
@ -1901,23 +1953,43 @@ sctp_endpoint_probe(struct sockaddr *nam, struct sctppcbhead *head,
if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) &&
(inp->sctp_lport == lport)) {
/* got it */
switch (nam->sa_family) {
#ifdef INET
if ((nam->sa_family == AF_INET) &&
(inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
SCTP_IPV6_V6ONLY(inp)) {
/* IPv4 on a IPv6 socket with ONLY IPv6 set */
SCTP_INP_RUNLOCK(inp);
continue;
}
case AF_INET:
if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
SCTP_IPV6_V6ONLY(inp)) {
/* IPv4 on a IPv6 socket with ONLY IPv6 set */
SCTP_INP_RUNLOCK(inp);
continue;
}
#if defined(__FreeBSD__)
if (prison_check_ip4(inp->ip_inp.inp.inp_cred,
&sin->sin_addr) != 0) {
SCTP_INP_RUNLOCK(inp);
continue;
}
#endif
break;
#endif
#ifdef INET6
/* A V6 address and the endpoint is NOT bound V6 */
if (nam->sa_family == AF_INET6 &&
(inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) {
SCTP_INP_RUNLOCK(inp);
continue;
}
case AF_INET6:
/* A V6 address and the endpoint is NOT bound V6 */
if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) {
SCTP_INP_RUNLOCK(inp);
continue;
}
#if defined(__FreeBSD__)
if (prison_check_ip6(inp->ip_inp.inp.inp_cred,
&sin6->sin6_addr) != 0) {
SCTP_INP_RUNLOCK(inp);
continue;
}
#endif
break;
#endif
default:
break;
}
/* does a VRF id match? */
fnd = 0;
#ifdef SCTP_MVRF
@ -2432,12 +2504,7 @@ sctp_findassoc_by_vtag(struct sockaddr *from, struct sockaddr *to, uint32_t vtag
SCTP_INP_INFO_RLOCK();
head = &SCTP_BASE_INFO(sctp_asochash)[SCTP_PCBHASH_ASOC(vtag,
SCTP_BASE_INFO(hashasocmark))];
if (head == NULL) {
/* invalid vtag */
SCTP_INP_INFO_RUNLOCK();
return (NULL);
}
SCTP_BASE_INFO(hashasocmark))];
LIST_FOREACH(stcb, head, sctp_asocs) {
SCTP_INP_RLOCK(stcb->sctp_ep);
if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) {
@ -2605,7 +2672,7 @@ sctp_findassociation_ep_asconf(struct mbuf *m, int offset,
struct sctp_inpcb **inp_p, struct sctp_nets **netp, uint32_t vrf_id)
{
struct sctp_tcb *stcb;
struct sockaddr_storage remote_store;
union sctp_sockstore remote_store;
struct sctp_paramhdr parm_buf, *phdr;
int ptype;
int zero_address = 0;
@ -2644,7 +2711,7 @@ sctp_findassociation_ep_asconf(struct mbuf *m, int offset,
__FUNCTION__);
return (NULL);
}
sin6 = (struct sockaddr_in6 *)&remote_store;
sin6 = &remote_store.sin6;
sin6->sin6_family = AF_INET6;
#ifdef HAVE_SIN6_LEN
sin6->sin6_len = sizeof(*sin6);
@ -2673,7 +2740,7 @@ sctp_findassociation_ep_asconf(struct mbuf *m, int offset,
__FUNCTION__);
return (NULL);
}
sin = (struct sockaddr_in *)&remote_store;
sin = &remote_store.sin;
sin->sin_family = AF_INET;
#ifdef HAVE_SIN_LEN
sin->sin_len = sizeof(*sin);
@ -2698,7 +2765,7 @@ sctp_findassociation_ep_asconf(struct mbuf *m, int offset,
}
} else {
stcb = sctp_findassociation_ep_addr(inp_p,
(struct sockaddr *)&remote_store, netp,
&remote_store.sa, netp,
dst, NULL);
}
return (stcb);
@ -2747,6 +2814,9 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id)
/* setup socket pointers */
inp->sctp_socket = so;
inp->ip_inp.inp.inp_socket = so;
#if defined(__FreeBSD__)
inp->ip_inp.inp.inp_cred = crhold(so->so_cred);
#endif
#ifdef INET6
#if !defined(__Userspace__) && !defined(__Windows__)
if (INP_SOCKAF(so) == AF_INET6) {
@ -2763,7 +2833,13 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id)
inp->partial_delivery_point = SCTP_SB_LIMIT_RCV(so) >> SCTP_PARTIAL_DELIVERY_SHIFT;
inp->sctp_frag_point = SCTP_DEFAULT_MAXSEGMENT;
inp->sctp_cmt_on_off = SCTP_BASE_SYSCTL(sctp_cmt_on_off);
inp->sctp_ecn_enable = SCTP_BASE_SYSCTL(sctp_ecn_enable);
inp->ecn_supported = (uint8_t)SCTP_BASE_SYSCTL(sctp_ecn_enable);
inp->prsctp_supported = (uint8_t)SCTP_BASE_SYSCTL(sctp_pr_enable);
inp->auth_supported = (uint8_t)SCTP_BASE_SYSCTL(sctp_auth_enable);
inp->asconf_supported = (uint8_t)SCTP_BASE_SYSCTL(sctp_asconf_enable);
inp->reconfig_supported = (uint8_t)SCTP_BASE_SYSCTL(sctp_reconfig_enable);
inp->nrsack_supported = (uint8_t)SCTP_BASE_SYSCTL(sctp_nrsack_enable);
inp->pktdrop_supported = (uint8_t)SCTP_BASE_SYSCTL(sctp_pktdrop_enable);
#if defined(__Userspace__)
inp->ulp_info = NULL;
inp->recv_callback = NULL;
@ -2773,6 +2849,9 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id)
/* init the small hash table we use to track asocid <-> tcb */
inp->sctp_asocidhash = SCTP_HASH_INIT(SCTP_STACK_VTAG_HASH_SIZE, &inp->hashasocidmark);
if (inp->sctp_asocidhash == NULL) {
#if defined(__FreeBSD__)
crfree(inp->ip_inp.inp.inp_cred);
#endif
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_ep), inp);
SCTP_INP_INFO_WUNLOCK();
return (ENOBUFS);
@ -2792,6 +2871,9 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id)
error = 0;
#endif
if (error != 0) {
#if defined(__FreeBSD__)
crfree(inp->ip_inp.inp.inp_cred);
#endif
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_ep), inp);
SCTP_INP_INFO_WUNLOCK();
return error;
@ -2837,6 +2919,9 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id)
*/
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EOPNOTSUPP);
so->so_pcb = NULL;
#if defined(__FreeBSD__)
crfree(inp->ip_inp.inp.inp_cred);
#endif
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_ep), inp);
return (EOPNOTSUPP);
}
@ -2856,6 +2941,9 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id)
SCTP_PRINTF("Out of SCTP-INPCB->hashinit - no resources\n");
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, ENOBUFS);
so->so_pcb = NULL;
#if defined(__FreeBSD__)
crfree(inp->ip_inp.inp.inp_cred);
#endif
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_ep), inp);
return (ENOBUFS);
}
@ -2867,6 +2955,9 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id)
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, ENOBUFS);
so->so_pcb = NULL;
SCTP_HASH_FREE(inp->sctp_tcbhash, inp->sctp_hashmark);
#if defined(__FreeBSD__)
crfree(inp->ip_inp.inp.inp_cred);
#endif
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_ep), inp);
return (ENOBUFS);
}
@ -2885,6 +2976,9 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id)
#endif
SCTP_HASH_FREE(inp->sctp_tcbhash, inp->sctp_hashmark);
so->so_pcb = NULL;
#if defined(__FreeBSD__)
crfree(inp->ip_inp.inp.inp_cred);
#endif
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_ep), inp);
SCTP_UNLOCK_EXC(SCTP_BASE_INFO(sctbinfo).ipi_lock);
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, ENOMEM);
@ -2994,12 +3088,15 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id)
*/
m->local_hmacs = sctp_default_supported_hmaclist();
m->local_auth_chunks = sctp_alloc_chunklist();
if (inp->asconf_supported) {
sctp_auth_add_chunk(SCTP_ASCONF, m->local_auth_chunks);
sctp_auth_add_chunk(SCTP_ASCONF_ACK, m->local_auth_chunks);
}
m->default_dscp = 0;
#ifdef INET6
m->default_flowlabel = 0;
#endif
m->port = 0; /* encapsulation disabled by default */
sctp_auth_set_default_chunks(m->local_auth_chunks);
LIST_INIT(&m->shared_keys);
/* add default NULL key as key id 0 */
null_key = sctp_alloc_sharedkey();
@ -3146,13 +3243,13 @@ extern void in6_sin6_2_sin(struct sockaddr_in *, struct sockaddr_in6 *sin6);
int
#if defined(__FreeBSD__) && __FreeBSD_version >= 500000
sctp_inpcb_bind(struct socket *so, struct sockaddr *addr,
struct sctp_ifa *sctp_ifap, struct thread *p)
struct sctp_ifa *sctp_ifap, struct thread *p)
#elif defined(__Windows__)
sctp_inpcb_bind(struct socket *so, struct sockaddr *addr,
struct sctp_ifa *sctp_ifap, PKTHREAD p)
struct sctp_ifa *sctp_ifap, PKTHREAD p)
#else
sctp_inpcb_bind(struct socket *so, struct sockaddr *addr,
struct sctp_ifa *sctp_ifap, struct proc *p)
struct sctp_ifa *sctp_ifap, struct proc *p)
#endif
{
/* bind a ep to a socket address */
@ -3217,14 +3314,14 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr,
sin = (struct sockaddr_in *)addr;
lport = sin->sin_port;
#if defined(__FreeBSD__) && __FreeBSD_version >= 800000
/*
* For LOOPBACK the prison_local_ip4() call will transmute the ip address
* to the proper value.
*/
if (p && (error = prison_local_ip4(p->td_ucred, &sin->sin_addr)) != 0) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, error);
return (error);
}
/*
* For LOOPBACK the prison_local_ip4() call will transmute the ip address
* to the proper value.
*/
if (p && (error = prison_local_ip4(p->td_ucred, &sin->sin_addr)) != 0) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, error);
return (error);
}
#endif
if (sin->sin_addr.s_addr != INADDR_ANY) {
bindall = 0;
@ -3248,15 +3345,15 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr,
#endif
lport = sin6->sin6_port;
#if defined(__FreeBSD__) && __FreeBSD_version >= 800000
/*
* For LOOPBACK the prison_local_ip6() call will transmute the ipv6 address
* to the proper value.
*/
if (p && (error = prison_local_ip6(p->td_ucred, &sin6->sin6_addr,
(SCTP_IPV6_V6ONLY(inp) != 0))) != 0) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, error);
return (error);
}
/*
* For LOOPBACK the prison_local_ip6() call will transmute the ipv6 address
* to the proper value.
*/
if (p && (error = prison_local_ip6(p->td_ucred, &sin6->sin6_addr,
(SCTP_IPV6_V6ONLY(inp) != 0))) != 0) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, error);
return (error);
}
#endif
if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
bindall = 0;
@ -3324,7 +3421,7 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr,
SCTP_INP_INFO_WLOCK();
SCTP_INP_WLOCK(inp);
/* Setup a vrf_id to be the default for the non-bind-all case. */
vrf_id = inp->def_vrf_id;
vrf_id = inp->def_vrf_id;
/* increase our count due to the unlock we do */
SCTP_INP_INCR_REF(inp);
@ -3348,7 +3445,7 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr,
#elif defined(__APPLE__)
suser(p->p_ucred, &p->p_acflag)
#elif defined(__Userspace__) /* must be true to use raw socket */
1
1
#else
suser(p, 0)
#endif
@ -3368,15 +3465,6 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr,
}
#endif
}
#if !defined(__Panda__) && !defined(__Userspace__)
if (p == NULL) {
SCTP_INP_DECR_REF(inp);
SCTP_INP_WUNLOCK(inp);
SCTP_INP_INFO_WUNLOCK();
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, error);
return (error);
}
#endif
#endif /* __Windows__ */
SCTP_INP_WUNLOCK(inp);
if (bindall) {
@ -3457,7 +3545,7 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr,
}
} else {
uint16_t first, last, candidate;
uint16_t count;
uint16_t count;
int done;
#if defined(__Windows__)
@ -3465,12 +3553,12 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr,
last = 0xffff;
#else
#if defined(__Userspace__)
/* TODO ensure uid is 0, etc... */
/* TODO ensure uid is 0, etc... */
#elif defined(__FreeBSD__) || defined(__APPLE__)
if (ip_inp->inp_flags & INP_HIGHPORT) {
first = MODULE_GLOBAL(ipport_hifirstauto);
last = MODULE_GLOBAL(ipport_hilastauto);
} else if (ip_inp->inp_flags & INP_LOWPORT) {
if (ip_inp->inp_flags & INP_HIGHPORT) {
first = MODULE_GLOBAL(ipport_hifirstauto);
last = MODULE_GLOBAL(ipport_hilastauto);
} else if (ip_inp->inp_flags & INP_LOWPORT) {
if (p && (error =
#ifdef __FreeBSD__
#if __FreeBSD_version > 602000
@ -3492,14 +3580,14 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr,
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, error);
return (error);
}
first = MODULE_GLOBAL(ipport_lowfirstauto);
last = MODULE_GLOBAL(ipport_lowlastauto);
} else {
first = MODULE_GLOBAL(ipport_lowfirstauto);
last = MODULE_GLOBAL(ipport_lowlastauto);
} else {
#endif
first = MODULE_GLOBAL(ipport_firstauto);
last = MODULE_GLOBAL(ipport_lastauto);
first = MODULE_GLOBAL(ipport_firstauto);
last = MODULE_GLOBAL(ipport_lastauto);
#if defined(__FreeBSD__) || defined(__APPLE__)
}
}
#endif
#endif /* __Windows__ */
if (first > last) {
@ -3605,42 +3693,27 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr,
* too (before adding).
*/
struct sctp_ifa *ifa;
struct sockaddr_storage store_sa;
union sctp_sockstore store;
memset(&store_sa, 0, sizeof(store_sa));
memset(&store, 0, sizeof(store));
switch (addr->sa_family) {
#ifdef INET
case AF_INET:
{
struct sockaddr_in *sin;
sin = (struct sockaddr_in *)&store_sa;
memcpy(sin, addr, sizeof(struct sockaddr_in));
sin->sin_port = 0;
memcpy(&store.sin, addr, sizeof(struct sockaddr_in));
store.sin.sin_port = 0;
break;
}
#endif
#ifdef INET6
case AF_INET6:
{
struct sockaddr_in6 *sin6;
sin6 = (struct sockaddr_in6 *)&store_sa;
memcpy(sin6, addr, sizeof(struct sockaddr_in6));
sin6->sin6_port = 0;
memcpy(&store.sin6, addr, sizeof(struct sockaddr_in6));
store.sin6.sin6_port = 0;
break;
}
#endif
#if defined(__Userspace__)
case AF_CONN:
{
struct sockaddr_conn *sconn;
sconn = (struct sockaddr_conn *)&store_sa;
memcpy(sconn, addr, sizeof(struct sockaddr_conn));
sconn->sconn_port = 0;
memcpy(&store.sconn, addr, sizeof(struct sockaddr_conn));
store.sconn.sconn_port = 0;
break;
}
#endif
default:
break;
@ -3657,7 +3730,7 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr,
* O/S's will pass things in via the
* sctp_ifap argument (Panda).
*/
ifa = sctp_find_ifa_by_addr((struct sockaddr *)&store_sa,
ifa = sctp_find_ifa_by_addr(&store.sa,
vrf_id, SCTP_ADDR_NOT_LOCKED);
}
if (ifa == NULL) {
@ -3700,7 +3773,7 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr,
/* Put it into tcp 1-2-1 hash */
head = &SCTP_BASE_INFO(sctp_tcpephash)[SCTP_PCBHASH_ALLADDR(lport, SCTP_BASE_INFO(hashtcpmark))];
inp->sctp_flags |= SCTP_PCB_FLAGS_IN_TCPPOOL;
} else {
} else {
head = &SCTP_BASE_INFO(sctp_ephash)[SCTP_PCBHASH_ALLADDR(lport, SCTP_BASE_INFO(hashmark))];
}
/* put it in the bucket */
@ -3906,17 +3979,7 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
/* Left with Data unread */
struct mbuf *op_err;
op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr),
0, M_NOWAIT, 1, MT_DATA);
if (op_err) {
/* Fill in the user initiated abort */
struct sctp_paramhdr *ph;
SCTP_BUF_LEN(op_err) = sizeof(struct sctp_paramhdr);
ph = mtod(op_err, struct sctp_paramhdr *);
ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT);
ph->param_length = htons(SCTP_BUF_LEN(op_err));
}
op_err = sctp_generate_cause(SCTP_CAUSE_USER_INITIATED_ABT, "");
asoc->sctp_ep->last_abort_code = SCTP_FROM_SCTP_PCB+SCTP_LOC_3;
sctp_send_abort_tcb(asoc, op_err, SCTP_SO_LOCKED);
SCTP_STAT_INCR_COUNTER32(sctps_aborted);
@ -3986,17 +4049,7 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
(asoc->asoc.state & SCTP_STATE_PARTIAL_MSG_LEFT)) {
struct mbuf *op_err;
abort_anyway:
op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr),
0, M_NOWAIT, 1, MT_DATA);
if (op_err) {
/* Fill in the user initiated abort */
struct sctp_paramhdr *ph;
SCTP_BUF_LEN(op_err) = sizeof(struct sctp_paramhdr);
ph = mtod(op_err, struct sctp_paramhdr *);
ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT);
ph->param_length = htons(SCTP_BUF_LEN(op_err));
}
op_err = sctp_generate_cause(SCTP_CAUSE_USER_INITIATED_ABT, "");
asoc->sctp_ep->last_abort_code = SCTP_FROM_SCTP_PCB+SCTP_LOC_5;
sctp_send_abort_tcb(asoc, op_err, SCTP_SO_LOCKED);
SCTP_STAT_INCR_COUNTER32(sctps_aborted);
@ -4063,17 +4116,7 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
((asoc->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) == 0)) {
struct mbuf *op_err;
op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr),
0, M_NOWAIT, 1, MT_DATA);
if (op_err) {
/* Fill in the user initiated abort */
struct sctp_paramhdr *ph;
SCTP_BUF_LEN(op_err) = sizeof(struct sctp_paramhdr);
ph = mtod(op_err, struct sctp_paramhdr *);
ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT);
ph->param_length = htons(SCTP_BUF_LEN(op_err));
}
op_err = sctp_generate_cause(SCTP_CAUSE_USER_INITIATED_ABT, "");
asoc->sctp_ep->last_abort_code = SCTP_FROM_SCTP_PCB+SCTP_LOC_7;
sctp_send_abort_tcb(asoc, op_err, SCTP_SO_LOCKED);
SCTP_STAT_INCR_COUNTER32(sctps_aborted);
@ -4298,6 +4341,7 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
}
/* Now we must put the ep memory back into the zone pool */
#if defined(__FreeBSD__)
crfree(inp->ip_inp.inp.inp_cred);
INP_LOCK_DESTROY(&inp->ip_inp.inp);
#endif
SCTP_INP_LOCK_DESTROY(inp);
@ -4557,7 +4601,7 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr,
* this means its an initial value
*/
net->rto_needed = 1;
net->RTO = 0;
net->RTO = 0;
net->RTO_measured = 0;
stcb->asoc.numnets++;
net->ref_count = 1;
@ -4610,7 +4654,9 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr,
#endif
SCTP_RTALLOC((sctp_route_t *)&net->ro, stcb->asoc.vrf_id);
#if !defined(__Userspace__)
#if defined(__Userspace__)
net->src_addr_selected = 0;
#else
if (SCTP_ROUTE_HAS_VALID_IFN(&net->ro)) {
/* Get source address */
net->ro._s_addr = sctp_source_address_selection(stcb->sctp_ep,
@ -4619,9 +4665,14 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr,
net,
0,
stcb->asoc.vrf_id);
/* Now get the interface MTU */
if (net->ro._s_addr && net->ro._s_addr->ifn_p) {
net->mtu = SCTP_GATHER_MTU_FROM_INTFC(net->ro._s_addr->ifn_p);
if (net->ro._s_addr != NULL) {
net->src_addr_selected = 1;
/* Now get the interface MTU */
if (net->ro._s_addr->ifn_p != NULL) {
net->mtu = SCTP_GATHER_MTU_FROM_INTFC(net->ro._s_addr->ifn_p);
}
} else {
net->src_addr_selected = 0;
}
if (net->mtu > 0) {
uint32_t rmtu;
@ -4636,9 +4687,11 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr,
* the route may be leading out the loopback, or
* a different interface.
*/
net->mtu = rmtu;
net->mtu = rmtu;
}
}
}
} else {
net->src_addr_selected = 0;
}
#endif
if (net->mtu == 0) {
@ -4662,9 +4715,11 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr,
break;
}
}
#if defined(INET) || defined(INET6)
if (net->port) {
net->mtu -= (uint32_t)sizeof(struct udphdr);
}
#endif
if (from == SCTP_ALLOC_ASOC) {
stcb->asoc.smallest_mtu = net->mtu;
}
@ -4696,15 +4751,12 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr,
*/
net->find_pseudo_cumack = 1;
net->find_rtx_pseudo_cumack = 1;
net->src_addr_selected = 0;
#if defined(__FreeBSD__)
/* Choose an initial flowid. */
net->flowid = stcb->asoc.my_vtag ^
ntohs(stcb->rport) ^
ntohs(stcb->sctp_ep->sctp_lport);
#ifdef INVARIANTS
net->flowidset = 1;
#endif
net->flowtype = M_HASHTYPE_OPAQUE;
#endif
if (netp) {
*netp = net;
@ -5131,9 +5183,9 @@ sctp_remove_net(struct sctp_tcb *stcb, struct sctp_nets *net)
(by micchie)
*/
if (sctp_is_mobility_feature_on(stcb->sctp_ep,
SCTP_MOBILITY_BASE) ||
SCTP_MOBILITY_BASE) ||
sctp_is_mobility_feature_on(stcb->sctp_ep,
SCTP_MOBILITY_FASTHANDOFF)) {
SCTP_MOBILITY_FASTHANDOFF)) {
SCTPDBG(SCTP_DEBUG_ASCONF1, "remove_net: primary dst is deleting\n");
if (asoc->deleted_primary != NULL) {
SCTPDBG(SCTP_DEBUG_ASCONF1, "remove_net: deleted primary may be already stored\n");
@ -6546,7 +6598,7 @@ sctp_startup_mcore_threads(void)
}
}
#endif
#if defined(__FreeBSD__) && __FreeBSD_cc_version >= 1100000
#if defined(__FreeBSD__) && __FreeBSD_cc_version >= 1200000
static struct mbuf *
sctp_netisr_hdlr(struct mbuf *m, uintptr_t source)
{
@ -6771,7 +6823,7 @@ sctp_pcb_init()
*/
sctp_init_vrf_list(SCTP_DEFAULT_VRF);
#endif
#if defined(__FreeBSD__) && __FreeBSD_cc_version >= 1100000
#if defined(__FreeBSD__) && __FreeBSD_cc_version >= 1200000
if (ip_register_flow_handler(sctp_netisr_hdlr, IPPROTO_SCTP)) {
SCTP_PRINTF("***SCTP- Error can't register netisr handler***\n");
}
@ -6887,13 +6939,16 @@ sctp_pcb_finish(void)
#endif
#if !defined(__FreeBSD__)
SCTP_IPI_ITERATOR_WQ_DESTROY();
SCTP_ITERATOR_LOCK_DESTROY();
SCTP_ITERATOR_LOCK_DESTROY();
#endif
SCTP_OS_TIMER_STOP(&SCTP_BASE_INFO(addr_wq_timer.timer));
SCTP_WQ_ADDR_LOCK();
LIST_FOREACH_SAFE(wi, &SCTP_BASE_INFO(addr_wq), sctp_nxt_addr, nwi) {
LIST_REMOVE(wi, sctp_nxt_addr);
SCTP_DECR_LADDR_COUNT();
if (wi->action == SCTP_DEL_IP_ADDRESS) {
SCTP_FREE(wi->ifa, SCTP_M_IFA);
}
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_laddr), wi);
}
SCTP_WQ_ADDR_UNLOCK();
@ -7038,7 +7093,14 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
sctp_key_t *new_key;
uint32_t keylen;
int got_random = 0, got_hmacs = 0, got_chklist = 0;
uint8_t ecn_allowed;
uint8_t peer_supports_ecn;
uint8_t peer_supports_prsctp;
uint8_t peer_supports_auth;
uint8_t peer_supports_asconf;
uint8_t peer_supports_asconf_ack;
uint8_t peer_supports_reconfig;
uint8_t peer_supports_nrsack;
uint8_t peer_supports_pktdrop;
#ifdef INET
struct sockaddr_in sin;
#endif
@ -7068,8 +7130,13 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
} else {
sa = src;
}
/* Turn off ECN until we get through all params */
ecn_allowed = 0;
peer_supports_ecn = 0;
peer_supports_prsctp = 0;
peer_supports_auth = 0;
peer_supports_asconf = 0;
peer_supports_reconfig = 0;
peer_supports_nrsack = 0;
peer_supports_pktdrop = 0;
TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
/* mark all addresses that we have currently on the list */
net->dest_state |= SCTP_ADDR_NOT_IN_ASSOC;
@ -7128,12 +7195,6 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
/* the assoc was freed? */
return (-4);
}
/*
* peer must explicitly turn this on. This may have been initialized
* to be "on" in order to allow local addr changes while INIT's are
* in flight.
*/
stcb->asoc.peer_supports_asconf = 0;
/* now we must go through each of the params. */
phdr = sctp_get_next_param(m, offset, &parm_buf, sizeof(parm_buf));
while (phdr) {
@ -7319,7 +7380,7 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
} else
#endif
if (ptype == SCTP_ECN_CAPABLE) {
ecn_allowed = 1;
peer_supports_ecn = 1;
} else if (ptype == SCTP_ULP_ADAPTATION) {
if (stcb->asoc.state != SCTP_STATE_OPEN) {
struct sctp_adaptation_layer_indication ai, *aip;
@ -7340,7 +7401,9 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
struct sctp_asconf_addrv4_param *fii;
#endif
stcb->asoc.peer_supports_asconf = 1;
if (stcb->asoc.asconf_supported == 0) {
return (-100);
}
if (plen > sizeof(lstore)) {
return (-23);
}
@ -7392,7 +7455,7 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
stcb->asoc.peer_supports_nat = 1;
} else if (ptype == SCTP_PRSCTP_SUPPORTED) {
/* Peer supports pr-sctp */
stcb->asoc.peer_supports_prsctp = 1;
peer_supports_prsctp = 1;
} else if (ptype == SCTP_SUPPORTED_CHUNK_EXT) {
/* A supported extension chunk */
struct sctp_supported_chunk_types_param *pr_supported;
@ -7404,34 +7467,30 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
if (phdr == NULL) {
return (-25);
}
stcb->asoc.peer_supports_asconf = 0;
stcb->asoc.peer_supports_prsctp = 0;
stcb->asoc.peer_supports_pktdrop = 0;
stcb->asoc.peer_supports_strreset = 0;
stcb->asoc.peer_supports_nr_sack = 0;
stcb->asoc.peer_supports_auth = 0;
pr_supported = (struct sctp_supported_chunk_types_param *)phdr;
num_ent = plen - sizeof(struct sctp_paramhdr);
for (i = 0; i < num_ent; i++) {
switch (pr_supported->chunk_types[i]) {
case SCTP_ASCONF:
peer_supports_asconf = 1;
break;
case SCTP_ASCONF_ACK:
stcb->asoc.peer_supports_asconf = 1;
peer_supports_asconf_ack = 1;
break;
case SCTP_FORWARD_CUM_TSN:
stcb->asoc.peer_supports_prsctp = 1;
peer_supports_prsctp = 1;
break;
case SCTP_PACKET_DROPPED:
stcb->asoc.peer_supports_pktdrop = 1;
peer_supports_pktdrop = 1;
break;
case SCTP_NR_SELECTIVE_ACK:
stcb->asoc.peer_supports_nr_sack = 1;
peer_supports_nrsack = 1;
break;
case SCTP_STREAM_RESET:
stcb->asoc.peer_supports_strreset = 1;
peer_supports_reconfig = 1;
break;
case SCTP_AUTHENTICATION:
stcb->asoc.peer_supports_auth = 1;
peer_supports_auth = 1;
break;
default:
/* one I have not learned yet */
@ -7460,8 +7519,8 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
}
got_random = 1;
} else if (ptype == SCTP_HMAC_LIST) {
int num_hmacs;
int i;
uint16_t num_hmacs;
uint16_t i;
if (plen > sizeof(hmacs_store))
break;
@ -7568,24 +7627,47 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
}
}
}
if (ecn_allowed == 0) {
stcb->asoc.ecn_allowed = 0;
if ((stcb->asoc.ecn_supported == 1) &&
(peer_supports_ecn == 0)) {
stcb->asoc.ecn_supported = 0;
}
if ((stcb->asoc.prsctp_supported == 1) &&
(peer_supports_prsctp == 0)) {
stcb->asoc.prsctp_supported = 0;
}
if ((stcb->asoc.auth_supported == 1) &&
((peer_supports_auth == 0) ||
(got_random == 0) || (got_hmacs == 0))) {
stcb->asoc.auth_supported = 0;
}
if ((stcb->asoc.asconf_supported == 1) &&
((peer_supports_asconf == 0) || (peer_supports_asconf_ack == 0) ||
(stcb->asoc.auth_supported == 0) ||
(saw_asconf == 0) || (saw_asconf_ack == 0))) {
stcb->asoc.asconf_supported = 0;
}
if ((stcb->asoc.reconfig_supported == 1) &&
(peer_supports_reconfig == 0)) {
stcb->asoc.reconfig_supported = 0;
}
if ((stcb->asoc.nrsack_supported == 1) &&
(peer_supports_nrsack == 0)) {
stcb->asoc.nrsack_supported = 0;
}
if ((stcb->asoc.pktdrop_supported == 1) &&
(peer_supports_pktdrop == 0)){
stcb->asoc.pktdrop_supported = 0;
}
/* validate authentication required parameters */
if (got_random && got_hmacs) {
stcb->asoc.peer_supports_auth = 1;
} else {
stcb->asoc.peer_supports_auth = 0;
}
if (!stcb->asoc.peer_supports_auth && got_chklist) {
if ((peer_supports_auth == 0) && (got_chklist == 1)) {
/* peer does not support auth but sent a chunks list? */
return (-31);
}
if (!SCTP_BASE_SYSCTL(sctp_asconf_auth_nochk) && stcb->asoc.peer_supports_asconf &&
!stcb->asoc.peer_supports_auth) {
if ((peer_supports_asconf == 1) && (peer_supports_auth == 0)) {
/* peer supports asconf but not auth? */
return (-32);
} else if ((stcb->asoc.peer_supports_asconf) && (stcb->asoc.peer_supports_auth) &&
} else if ((peer_supports_asconf == 1) &&
(peer_supports_auth == 1) &&
((saw_asconf == 0) || (saw_asconf_ack == 0))) {
return (-33);
}
@ -7680,10 +7762,6 @@ sctp_is_vtag_good(uint32_t tag, uint16_t lport, uint16_t rport, struct timeval *
SCTP_INP_INFO_RLOCK();
head = &SCTP_BASE_INFO(sctp_asochash)[SCTP_PCBHASH_ASOC(tag,
SCTP_BASE_INFO(hashasocmark))];
if (head == NULL) {
/* invalid vtag */
goto skip_vtag_check;
}
LIST_FOREACH(stcb, head, sctp_asocs) {
/* We choose not to lock anything here. TCB's can't be
* removed since we have the read lock, so they can't
@ -7707,8 +7785,6 @@ sctp_is_vtag_good(uint32_t tag, uint16_t lport, uint16_t rport, struct timeval *
return (0);
}
}
skip_vtag_check:
chain = &SCTP_BASE_INFO(vtag_timewait)[(tag % SCTP_STACK_VTAG_HASH_SIZE)];
/* Now what about timed wait ? */
LIST_FOREACH(twait_block, chain, sctp_nxt_tagblock) {

View File

@ -32,7 +32,7 @@
#ifdef __FreeBSD__
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: head/sys/netinet/sctp_pcb.h 254248 2013-08-12 13:52:15Z tuexen $");
__FBSDID("$FreeBSD: head/sys/netinet/sctp_pcb.h 275427 2014-12-02 20:29:29Z tuexen $");
#endif
#ifndef _NETINET_SCTP_PCB_H_
@ -110,7 +110,7 @@ struct sctp_ifa {
*/
union sctp_sockstore address;
uint32_t refcount; /* number of folks refering to this */
uint32_t flags;
uint32_t flags;
uint32_t localifa_flags;
uint32_t vrf_id; /* vrf_id of this addr (for deleting) */
uint8_t src_is_loop;
@ -480,7 +480,13 @@ struct sctp_inpcb {
uint32_t sctp_context;
uint8_t local_strreset_support;
uint32_t sctp_cmt_on_off;
uint32_t sctp_ecn_enable;
uint8_t ecn_supported;
uint8_t prsctp_supported;
uint8_t auth_supported;
uint8_t asconf_supported;
uint8_t reconfig_supported;
uint8_t nrsack_supported;
uint8_t pktdrop_supported;
struct sctp_nonpad_sndrcvinfo def_send;
/*-
* These three are here for the sosend_dgram

View File

@ -32,7 +32,7 @@
#ifdef __FreeBSD__
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: head/sys/netinet/sctp_peeloff.c 243565 2012-11-26 16:44:03Z tuexen $");
__FBSDID("$FreeBSD: head/sys/netinet/sctp_peeloff.c 269858 2014-08-12 11:30:16Z tuexen $");
#endif
#include <netinet/sctp_os.h>
@ -125,7 +125,13 @@ sctp_do_peeloff(struct socket *head, struct socket *so, sctp_assoc_t assoc_id)
n_inp->sctp_mobility_features = inp->sctp_mobility_features;
n_inp->sctp_frag_point = inp->sctp_frag_point;
n_inp->sctp_cmt_on_off = inp->sctp_cmt_on_off;
n_inp->sctp_ecn_enable = inp->sctp_ecn_enable;
n_inp->ecn_supported = inp->ecn_supported;
n_inp->prsctp_supported = inp->prsctp_supported;
n_inp->auth_supported = inp->auth_supported;
n_inp->asconf_supported = inp->asconf_supported;
n_inp->reconfig_supported = inp->reconfig_supported;
n_inp->nrsack_supported = inp->nrsack_supported;
n_inp->pktdrop_supported = inp->pktdrop_supported;
n_inp->partial_delivery_point = inp->partial_delivery_point;
n_inp->sctp_context = inp->sctp_context;
n_inp->local_strreset_support = inp->local_strreset_support;
@ -234,7 +240,13 @@ sctp_get_peeloff(struct socket *head, sctp_assoc_t assoc_id, int *error)
n_inp->sctp_features = inp->sctp_features;
n_inp->sctp_frag_point = inp->sctp_frag_point;
n_inp->sctp_cmt_on_off = inp->sctp_cmt_on_off;
n_inp->sctp_ecn_enable = inp->sctp_ecn_enable;
n_inp->ecn_supported = inp->ecn_supported;
n_inp->prsctp_supported = inp->prsctp_supported;
n_inp->auth_supported = inp->auth_supported;
n_inp->asconf_supported = inp->asconf_supported;
n_inp->reconfig_supported = inp->reconfig_supported;
n_inp->nrsack_supported = inp->nrsack_supported;
n_inp->pktdrop_supported = inp->pktdrop_supported;
n_inp->partial_delivery_point = inp->partial_delivery_point;
n_inp->sctp_context = inp->sctp_context;
n_inp->local_strreset_support = inp->local_strreset_support;

View File

@ -32,7 +32,7 @@
#ifdef __FreeBSD__
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: head/sys/netinet/sctp_structs.h 255190 2013-09-03 19:31:59Z tuexen $");
__FBSDID("$FreeBSD: head/sys/netinet/sctp_structs.h 275483 2014-12-04 21:17:50Z tuexen $");
#endif
#ifndef _NETINET_SCTP_STRUCTS_H_
@ -428,9 +428,7 @@ struct sctp_nets {
uint8_t rto_needed;
#if defined(__FreeBSD__)
uint32_t flowid;
#ifdef INVARIANTS
uint8_t flowidset;
#endif
uint8_t flowtype;
#endif
};
@ -468,8 +466,8 @@ TAILQ_HEAD(sctpchunk_listhead, sctp_tmit_chunk);
#define CHUNK_FLAGS_FRAGMENT_OK 0x0100
struct chk_id {
uint16_t id;
uint16_t can_take_data;
uint8_t id;
uint8_t can_take_data;
};
@ -636,6 +634,14 @@ struct sctp_stream_out {
struct sctp_streamhead outqueue;
union scheduling_parameters ss_params;
uint32_t chunks_on_queues;
#if defined(SCTP_DETAILED_STR_STATS)
uint32_t abandoned_unsent[SCTP_PR_SCTP_MAX + 1];
uint32_t abandoned_sent[SCTP_PR_SCTP_MAX + 1];
#else
/* Only the aggregation */
uint32_t abandoned_unsent[1];
uint32_t abandoned_sent[1];
#endif
uint16_t stream_no;
uint16_t next_sequence_send; /* next one I expect to send out */
uint8_t last_msg_incomplete;
@ -714,8 +720,8 @@ struct sctp_nonpad_sndrcvinfo {
struct sctp_cc_functions {
void (*sctp_set_initial_cc_param)(struct sctp_tcb *stcb, struct sctp_nets *net);
void (*sctp_cwnd_update_after_sack)(struct sctp_tcb *stcb,
struct sctp_association *asoc,
int accum_moved ,int reneged_all, int will_exit);
struct sctp_association *asoc,
int accum_moved ,int reneged_all, int will_exit);
void (*sctp_cwnd_update_exit_pf)(struct sctp_tcb *stcb, struct sctp_nets *net);
void (*sctp_cwnd_update_after_fr)(struct sctp_tcb *stcb,
struct sctp_association *asoc);
@ -1200,30 +1206,21 @@ struct sctp_association {
* sum is updated as well.
*/
/* Flag to tell if ECN is allowed */
uint8_t ecn_allowed;
/* Flags whether an extension is supported or not */
uint8_t ecn_supported;
uint8_t prsctp_supported;
uint8_t auth_supported;
uint8_t asconf_supported;
uint8_t reconfig_supported;
uint8_t nrsack_supported;
uint8_t pktdrop_supported;
/* Did the peer make the stream config (add out) request */
uint8_t peer_req_out;
/* flag to indicate if peer can do asconf */
uint8_t peer_supports_asconf;
/* EY - flag to indicate if peer can do nr_sack*/
uint8_t peer_supports_nr_sack;
/* pr-sctp support flag */
uint8_t peer_supports_prsctp;
/* peer authentication support flag */
uint8_t peer_supports_auth;
/* stream resets are supported by the peer */
uint8_t peer_supports_strreset;
uint8_t local_strreset_support;
uint8_t peer_supports_nat;
/*
* packet drop's are supported by the peer, we don't really care
* about this but we bookkeep it anyway.
*/
uint8_t peer_supports_pktdrop;
uint8_t peer_supports_nat;
struct sctp_scoping scope;
/* flags to handle send alternate net tracking */
@ -1248,8 +1245,6 @@ struct sctp_association {
uint8_t sctp_cmt_on_off;
uint8_t iam_blocking;
uint8_t cookie_how[8];
/* EY 05/05/08 - NR_SACK variable*/
uint8_t sctp_nr_sack_on_off;
/* JRS 5/21/07 - CMT PF variable */
uint8_t sctp_cmt_pf;
uint8_t use_precise_time;
@ -1272,6 +1267,8 @@ struct sctp_association {
uint32_t timoshutdownack;
struct timeval start_time;
struct timeval discontinuity_time;
uint64_t abandoned_unsent[SCTP_PR_SCTP_MAX + 1];
uint64_t abandoned_sent[SCTP_PR_SCTP_MAX + 1];
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -32,7 +32,7 @@
#ifdef __FreeBSD__
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: head/sys/netinet/sctp_sysctl.h 252779 2013-07-05 10:08:49Z tuexen $");
__FBSDID("$FreeBSD: head/sys/netinet/sctp_sysctl.h 271204 2014-09-06 19:12:14Z tuexen $");
#endif
#ifndef _NETINET_SCTP_SYSCTL_H_
@ -47,6 +47,12 @@ struct sctp_sysctl {
uint32_t sctp_auto_asconf;
uint32_t sctp_multiple_asconfs;
uint32_t sctp_ecn_enable;
uint32_t sctp_pr_enable;
uint32_t sctp_auth_enable;
uint32_t sctp_asconf_enable;
uint32_t sctp_reconfig_enable;
uint32_t sctp_nrsack_enable;
uint32_t sctp_pktdrop_enable;
uint32_t sctp_fr_max_burst_default;
uint32_t sctp_strict_sacks;
#if !(defined(__FreeBSD__) && __FreeBSD_version >= 800000)
@ -83,11 +89,7 @@ struct sctp_sysctl {
uint32_t sctp_nr_outgoing_streams_default;
uint32_t sctp_cmt_on_off;
uint32_t sctp_cmt_use_dac;
/* EY 5/5/08 - nr_sack flag variable */
uint32_t sctp_nr_sack_on_off;
uint32_t sctp_use_cwnd_based_maxburst;
uint32_t sctp_asconf_auth_nochk;
uint32_t sctp_auth_disable;
uint32_t sctp_nat_friendly;
uint32_t sctp_L2_abc_variable;
uint32_t sctp_mbuf_threshold_count;
@ -111,6 +113,7 @@ struct sctp_sysctl {
uint32_t sctp_rttvar_eqret;
uint32_t sctp_steady_step;
uint32_t sctp_use_dccc_ecn;
uint32_t sctp_diag_info_code;
#if defined(SCTP_LOCAL_TRACE_BUF)
#if defined(__Windows__)
struct sctp_log *sctp_log;
@ -157,7 +160,7 @@ struct sctp_sysctl {
#define SCTPCTL_AUTOASCONF_DESC "Enable SCTP Auto-ASCONF"
#define SCTPCTL_AUTOASCONF_MIN 0
#define SCTPCTL_AUTOASCONF_MAX 1
#define SCTPCTL_AUTOASCONF_DEFAULT SCTP_DEFAULT_AUTO_ASCONF
#define SCTPCTL_AUTOASCONF_DEFAULT 1
/* autoasconf: Enable SCTP Auto-ASCONF */
#define SCTPCTL_MULTIPLEASCONFS_DESC "Enable SCTP Muliple-ASCONFs"
@ -171,6 +174,42 @@ struct sctp_sysctl {
#define SCTPCTL_ECN_ENABLE_MAX 1
#define SCTPCTL_ECN_ENABLE_DEFAULT 1
/* pr_enable: Enable PR-SCTP */
#define SCTPCTL_PR_ENABLE_DESC "Enable PR-SCTP"
#define SCTPCTL_PR_ENABLE_MIN 0
#define SCTPCTL_PR_ENABLE_MAX 1
#define SCTPCTL_PR_ENABLE_DEFAULT 1
/* auth_enable: Enable SCTP AUTH function */
#define SCTPCTL_AUTH_ENABLE_DESC "Enable SCTP AUTH function"
#define SCTPCTL_AUTH_ENABLE_MIN 0
#define SCTPCTL_AUTH_ENABLE_MAX 1
#define SCTPCTL_AUTH_ENABLE_DEFAULT 1
/* asconf_enable: Enable SCTP ASCONF */
#define SCTPCTL_ASCONF_ENABLE_DESC "Enable SCTP ASCONF"
#define SCTPCTL_ASCONF_ENABLE_MIN 0
#define SCTPCTL_ASCONF_ENABLE_MAX 1
#define SCTPCTL_ASCONF_ENABLE_DEFAULT 1
/* reconfig_enable: Enable SCTP RE-CONFIG */
#define SCTPCTL_RECONFIG_ENABLE_DESC "Enable SCTP RE-CONFIG"
#define SCTPCTL_RECONFIG_ENABLE_MIN 0
#define SCTPCTL_RECONFIG_ENABLE_MAX 1
#define SCTPCTL_RECONFIG_ENABLE_DEFAULT 1
/* nrsack_enable: Enable NR_SACK */
#define SCTPCTL_NRSACK_ENABLE_DESC "Enable SCTP NR-SACK"
#define SCTPCTL_NRSACK_ENABLE_MIN 0
#define SCTPCTL_NRSACK_ENABLE_MAX 1
#define SCTPCTL_NRSACK_ENABLE_DEFAULT 0
/* pktdrop_enable: Enable SCTP Packet Drop Reports */
#define SCTPCTL_PKTDROP_ENABLE_DESC "Enable SCTP PKTDROP"
#define SCTPCTL_PKTDROP_ENABLE_MIN 0
#define SCTPCTL_PKTDROP_ENABLE_MAX 1
#define SCTPCTL_PKTDROP_ENABLE_DEFAULT 0
/* strict_sacks: Enable SCTP Strict SACK checking */
#define SCTPCTL_STRICT_SACKS_DESC "Enable SCTP Strict SACK checking"
#define SCTPCTL_STRICT_SACKS_MIN 0
@ -358,12 +397,6 @@ struct sctp_sysctl {
#define SCTPCTL_CMT_ON_OFF_MAX SCTP_CMT_MAX
#define SCTPCTL_CMT_ON_OFF_DEFAULT SCTP_CMT_OFF
/* EY - nr_sack_on_off: NR_SACK on/off flag */
#define SCTPCTL_NR_SACK_ON_OFF_DESC "NR_SACK on/off flag"
#define SCTPCTL_NR_SACK_ON_OFF_MIN 0
#define SCTPCTL_NR_SACK_ON_OFF_MAX 1
#define SCTPCTL_NR_SACK_ON_OFF_DEFAULT 0
/* cmt_use_dac: CMT DAC on/off flag */
#define SCTPCTL_CMT_USE_DAC_DESC "CMT DAC on/off flag"
#define SCTPCTL_CMT_USE_DAC_MIN 0
@ -376,18 +409,6 @@ struct sctp_sysctl {
#define SCTPCTL_CWND_MAXBURST_MAX 1
#define SCTPCTL_CWND_MAXBURST_DEFAULT 1
/* asconf_auth_nochk: Disable SCTP ASCONF AUTH requirement */
#define SCTPCTL_ASCONF_AUTH_NOCHK_DESC "Disable SCTP ASCONF AUTH requirement"
#define SCTPCTL_ASCONF_AUTH_NOCHK_MIN 0
#define SCTPCTL_ASCONF_AUTH_NOCHK_MAX 1
#define SCTPCTL_ASCONF_AUTH_NOCHK_DEFAULT 0
/* auth_disable: Disable SCTP AUTH function */
#define SCTPCTL_AUTH_DISABLE_DESC "Disable SCTP AUTH function"
#define SCTPCTL_AUTH_DISABLE_MIN 0
#define SCTPCTL_AUTH_DISABLE_MAX 1
#define SCTPCTL_AUTH_DISABLE_DEFAULT 0
/* nat_friendly: SCTP NAT friendly operation */
#define SCTPCTL_NAT_FRIENDLY_DESC "SCTP NAT friendly operation"
#define SCTPCTL_NAT_FRIENDLY_MIN 0
@ -470,19 +491,23 @@ struct sctp_sysctl {
#define SCTPCTL_MOBILITY_BASE_DESC "Enable SCTP base mobility"
#define SCTPCTL_MOBILITY_BASE_MIN 0
#define SCTPCTL_MOBILITY_BASE_MAX 1
#define SCTPCTL_MOBILITY_BASE_DEFAULT SCTP_DEFAULT_MOBILITY_BASE
#define SCTPCTL_MOBILITY_BASE_DEFAULT 0
/* mobility_fasthandoff: Enable SCTP fast handoff support */
#define SCTPCTL_MOBILITY_FASTHANDOFF_DESC "Enable SCTP fast handoff"
#define SCTPCTL_MOBILITY_FASTHANDOFF_MIN 0
#define SCTPCTL_MOBILITY_FASTHANDOFF_MAX 1
#define SCTPCTL_MOBILITY_FASTHANDOFF_DEFAULT SCTP_DEFAULT_MOBILITY_FASTHANDOFF
#define SCTPCTL_MOBILITY_FASTHANDOFF_DEFAULT 0
/* Enable SCTP/UDP tunneling port */
#define SCTPCTL_UDP_TUNNELING_PORT_DESC "Set the SCTP/UDP tunneling port"
#define SCTPCTL_UDP_TUNNELING_PORT_MIN 0
#define SCTPCTL_UDP_TUNNELING_PORT_MAX 65535
#if defined(__FreeBSD__)
#define SCTPCTL_UDP_TUNNELING_PORT_DEFAULT 0
#else
#define SCTPCTL_UDP_TUNNELING_PORT_DEFAULT SCTP_OVER_UDP_TUNNELING_PORT
#endif
/* Enable sending of the SACK-IMMEDIATELY bit */
#define SCTPCTL_SACK_IMMEDIATELY_ENABLE_DESC "Enable sending of the SACK-IMMEDIATELY-bit."
@ -546,6 +571,11 @@ struct sctp_sysctl {
#define SCTPCTL_BLACKHOLE_MAX 2
#define SCTPCTL_BLACKHOLE_DEFAULT SCTPCTL_BLACKHOLE_MIN
#define SCTPCTL_DIAG_INFO_CODE_DESC "Diagnostic information error cause code"
#define SCTPCTL_DIAG_INFO_CODE_MIN 0
#define SCTPCTL_DIAG_INFO_CODE_MAX 65535
#define SCTPCTL_DIAG_INFO_CODE_DEFAULT 0
#if defined(SCTP_DEBUG)
/* debug: Configure debug output */
#define SCTPCTL_DEBUG_DESC "Configure debug output"
@ -574,12 +604,14 @@ struct sctp_sysctl {
#endif
#if defined(__APPLE__)
#define SCTPCTL_ADDR_WATCHDOG_LIMIT_MIN 0
#define SCTPCTL_ADDR_WATCHDOG_LIMIT_MAX 0xFFFFFFFF
#define SCTPCTL_ADDR_WATCHDOG_LIMIT_DESC "Address watchdog limit"
#define SCTPCTL_ADDR_WATCHDOG_LIMIT_MIN 0
#define SCTPCTL_ADDR_WATCHDOG_LIMIT_MAX 0xFFFFFFFF
#define SCTPCTL_ADDR_WATCHDOG_LIMIT_DEFAULT SCTPCTL_ADDR_WATCHDOG_LIMIT_MIN
#define SCTPCTL_VTAG_WATCHDOG_LIMIT_MIN 0
#define SCTPCTL_VTAG_WATCHDOG_LIMIT_MAX 0xFFFFFFFF
#define SCTPCTL_VTAG_WATCHDOG_LIMIT_DESC "VTag watchdog limit"
#define SCTPCTL_VTAG_WATCHDOG_LIMIT_MIN 0
#define SCTPCTL_VTAG_WATCHDOG_LIMIT_MAX 0xFFFFFFFF
#define SCTPCTL_VTAG_WATCHDOG_LIMIT_DEFAULT SCTPCTL_VTAG_WATCHDOG_LIMIT_MIN
#endif

View File

@ -32,7 +32,7 @@
#ifdef __FreeBSD__
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: head/sys/netinet/sctp_timer.c 257359 2013-10-29 20:04:50Z tuexen $");
__FBSDID("$FreeBSD: head/sys/netinet/sctp_timer.c 277380 2015-01-19 11:52:08Z tuexen $");
#endif
#define _IP_VHL
@ -54,9 +54,11 @@ __FBSDID("$FreeBSD: head/sys/netinet/sctp_timer.c 257359 2013-10-29 20:04:50Z tu
#include <netinet/sctp_input.h>
#include <netinet/sctp.h>
#include <netinet/sctp_uio.h>
#if defined(INET) || defined(INET6)
#if !defined(__Userspace_os_Windows)
#include <netinet/udp.h>
#endif
#endif
#if defined(__APPLE__)
#define APPLE_FILE_NO 6
@ -157,24 +159,12 @@ sctp_threshold_management(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
*/
if (stcb->asoc.overall_error_count > threshold) {
/* Abort notification sends a ULP notify */
struct mbuf *oper;
struct mbuf *op_err;
oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + sizeof(uint32_t)),
0, M_NOWAIT, 1, MT_DATA);
if (oper) {
struct sctp_paramhdr *ph;
uint32_t *ippp;
SCTP_BUF_LEN(oper) = sizeof(struct sctp_paramhdr) +
sizeof(uint32_t);
ph = mtod(oper, struct sctp_paramhdr *);
ph->param_type = htons(SCTP_CAUSE_PROTOCOL_VIOLATION);
ph->param_length = htons(SCTP_BUF_LEN(oper));
ippp = (uint32_t *) (ph + 1);
*ippp = htonl(SCTP_FROM_SCTP_TIMER+SCTP_LOC_1);
}
op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION,
"Association error couter exceeded");
inp->last_abort_code = SCTP_FROM_SCTP_TIMER+SCTP_LOC_1;
sctp_abort_an_association(inp, stcb, oper, SCTP_SO_NOT_LOCKED);
sctp_abort_an_association(inp, stcb, op_err, SCTP_SO_NOT_LOCKED);
return (1);
}
return (0);
@ -228,7 +218,7 @@ sctp_find_alternate_net(struct sctp_tcb *stcb,
* t3 handler.
*/
if (mnet == net) {
if (min_errors == -1) {
if (min_errors == -1) {
min_errors = mnet->error_count + 1;
min_errors_net = mnet;
} else if (mnet->error_count + 1 < min_errors) {
@ -241,7 +231,7 @@ sctp_find_alternate_net(struct sctp_tcb *stcb,
}
continue;
} else {
if (min_errors == -1) {
if (min_errors == -1) {
min_errors = mnet->error_count;
min_errors_net = mnet;
} else if (mnet->error_count < min_errors) {
@ -342,10 +332,9 @@ sctp_find_alternate_net(struct sctp_tcb *stcb,
return (NULL);
}
}
do {
for (;;) {
alt = TAILQ_NEXT(mnet, sctp_next);
if (alt == NULL)
{
if (alt == NULL) {
once++;
if (once > 1) {
break;
@ -362,7 +351,6 @@ sctp_find_alternate_net(struct sctp_tcb *stcb,
}
alt->src_addr_selected = 0;
}
/*sa_ignore NO_NULL_CHK*/
if (((alt->dest_state & SCTP_ADDR_REACHABLE) == SCTP_ADDR_REACHABLE) &&
(alt->ro.ro_rt != NULL) &&
(!(alt->dest_state & SCTP_ADDR_UNCONFIRMED))) {
@ -370,14 +358,14 @@ sctp_find_alternate_net(struct sctp_tcb *stcb,
break;
}
mnet = alt;
} while (alt != NULL);
}
if (alt == NULL) {
/* Case where NO insv network exists (dormant state) */
/* we rotate destinations */
once = 0;
mnet = net;
do {
for (;;) {
if (mnet == NULL) {
return (TAILQ_FIRST(&stcb->asoc.nets));
}
@ -388,15 +376,17 @@ sctp_find_alternate_net(struct sctp_tcb *stcb,
break;
}
alt = TAILQ_FIRST(&stcb->asoc.nets);
if (alt == NULL) {
break;
}
}
/*sa_ignore NO_NULL_CHK*/
if ((!(alt->dest_state & SCTP_ADDR_UNCONFIRMED)) &&
(alt != net)) {
/* Found an alternate address */
break;
}
mnet = alt;
} while (alt != NULL);
}
}
if (alt == NULL) {
return (net);
@ -451,7 +441,7 @@ sctp_recover_sent_list(struct sctp_tcb *stcb)
sctp_free_bufspace(stcb, asoc, chk, 1);
sctp_m_freem(chk->data);
chk->data = NULL;
if (asoc->peer_supports_prsctp && PR_SCTP_BUF_ENABLED(chk->flags)) {
if (asoc->prsctp_supported && PR_SCTP_BUF_ENABLED(chk->flags)) {
asoc->sent_queue_cnt_removeable--;
}
}
@ -609,7 +599,7 @@ sctp_mark_all_for_resend(struct sctp_tcb *stcb,
continue;
}
}
if (stcb->asoc.peer_supports_prsctp && PR_SCTP_TTL_ENABLED(chk->flags)) {
if (stcb->asoc.prsctp_supported && PR_SCTP_TTL_ENABLED(chk->flags)) {
/* Is it expired? */
#ifndef __FreeBSD__
if (timercmp(&now, &chk->rec.data.timetodrop, >)) {
@ -627,7 +617,7 @@ sctp_mark_all_for_resend(struct sctp_tcb *stcb,
continue;
}
}
if (stcb->asoc.peer_supports_prsctp && PR_SCTP_RTX_ENABLED(chk->flags)) {
if (stcb->asoc.prsctp_supported && PR_SCTP_RTX_ENABLED(chk->flags)) {
/* Has it been retransmitted tv_sec times? */
if (chk->snd_count > chk->rec.data.timetodrop.tv_sec) {
if (chk->data) {
@ -936,9 +926,9 @@ sctp_t3rxt_timer(struct sctp_inpcb *inp,
*/
if (net->ro._s_addr) {
sctp_free_ifa(net->ro._s_addr);
net->ro._s_addr = NULL;
net->ro._s_addr = NULL;
}
net->src_addr_selected = 0;
net->src_addr_selected = 0;
/* Force a route allocation too */
if (net->ro.ro_rt) {
@ -974,7 +964,7 @@ sctp_t3rxt_timer(struct sctp_inpcb *inp,
sctp_timer_start(SCTP_TIMER_TYPE_SEND, inp, stcb, net);
return (0);
}
if (stcb->asoc.peer_supports_prsctp) {
if (stcb->asoc.prsctp_supported) {
struct sctp_tmit_chunk *lchk;
lchk = sctp_try_advance_peer_ack_point(stcb, &stcb->asoc);
@ -1058,24 +1048,12 @@ sctp_cookie_timer(struct sctp_inpcb *inp,
if (cookie == NULL) {
if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_ECHOED) {
/* FOOBAR! */
struct mbuf *oper;
struct mbuf *op_err;
oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + sizeof(uint32_t)),
0, M_NOWAIT, 1, MT_DATA);
if (oper) {
struct sctp_paramhdr *ph;
uint32_t *ippp;
SCTP_BUF_LEN(oper) = sizeof(struct sctp_paramhdr) +
sizeof(uint32_t);
ph = mtod(oper, struct sctp_paramhdr *);
ph->param_type = htons(SCTP_CAUSE_PROTOCOL_VIOLATION);
ph->param_length = htons(SCTP_BUF_LEN(oper));
ippp = (uint32_t *) (ph + 1);
*ippp = htonl(SCTP_FROM_SCTP_TIMER+SCTP_LOC_3);
}
op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION,
"Cookie timer expired, but no cookie");
inp->last_abort_code = SCTP_FROM_SCTP_TIMER+SCTP_LOC_4;
sctp_abort_an_association(inp, stcb, oper, SCTP_SO_NOT_LOCKED);
sctp_abort_an_association(inp, stcb, op_err, SCTP_SO_NOT_LOCKED);
} else {
#ifdef INVARIANTS
panic("Cookie timer expires in wrong state?");
@ -1501,7 +1479,7 @@ sctp_pathmtu_timer(struct sctp_inpcb *inp,
#elif defined(SCTP_KAME)
(void)sa6_embedscope(sin6, MODULE_GLOBAL(ip6_use_defzone));
#else
(void)in6_embedscope(&sin6->sin6_addr, sin6);
(void)in6_embedscope(&sin6->sin6_addr, sin6);
#endif
}
#endif
@ -1526,9 +1504,11 @@ sctp_pathmtu_timer(struct sctp_inpcb *inp,
}
if (net->ro._s_addr) {
mtu = SCTP_GATHER_MTU_FROM_ROUTE(net->ro._s_addr, &net->ro._s_addr.sa, net->ro.ro_rt);
#if defined(INET) || defined(INET6)
if (net->port) {
mtu -= sizeof(struct udphdr);
}
#endif
if (mtu > next_mtu) {
net->mtu = next_mtu;
}

View File

@ -32,7 +32,7 @@
#ifdef __FreeBSD__
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: head/sys/netinet/sctp_uio.h 255160 2013-09-02 22:48:41Z tuexen $");
__FBSDID("$FreeBSD: head/sys/netinet/sctp_uio.h 269945 2014-08-13 15:50:16Z tuexen $");
#endif
#ifndef _NETINET_SCTP_UIO_H_
@ -279,18 +279,23 @@ struct sctp_snd_all_completes {
SCTP_SACK_IMMEDIATELY)) != 0)
/* for the endpoint */
/* The lower byte is an enumeration of PR-SCTP policies */
/* The lower four bits is an enumeration of PR-SCTP policies */
#define SCTP_PR_SCTP_NONE 0x0000 /* Reliable transfer */
#define SCTP_PR_SCTP_TTL 0x0001 /* Time based PR-SCTP */
#define SCTP_PR_SCTP_BUF 0x0002 /* Buffer based PR-SCTP */
#define SCTP_PR_SCTP_RTX 0x0003 /* Number of retransmissions based PR-SCTP */
#define SCTP_PR_SCTP_MAX SCTP_PR_SCTP_RTX
#define SCTP_PR_SCTP_ALL 0x000f /* Used for aggregated stats */
#define PR_SCTP_POLICY(x) ((x) & 0x0f)
#define PR_SCTP_ENABLED(x) (PR_SCTP_POLICY(x) != SCTP_PR_SCTP_NONE)
#define PR_SCTP_ENABLED(x) ((PR_SCTP_POLICY(x) != SCTP_PR_SCTP_NONE) && \
(PR_SCTP_POLICY(x) != SCTP_PR_SCTP_ALL))
#define PR_SCTP_TTL_ENABLED(x) (PR_SCTP_POLICY(x) == SCTP_PR_SCTP_TTL)
#define PR_SCTP_BUF_ENABLED(x) (PR_SCTP_POLICY(x) == SCTP_PR_SCTP_BUF)
#define PR_SCTP_RTX_ENABLED(x) (PR_SCTP_POLICY(x) == SCTP_PR_SCTP_RTX)
#define PR_SCTP_INVALID_POLICY(x) (PR_SCTP_POLICY(x) > SCTP_PR_SCTP_RTX)
#define PR_SCTP_INVALID_POLICY(x) (PR_SCTP_POLICY(x) > SCTP_PR_SCTP_MAX)
#define PR_SCTP_VALID_POLICY(x) (PR_SCTP_POLICY(x) <= SCTP_PR_SCTP_MAX)
/* Stat's */
struct sctp_pcbinfo {
uint32_t ep_count;
@ -353,7 +358,6 @@ struct sctp_paddr_change {
uint32_t spc_state;
uint32_t spc_error;
sctp_assoc_t spc_assoc_id;
uint8_t spc_padding[4];
};
/* paddr state values */
@ -376,7 +380,7 @@ struct sctp_remote_error {
uint32_t sre_length;
uint16_t sre_error;
sctp_assoc_t sre_assoc_id;
uint8_t sre_data[4];
uint8_t sre_data[];
};
/* data send failure event (deprecated) */
@ -749,6 +753,14 @@ struct sctp_udpencaps {
uint16_t sue_port;
};
struct sctp_prstatus {
sctp_assoc_t sprstat_assoc_id;
uint16_t sprstat_sid;
uint16_t sprstat_policy;
uint64_t sprstat_abandoned_unsent;
uint64_t sprstat_abandoned_sent;
};
struct sctp_cwnd_args {
struct sctp_nets *net; /* network to */ /* FIXME: LP64 issue */
uint32_t cwnd_new_value;/* cwnd in k */

View File

@ -35,7 +35,7 @@
#endif
#include <netinet/sctp_os_userspace.h>
#ifndef _WIN32
#if !defined(_WIN32) && !defined(__Userspace_os_NaCl)
int
sctp_userspace_get_mtu_from_ifn(uint32_t if_index, int af)
{
@ -55,6 +55,14 @@ sctp_userspace_get_mtu_from_ifn(uint32_t if_index, int af)
}
#endif
#if defined(__Userspace_os_NaCl)
int
sctp_userspace_get_mtu_from_ifn(uint32_t if_index, int af)
{
return 1280;
}
#endif
#ifdef _WIN32
int
sctp_userspace_get_mtu_from_ifn(uint32_t if_index, int af)
@ -90,8 +98,8 @@ getwintimeofday(struct timeval *tv)
struct timeb tb;
ftime(&tb);
tv->tv_sec = tb.time;
tv->tv_usec = tb.millitm * 1000;
tv->tv_sec = (long)tb.time;
tv->tv_usec = (long)(tb.millitm) * 1000L;
}
int
@ -138,10 +146,10 @@ Win_getifaddrs(struct ifaddrs** interfaces)
SCTPDBG(SCTP_DEBUG_USR, "Can't allocate memory\n");
return (-1);
}
ifa->ifa_name = strdup(pAdapt->AdapterName);
ifa->ifa_name = _strdup(pAdapt->AdapterName);
ifa->ifa_flags = pAdapt->Flags;
ifa->ifa_addr = (struct sockaddr *)addr;
memcpy(&addr, &pAdapt->FirstUnicastAddress->Address.lpSockaddr, sizeof(struct sockaddr_in));
memcpy(addr, &pAdapt->FirstUnicastAddress->Address.lpSockaddr, sizeof(struct sockaddr_in));
interfaces[count] = ifa;
}
#endif
@ -172,10 +180,10 @@ Win_getifaddrs(struct ifaddrs** interfaces)
SCTPDBG(SCTP_DEBUG_USR, "Can't allocate memory\n");
return (-1);
}
ifa->ifa_name = strdup(pAdapt->AdapterName);
ifa->ifa_name = _strdup(pAdapt->AdapterName);
ifa->ifa_flags = pAdapt->Flags;
ifa->ifa_addr = (struct sockaddr *)addr6;
memcpy(&addr6, &pAdapt->FirstUnicastAddress->Address.lpSockaddr, sizeof(struct sockaddr_in6));
memcpy(addr6, &pAdapt->FirstUnicastAddress->Address.lpSockaddr, sizeof(struct sockaddr_in6));
interfaces[count] = ifa;
}
}
@ -215,11 +223,11 @@ win_if_nametoindex(const char *ifname)
}
#if WINVER < 0x0600
/* These functions are written based on the code at
/* These functions are written based on the code at
* http://www.cs.wustl.edu/~schmidt/win32-cv-1.html
* Therefore, for the rest of the file the following applies:
*
*
*
* Copyright and Licensing Information for ACE(TM), TAO(TM), CIAO(TM),
* DAnCE(TM), and CoSMIC(TM)
*
@ -326,7 +334,7 @@ win_if_nametoindex(const char *ifname)
* 22. http://www.dre.vanderbilt.edu/~schmidt/
* 23. http://www.cs.wustl.edu/ACE.html
*/
void
InitializeXPConditionVariable(userland_cond_t *cv)
{
@ -359,8 +367,7 @@ SleepXPConditionVariable(userland_cond_t *cv, userland_mutex_t *mtx)
}
EnterCriticalSection(&cv->waiters_count_lock);
cv->waiters_count--;
last_waiter =
result == (C_SIGNAL + C_BROADCAST && (cv->waiters_count == 0));
last_waiter = result == (C_SIGNAL + C_BROADCAST && (cv->waiters_count == 0));
LeaveCriticalSection(&cv->waiters_count_lock);
if (last_waiter)
ResetEvent(cv->events_[C_BROADCAST]);

File diff suppressed because it is too large Load Diff

View File

@ -32,7 +32,7 @@
#ifdef __FreeBSD__
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: head/sys/netinet/sctp_var.h 242327 2012-10-29 20:47:32Z tuexen $");
__FBSDID("$FreeBSD: head/sys/netinet/sctp_var.h 275427 2014-12-02 20:29:29Z tuexen $");
#endif
#ifndef _NETINET_SCTP_VAR_H_
@ -76,7 +76,7 @@ extern struct pr_usrreqs sctp_usrreqs;
((stcb->asoc.sctp_features & feature) == 0)) || \
((stcb == NULL) && (inp != NULL) && \
((inp->sctp_features & feature) == 0)) || \
((stcb == NULL) && (inp == NULL)))
((stcb == NULL) && (inp == NULL)))
/* managing mobility_feature in inpcb (by micchie) */
#define sctp_mobility_feature_on(inp, feature) (inp->sctp_mobility_features |= feature)
@ -110,7 +110,7 @@ extern struct pr_usrreqs sctp_usrreqs;
#define sctp_alloc_a_readq(_stcb, _readq) { \
(_readq) = SCTP_ZONE_GET(SCTP_BASE_INFO(ipi_zone_readq), struct sctp_queued_to_read); \
if ((_readq)) { \
SCTP_INCR_READQ_COUNT(); \
SCTP_INCR_READQ_COUNT(); \
} \
}
@ -125,11 +125,11 @@ extern struct pr_usrreqs sctp_usrreqs;
#define sctp_alloc_a_strmoq(_stcb, _strmoq) { \
(_strmoq) = SCTP_ZONE_GET(SCTP_BASE_INFO(ipi_zone_strmoq), struct sctp_stream_queue_pending); \
if ((_strmoq)) { \
if ((_strmoq)) { \
memset(_strmoq, 0, sizeof(struct sctp_stream_queue_pending)); \
SCTP_INCR_STRMOQ_COUNT(); \
(_strmoq)->holds_key_ref = 0; \
} \
} \
}
#define sctp_free_a_chunk(_stcb, _chk, _so_locked) { \
@ -137,22 +137,22 @@ extern struct pr_usrreqs sctp_usrreqs;
sctp_auth_key_release((_stcb), (_chk)->auth_keyid, _so_locked); \
(_chk)->holds_key_ref = 0; \
} \
if (_stcb) { \
SCTP_TCB_LOCK_ASSERT((_stcb)); \
if ((_chk)->whoTo) { \
sctp_free_remote_addr((_chk)->whoTo); \
(_chk)->whoTo = NULL; \
} \
if (((_stcb)->asoc.free_chunk_cnt > SCTP_BASE_SYSCTL(sctp_asoc_free_resc_limit)) || \
(SCTP_BASE_INFO(ipi_free_chunks) > SCTP_BASE_SYSCTL(sctp_system_free_resc_limit))) { \
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_chunk), (_chk)); \
SCTP_DECR_CHK_COUNT(); \
} else { \
TAILQ_INSERT_TAIL(&(_stcb)->asoc.free_chunks, (_chk), sctp_next); \
(_stcb)->asoc.free_chunk_cnt++; \
atomic_add_int(&SCTP_BASE_INFO(ipi_free_chunks), 1); \
} \
} else { \
if (_stcb) { \
SCTP_TCB_LOCK_ASSERT((_stcb)); \
if ((_chk)->whoTo) { \
sctp_free_remote_addr((_chk)->whoTo); \
(_chk)->whoTo = NULL; \
} \
if (((_stcb)->asoc.free_chunk_cnt > SCTP_BASE_SYSCTL(sctp_asoc_free_resc_limit)) || \
(SCTP_BASE_INFO(ipi_free_chunks) > SCTP_BASE_SYSCTL(sctp_system_free_resc_limit))) { \
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_chunk), (_chk)); \
SCTP_DECR_CHK_COUNT(); \
} else { \
TAILQ_INSERT_TAIL(&(_stcb)->asoc.free_chunks, (_chk), sctp_next); \
(_stcb)->asoc.free_chunk_cnt++; \
atomic_add_int(&SCTP_BASE_INFO(ipi_free_chunks), 1); \
} \
} else { \
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_chunk), (_chk)); \
SCTP_DECR_CHK_COUNT(); \
} \
@ -163,7 +163,7 @@ extern struct pr_usrreqs sctp_usrreqs;
(_chk) = SCTP_ZONE_GET(SCTP_BASE_INFO(ipi_zone_chunk), struct sctp_tmit_chunk); \
if ((_chk)) { \
SCTP_INCR_CHK_COUNT(); \
(_chk)->whoTo = NULL; \
(_chk)->whoTo = NULL; \
(_chk)->holds_key_ref = 0; \
} \
} else { \
@ -171,7 +171,7 @@ extern struct pr_usrreqs sctp_usrreqs;
TAILQ_REMOVE(&(_stcb)->asoc.free_chunks, (_chk), sctp_next); \
atomic_subtract_int(&SCTP_BASE_INFO(ipi_free_chunks), 1); \
(_chk)->holds_key_ref = 0; \
SCTP_STAT_INCR(sctps_cached_chk); \
SCTP_STAT_INCR(sctps_cached_chk); \
(_stcb)->asoc.free_chunk_cnt--; \
} \
}
@ -183,15 +183,15 @@ extern struct pr_usrreqs sctp_usrreqs;
if (SCTP_DECREMENT_AND_CHECK_REFCOUNT(&(__net)->ref_count)) { \
(void)SCTP_OS_TIMER_STOP(&(__net)->rxt_timer.timer); \
(void)SCTP_OS_TIMER_STOP(&(__net)->pmtu_timer.timer); \
if ((__net)->ro.ro_rt) { \
if ((__net)->ro.ro_rt) { \
RTFREE((__net)->ro.ro_rt); \
(__net)->ro.ro_rt = NULL; \
} \
} \
if ((__net)->src_addr_selected) { \
sctp_free_ifa((__net)->ro._s_addr); \
(__net)->ro._s_addr = NULL; \
} \
(__net)->src_addr_selected = 0; \
(__net)->src_addr_selected = 0; \
(__net)->dest_state &= ~SCTP_ADDR_REACHABLE; \
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_net), (__net)); \
SCTP_DECR_RADDR_COUNT(); \
@ -231,15 +231,15 @@ extern struct pr_usrreqs sctp_usrreqs;
(void)SCTP_OS_TIMER_STOP(&(__net)->rxt_timer.timer); \
(void)SCTP_OS_TIMER_STOP(&(__net)->pmtu_timer.timer); \
(void)SCTP_OS_TIMER_STOP(&(__net)->hb_timer.timer); \
if ((__net)->ro.ro_rt) { \
if ((__net)->ro.ro_rt) { \
RTFREE((__net)->ro.ro_rt); \
(__net)->ro.ro_rt = NULL; \
} \
} \
if ((__net)->src_addr_selected) { \
sctp_free_ifa((__net)->ro._s_addr); \
(__net)->ro._s_addr = NULL; \
} \
(__net)->src_addr_selected = 0; \
(__net)->src_addr_selected = 0; \
(__net)->dest_state &=~SCTP_ADDR_REACHABLE; \
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_net), (__net)); \
SCTP_DECR_RADDR_COUNT(); \
@ -323,12 +323,12 @@ extern struct pr_usrreqs sctp_usrreqs;
} while (0)
#define sctp_flight_size_increase(tp1) do { \
(tp1)->whoTo->flight_size += (tp1)->book_size; \
(tp1)->whoTo->flight_size += (tp1)->book_size; \
} while (0)
#ifdef SCTP_FS_SPEC_LOG
#define sctp_total_flight_decrease(stcb, tp1) do { \
if (stcb->asoc.fs_index > SCTP_FS_SPEC_LOG_SIZE) \
if (stcb->asoc.fs_index > SCTP_FS_SPEC_LOG_SIZE) \
stcb->asoc.fs_index = 0;\
stcb->asoc.fslog[stcb->asoc.fs_index].total_flight = stcb->asoc.total_flight; \
stcb->asoc.fslog[stcb->asoc.fs_index].tsn = tp1->rec.data.TSN_seq; \
@ -337,7 +337,7 @@ extern struct pr_usrreqs sctp_usrreqs;
stcb->asoc.fslog[stcb->asoc.fs_index].incr = 0; \
stcb->asoc.fslog[stcb->asoc.fs_index].decr = 1; \
stcb->asoc.fs_index++; \
tp1->window_probe = 0; \
tp1->window_probe = 0; \
if (stcb->asoc.total_flight >= tp1->book_size) { \
stcb->asoc.total_flight -= tp1->book_size; \
if (stcb->asoc.total_flight_count > 0) \
@ -349,7 +349,7 @@ extern struct pr_usrreqs sctp_usrreqs;
} while (0)
#define sctp_total_flight_increase(stcb, tp1) do { \
if (stcb->asoc.fs_index > SCTP_FS_SPEC_LOG_SIZE) \
if (stcb->asoc.fs_index > SCTP_FS_SPEC_LOG_SIZE) \
stcb->asoc.fs_index = 0;\
stcb->asoc.fslog[stcb->asoc.fs_index].total_flight = stcb->asoc.total_flight; \
stcb->asoc.fslog[stcb->asoc.fs_index].tsn = tp1->rec.data.TSN_seq; \
@ -358,14 +358,14 @@ extern struct pr_usrreqs sctp_usrreqs;
stcb->asoc.fslog[stcb->asoc.fs_index].incr = 1; \
stcb->asoc.fslog[stcb->asoc.fs_index].decr = 0; \
stcb->asoc.fs_index++; \
(stcb)->asoc.total_flight_count++; \
(stcb)->asoc.total_flight += (tp1)->book_size; \
(stcb)->asoc.total_flight_count++; \
(stcb)->asoc.total_flight += (tp1)->book_size; \
} while (0)
#else
#define sctp_total_flight_decrease(stcb, tp1) do { \
tp1->window_probe = 0; \
tp1->window_probe = 0; \
if (stcb->asoc.total_flight >= tp1->book_size) { \
stcb->asoc.total_flight -= tp1->book_size; \
if (stcb->asoc.total_flight_count > 0) \
@ -377,8 +377,8 @@ extern struct pr_usrreqs sctp_usrreqs;
} while (0)
#define sctp_total_flight_increase(stcb, tp1) do { \
(stcb)->asoc.total_flight_count++; \
(stcb)->asoc.total_flight += (tp1)->book_size; \
(stcb)->asoc.total_flight_count++; \
(stcb)->asoc.total_flight += (tp1)->book_size; \
} while (0)
#endif
@ -412,8 +412,12 @@ void sctp_ctlinput(int, struct sockaddr *, void *);
int sctp_ctloutput(struct socket *, struct sockopt *);
#ifdef INET
void sctp_input_with_port(struct mbuf *, int, uint16_t);
#if defined(__FreeBSD__) && __FreeBSD_version >= 1100020
int sctp_input(struct mbuf **, int *, int);
#else
void sctp_input(struct mbuf *, int);
#endif
#endif
void sctp_pathmtu_adjustment(struct sctp_tcb *, uint16_t);
#endif
#else

View File

@ -32,7 +32,7 @@
#ifdef __FreeBSD__
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: head/sys/netinet/sctputil.c 259943 2013-12-27 13:07:00Z tuexen $");
__FBSDID("$FreeBSD: head/sys/netinet/sctputil.c 277049 2015-01-12 07:39:52Z tuexen $");
#endif
#include <netinet/sctp_os.h>
@ -252,6 +252,7 @@ sctp_log_fr(uint32_t biggest_tsn, uint32_t biggest_new_tsn, uint32_t tsn, int fr
#endif
}
#ifdef SCTP_MBUF_LOGGING
void
sctp_log_mb(struct mbuf *m, int from)
{
@ -283,6 +284,17 @@ sctp_log_mb(struct mbuf *m, int from)
#endif
}
void
sctp_log_mbc(struct mbuf *m, int from)
{
struct mbuf *mat;
for (mat = m; mat; mat = SCTP_BUF_NEXT(mat)) {
sctp_log_mb(mat, from);
}
}
#endif
void
sctp_log_strm_del(struct sctp_queued_to_read *control, struct sctp_queued_to_read *poschk, int from)
{
@ -474,7 +486,8 @@ sctp_log_rwnd_set(uint8_t from, uint32_t peers_rwnd, uint32_t flight_size, uint3
#endif
}
void
#ifdef SCTP_MBCNT_LOGGING
static void
sctp_log_mbcnt(uint8_t from, uint32_t total_oq, uint32_t book, uint32_t total_mbcnt_q, uint32_t mbcnt)
{
#if defined(__FreeBSD__) || defined(SCTP_LOCAL_TRACE_BUF)
@ -493,6 +506,7 @@ sctp_log_mbcnt(uint8_t from, uint32_t total_oq, uint32_t book, uint32_t total_mb
sctp_clog.x.misc.log4);
#endif
}
#endif
void
sctp_misc_ints(uint8_t from, uint32_t a, uint32_t b, uint32_t c, uint32_t d)
@ -963,6 +977,9 @@ sctp_init_asoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
* caller in the sctp_aloc_assoc() function.
*/
int i;
#if defined(SCTP_DETAILED_STR_STATS)
int j;
#endif
asoc = &stcb->asoc;
/* init all variables to a known value. */
@ -972,8 +989,13 @@ sctp_init_asoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
asoc->heart_beat_delay = TICKS_TO_MSEC(inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT]);
asoc->cookie_life = inp->sctp_ep.def_cookie_life;
asoc->sctp_cmt_on_off = inp->sctp_cmt_on_off;
asoc->ecn_allowed = inp->sctp_ecn_enable;
asoc->sctp_nr_sack_on_off = (uint8_t)SCTP_BASE_SYSCTL(sctp_nr_sack_on_off);
asoc->ecn_supported = inp->ecn_supported;
asoc->prsctp_supported = inp->prsctp_supported;
asoc->auth_supported = inp->auth_supported;
asoc->asconf_supported = inp->asconf_supported;
asoc->reconfig_supported = inp->reconfig_supported;
asoc->nrsack_supported = inp->nrsack_supported;
asoc->pktdrop_supported = inp->pktdrop_supported;
asoc->sctp_cmt_pf = (uint8_t)0;
asoc->sctp_frag_point = inp->sctp_frag_point;
asoc->sctp_features = inp->sctp_features;
@ -1004,7 +1026,7 @@ sctp_init_asoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
#ifdef SCTP_ASOCLOG_OF_TSNS
asoc->tsn_in_at = 0;
asoc->tsn_out_at = 0;
asoc->tsn_out_at = 0;
asoc->tsn_in_wrapped = 0;
asoc->tsn_out_wrapped = 0;
asoc->cumack_log_at = 0;
@ -1019,7 +1041,6 @@ sctp_init_asoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
sctp_select_initial_TSN(&inp->sctp_ep);
asoc->asconf_seq_out_acked = asoc->asconf_seq_out - 1;
/* we are optimisitic here */
asoc->peer_supports_pktdrop = 1;
asoc->peer_supports_nat = 0;
asoc->sent_queue_retran_cnt = 0;
@ -1133,6 +1154,15 @@ sctp_init_asoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
asoc->strmout[i].next_sequence_send = 0x0;
TAILQ_INIT(&asoc->strmout[i].outqueue);
asoc->strmout[i].chunks_on_queues = 0;
#if defined(SCTP_DETAILED_STR_STATS)
for (j = 0; j < SCTP_PR_SCTP_MAX + 1; j++) {
asoc->strmout[i].abandoned_sent[j] = 0;
asoc->strmout[i].abandoned_unsent[j] = 0;
}
#else
asoc->strmout[i].abandoned_sent[0] = 0;
asoc->strmout[i].abandoned_unsent[0] = 0;
#endif
asoc->strmout[i].stream_no = i;
asoc->strmout[i].last_msg_incomplete = 0;
asoc->ss_functions.sctp_ss_init_stream(&asoc->strmout[i], NULL);
@ -1188,6 +1218,10 @@ sctp_init_asoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
asoc->timoshutdownack = 0;
(void)SCTP_GETTIME_TIMEVAL(&asoc->start_time);
asoc->discontinuity_time = asoc->start_time;
for (i = 0; i < SCTP_PR_SCTP_MAX + 1; i++) {
asoc->abandoned_unsent[i] = 0;
asoc->abandoned_sent[i] = 0;
}
/* sa_ignore MEMLEAK {memory is put in the assoc mapping array and freed later when
* the association is freed.
*/
@ -1273,7 +1307,7 @@ sctp_iterator_work(struct sctp_iterator *it)
SCTP_INP_INFO_RLOCK();
SCTP_ITERATOR_LOCK();
if (it->inp) {
if (it->inp) {
SCTP_INP_RLOCK(it->inp);
SCTP_INP_DECR_REF(it->inp);
}
@ -1816,7 +1850,7 @@ sctp_timeout_handler(void *t)
goto out_decr;
}
SCTP_STAT_INCR(sctps_timoshutdownack);
stcb->asoc.timoshutdownack++;
stcb->asoc.timoshutdownack++;
#ifdef SCTP_AUDITING_ENABLED
sctp_auditing(4, inp, stcb, net);
#endif
@ -2047,7 +2081,7 @@ sctp_timer_start(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb,
* though we use a different timer. We also add the HB timer
* PLUS a random jitter.
*/
if ((inp == NULL) || (stcb == NULL) || (net == NULL)) {
if ((stcb == NULL) || (net == NULL)) {
return;
} else {
uint32_t rndval;
@ -2102,9 +2136,6 @@ sctp_timer_start(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb,
* nothing needed but the endpoint here ususually about 60
* minutes.
*/
if (inp == NULL) {
return;
}
tmr = &inp->sctp_ep.signature_change;
to_ticks = inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_SIGNATURE];
break;
@ -2121,9 +2152,6 @@ sctp_timer_start(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb,
* timer since that has stopped and we are in the GONE
* state.
*/
if (inp == NULL) {
return;
}
tmr = &inp->sctp_ep.signature_change;
to_ticks = MSEC_TO_TICKS(SCTP_INP_KILL_TIMEOUT);
break;
@ -2132,10 +2160,7 @@ sctp_timer_start(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb,
* Here we use the value found in the EP for PMTU ususually
* about 10 minutes.
*/
if ((stcb == NULL) || (inp == NULL)) {
return;
}
if (net == NULL) {
if ((stcb == NULL) || (net == NULL)) {
return;
}
if (net->dest_state & SCTP_ADDR_NO_PMTUD) {
@ -2161,7 +2186,7 @@ sctp_timer_start(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb,
* Here we use the endpoints shutdown guard timer usually
* about 3 minutes.
*/
if ((inp == NULL) || (stcb == NULL)) {
if (stcb == NULL) {
return;
}
to_ticks = inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_MAXSHUTDOWN];
@ -2504,8 +2529,8 @@ sctp_calculate_rto(struct sctp_tcb *stcb,
/* store the current RTT in us */
net->rtt = (uint64_t)1000000 * (uint64_t)now.tv_sec +
(uint64_t)now.tv_usec;
/* computer rtt in ms */
rtt = net->rtt / 1000;
/* compute rtt in ms */
rtt = (int32_t)(net->rtt / 1000);
if ((asoc->cc_functions.sctp_rtt_calculated) && (rtt_from_sack == SCTP_RTT_FROM_DATA)) {
/* Tell the CC module that a new update has just occurred from a sack */
(*asoc->cc_functions.sctp_rtt_calculated)(stcb, net, &now);
@ -2566,15 +2591,15 @@ sctp_calculate_rto(struct sctp_tcb *stcb,
stcb->asoc.sat_network = 0;
stcb->asoc.sat_network_lockout = 1;
}
/* bound it, per C6/C7 in Section 5.3.1 */
if (new_rto < stcb->asoc.minrto) {
/* bound it, per C6/C7 in Section 5.3.1 */
if (new_rto < stcb->asoc.minrto) {
new_rto = stcb->asoc.minrto;
}
if (new_rto > stcb->asoc.maxrto) {
new_rto = stcb->asoc.maxrto;
}
/* we are now returning the RTO */
return (new_rto);
return (new_rto);
}
/*
@ -2637,58 +2662,44 @@ sctp_get_next_param(struct mbuf *m,
}
int
struct mbuf *
sctp_add_pad_tombuf(struct mbuf *m, int padlen)
{
/*
* add padlen bytes of 0 filled padding to the end of the mbuf. If
* padlen is > 3 this routine will fail.
*/
uint8_t *dp;
int i;
struct mbuf *m_last;
caddr_t dp;
if (padlen > 3) {
SCTP_LTRACE_ERR_RET_PKT(m, NULL, NULL, NULL, SCTP_FROM_SCTPUTIL, ENOBUFS);
return (ENOBUFS);
return (NULL);
}
if (padlen <= M_TRAILINGSPACE(m)) {
/*
* The easy way. We hope the majority of the time we hit
* here :)
*/
dp = (uint8_t *) (mtod(m, caddr_t) + SCTP_BUF_LEN(m));
SCTP_BUF_LEN(m) += padlen;
m_last = m;
} else {
/* Hard way we must grow the mbuf */
struct mbuf *tmp;
tmp = sctp_get_mbuf_for_msg(padlen, 0, M_NOWAIT, 1, MT_DATA);
if (tmp == NULL) {
/* Out of space GAK! we are in big trouble. */
SCTP_LTRACE_ERR_RET_PKT(m, NULL, NULL, NULL, SCTP_FROM_SCTPUTIL, ENOBUFS);
return (ENOBUFS);
/* Hard way we must grow the mbuf chain */
m_last = sctp_get_mbuf_for_msg(padlen, 0, M_NOWAIT, 1, MT_DATA);
if (m_last == NULL) {
return (NULL);
}
/* setup and insert in middle */
SCTP_BUF_LEN(tmp) = padlen;
SCTP_BUF_NEXT(tmp) = NULL;
SCTP_BUF_NEXT(m) = tmp;
dp = mtod(tmp, uint8_t *);
SCTP_BUF_LEN(m_last) = 0;
SCTP_BUF_NEXT(m_last) = NULL;
SCTP_BUF_NEXT(m) = m_last;
}
/* zero out the pad */
for (i = 0; i < padlen; i++) {
*dp = 0;
dp++;
}
return (0);
dp = mtod(m_last, caddr_t) + SCTP_BUF_LEN(m_last);
SCTP_BUF_LEN(m_last) += padlen;
memset(dp, 0, padlen);
return (m_last);
}
int
struct mbuf *
sctp_pad_lastmbuf(struct mbuf *m, int padval, struct mbuf *last_mbuf)
{
/* find the last mbuf in chain and pad it */
struct mbuf *m_at;
if (last_mbuf) {
if (last_mbuf != NULL) {
return (sctp_add_pad_tombuf(last_mbuf, padval));
} else {
for (m_at = m; m_at; m_at = SCTP_BUF_NEXT(m_at)) {
@ -2697,8 +2708,7 @@ sctp_pad_lastmbuf(struct mbuf *m, int padval, struct mbuf *last_mbuf)
}
}
}
SCTP_LTRACE_ERR_RET_PKT(m, NULL, NULL, NULL, SCTP_FROM_SCTPUTIL, EFAULT);
return (EFAULT);
return (NULL);
}
static void
@ -2741,6 +2751,7 @@ sctp_notify_assoc_change(uint16_t state, struct sctp_tcb *stcb,
}
SCTP_BUF_NEXT(m_notify) = NULL;
sac = mtod(m_notify, struct sctp_assoc_change *);
memset(sac, 0, notif_len);
sac->sac_type = SCTP_ASSOC_CHANGE;
sac->sac_flags = 0;
sac->sac_length = sizeof(struct sctp_assoc_change);
@ -2753,17 +2764,17 @@ sctp_notify_assoc_change(uint16_t state, struct sctp_tcb *stcb,
if (notif_len > sizeof(struct sctp_assoc_change)) {
if ((state == SCTP_COMM_UP) || (state == SCTP_RESTART)) {
i = 0;
if (stcb->asoc.peer_supports_prsctp) {
if (stcb->asoc.prsctp_supported == 1) {
sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_PR;
}
if (stcb->asoc.peer_supports_auth) {
if (stcb->asoc.auth_supported == 1) {
sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_AUTH;
}
if (stcb->asoc.peer_supports_asconf) {
if (stcb->asoc.asconf_supported == 1) {
sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_ASCONF;
}
sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_MULTIBUF;
if (stcb->asoc.peer_supports_strreset) {
if (stcb->asoc.reconfig_supported == 1) {
sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_RE_CONFIG;
}
sac->sac_length += i;
@ -2868,13 +2879,23 @@ sctp_notify_peer_addr_change(struct sctp_tcb *stcb, uint32_t state,
return;
SCTP_BUF_LEN(m_notify) = 0;
spc = mtod(m_notify, struct sctp_paddr_change *);
memset(spc, 0, sizeof(struct sctp_paddr_change));
spc->spc_type = SCTP_PEER_ADDR_CHANGE;
spc->spc_flags = 0;
spc->spc_length = sizeof(struct sctp_paddr_change);
switch (sa->sa_family) {
#ifdef INET
case AF_INET:
#ifdef INET6
if (sctp_is_feature_on(stcb->sctp_ep, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) {
in6_sin_2_v4mapsin6((struct sockaddr_in *)sa,
(struct sockaddr_in6 *)&spc->spc_aaddr);
} else {
memcpy(&spc->spc_aaddr, sa, sizeof(struct sockaddr_in));
}
#else
memcpy(&spc->spc_aaddr, sa, sizeof(struct sockaddr_in));
#endif
break;
#endif
#ifdef INET6
@ -2891,7 +2912,7 @@ sctp_notify_peer_addr_change(struct sctp_tcb *stcb, uint32_t state,
if (sin6->sin6_scope_id == 0) {
/* recover scope_id for user */
#ifdef SCTP_KAME
(void)sa6_recoverscope(sin6);
(void)sa6_recoverscope(sin6);
#else
(void)in6_recoverscope(sin6, &sin6->sin6_addr,
NULL);
@ -2972,21 +2993,21 @@ sctp_notify_send_failed(struct sctp_tcb *stcb, uint8_t sent, uint32_t error,
if (m_notify == NULL)
/* no space left */
return;
length += chk->send_size;
length -= sizeof(struct sctp_data_chunk);
SCTP_BUF_LEN(m_notify) = 0;
if (sctp_stcb_is_feature_on(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVNSENDFAILEVNT)) {
ssfe = mtod(m_notify, struct sctp_send_failed_event *);
memset(ssfe, 0, length);
ssfe->ssfe_type = SCTP_SEND_FAILED_EVENT;
if (sent) {
ssfe->ssfe_flags = SCTP_DATA_SENT;
} else {
ssfe->ssfe_flags = SCTP_DATA_UNSENT;
}
length += chk->send_size;
length -= sizeof(struct sctp_data_chunk);
ssfe->ssfe_length = length;
ssfe->ssfe_error = error;
/* not exactly what the user sent in, but should be close :) */
bzero(&ssfe->ssfe_info, sizeof(ssfe->ssfe_info));
ssfe->ssfe_info.snd_sid = chk->rec.data.stream_number;
ssfe->ssfe_info.snd_flags = chk->rec.data.rcv_flags;
ssfe->ssfe_info.snd_ppid = chk->rec.data.payloadtype;
@ -2996,12 +3017,15 @@ sctp_notify_send_failed(struct sctp_tcb *stcb, uint8_t sent, uint32_t error,
SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_send_failed_event);
} else {
ssf = mtod(m_notify, struct sctp_send_failed *);
memset(ssf, 0, length);
ssf->ssf_type = SCTP_SEND_FAILED;
if (sent) {
ssf->ssf_flags = SCTP_DATA_SENT;
} else {
ssf->ssf_flags = SCTP_DATA_UNSENT;
}
length += chk->send_size;
length -= sizeof(struct sctp_data_chunk);
ssf->ssf_length = length;
ssf->ssf_error = error;
/* not exactly what the user sent in, but should be close :) */
@ -3086,16 +3110,16 @@ sctp_notify_send_failed2(struct sctp_tcb *stcb, uint32_t error,
/* no space left */
return;
}
length += sp->length;
SCTP_BUF_LEN(m_notify) = 0;
if (sctp_stcb_is_feature_on(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVNSENDFAILEVNT)) {
ssfe = mtod(m_notify, struct sctp_send_failed_event *);
memset(ssfe, 0, length);
ssfe->ssfe_type = SCTP_SEND_FAILED_EVENT;
ssfe->ssfe_flags = SCTP_DATA_UNSENT;
length += sp->length;
ssfe->ssfe_length = length;
ssfe->ssfe_error = error;
/* not exactly what the user sent in, but should be close :) */
bzero(&ssfe->ssfe_info, sizeof(ssfe->ssfe_info));
ssfe->ssfe_info.snd_sid = sp->stream;
if (sp->some_taken) {
ssfe->ssfe_info.snd_flags = SCTP_DATA_LAST_FRAG;
@ -3109,12 +3133,13 @@ sctp_notify_send_failed2(struct sctp_tcb *stcb, uint32_t error,
SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_send_failed_event);
} else {
ssf = mtod(m_notify, struct sctp_send_failed *);
memset(ssf, 0, length);
ssf->ssf_type = SCTP_SEND_FAILED;
ssf->ssf_flags = SCTP_DATA_UNSENT;
length += sp->length;
ssf->ssf_length = length;
ssf->ssf_error = error;
/* not exactly what the user sent in, but should be close :) */
bzero(&ssf->ssf_info, sizeof(ssf->ssf_info));
ssf->ssf_info.sinfo_stream = sp->stream;
ssf->ssf_info.sinfo_ssn = 0;
if (sp->some_taken) {
@ -3177,6 +3202,7 @@ sctp_notify_adaptation_layer(struct sctp_tcb *stcb)
return;
SCTP_BUF_LEN(m_notify) = 0;
sai = mtod(m_notify, struct sctp_adaptation_event *);
memset(sai, 0, sizeof(struct sctp_adaptation_event));
sai->sai_type = SCTP_ADAPTATION_INDICATION;
sai->sai_flags = 0;
sai->sai_length = sizeof(struct sctp_adaptation_event);
@ -3233,6 +3259,7 @@ sctp_notify_partial_delivery_indication(struct sctp_tcb *stcb, uint32_t error,
return;
SCTP_BUF_LEN(m_notify) = 0;
pdapi = mtod(m_notify, struct sctp_pdapi_event *);
memset(pdapi, 0, sizeof(struct sctp_pdapi_event));
pdapi->pdapi_type = SCTP_PARTIAL_DELIVERY_EVENT;
pdapi->pdapi_flags = 0;
pdapi->pdapi_length = sizeof(struct sctp_pdapi_event);
@ -3343,6 +3370,7 @@ sctp_notify_shutdown_event(struct sctp_tcb *stcb)
/* no space left */
return;
sse = mtod(m_notify, struct sctp_shutdown_event *);
memset(sse, 0, sizeof(struct sctp_shutdown_event));
sse->sse_type = SCTP_SHUTDOWN_EVENT;
sse->sse_flags = 0;
sse->sse_length = sizeof(struct sctp_shutdown_event);
@ -3394,6 +3422,7 @@ sctp_notify_sender_dry_event(struct sctp_tcb *stcb,
}
SCTP_BUF_LEN(m_notify) = 0;
event = mtod(m_notify, struct sctp_sender_dry_event *);
memset(event, 0, sizeof(struct sctp_sender_dry_event));
event->sender_dry_type = SCTP_SENDER_DRY_EVENT;
event->sender_dry_flags = 0;
event->sender_dry_length = sizeof(struct sctp_sender_dry_event);
@ -3426,7 +3455,6 @@ sctp_notify_stream_reset_add(struct sctp_tcb *stcb, uint16_t numberin, uint16_t
struct mbuf *m_notify;
struct sctp_queued_to_read *control;
struct sctp_stream_change_event *stradd;
int len;
if ((stcb == NULL) ||
(sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_STREAM_CHANGEEVNT))) {
@ -3439,25 +3467,20 @@ sctp_notify_stream_reset_add(struct sctp_tcb *stcb, uint16_t numberin, uint16_t
return;
}
stcb->asoc.peer_req_out = 0;
m_notify = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_NOWAIT, 1, MT_DATA);
m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_stream_change_event), 0, M_NOWAIT, 1, MT_DATA);
if (m_notify == NULL)
/* no space left */
return;
SCTP_BUF_LEN(m_notify) = 0;
len = sizeof(struct sctp_stream_change_event);
if (len > M_TRAILINGSPACE(m_notify)) {
/* never enough room */
sctp_m_freem(m_notify);
return;
}
stradd = mtod(m_notify, struct sctp_stream_change_event *);
memset(stradd, 0, sizeof(struct sctp_stream_change_event));
stradd->strchange_type = SCTP_STREAM_CHANGE_EVENT;
stradd->strchange_flags = flag;
stradd->strchange_length = len;
stradd->strchange_length = sizeof(struct sctp_stream_change_event);
stradd->strchange_assoc_id = sctp_get_associd(stcb);
stradd->strchange_instrms = numberin;
stradd->strchange_outstrms = numberout;
SCTP_BUF_LEN(m_notify) = len;
SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_stream_change_event);
SCTP_BUF_NEXT(m_notify) = NULL;
if (sctp_sbspace(&stcb->asoc, &stcb->sctp_socket->so_rcv) < SCTP_BUF_LEN(m_notify)) {
/* no space */
@ -3488,32 +3511,26 @@ sctp_notify_stream_reset_tsn(struct sctp_tcb *stcb, uint32_t sending_tsn, uint32
struct mbuf *m_notify;
struct sctp_queued_to_read *control;
struct sctp_assoc_reset_event *strasoc;
int len;
if ((stcb == NULL) ||
(sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_ASSOC_RESETEVNT))) {
/* event not enabled */
return;
}
m_notify = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_NOWAIT, 1, MT_DATA);
m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_assoc_reset_event), 0, M_NOWAIT, 1, MT_DATA);
if (m_notify == NULL)
/* no space left */
return;
SCTP_BUF_LEN(m_notify) = 0;
len = sizeof(struct sctp_assoc_reset_event);
if (len > M_TRAILINGSPACE(m_notify)) {
/* never enough room */
sctp_m_freem(m_notify);
return;
}
strasoc = mtod(m_notify, struct sctp_assoc_reset_event *);
memset(strasoc, 0, sizeof(struct sctp_assoc_reset_event));
strasoc->assocreset_type = SCTP_ASSOC_RESET_EVENT;
strasoc->assocreset_flags = flag;
strasoc->assocreset_length = len;
strasoc->assocreset_length = sizeof(struct sctp_assoc_reset_event);
strasoc->assocreset_assoc_id= sctp_get_associd(stcb);
strasoc->assocreset_local_tsn = sending_tsn;
strasoc->assocreset_remote_tsn = recv_tsn;
SCTP_BUF_LEN(m_notify) = len;
SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_assoc_reset_event);
SCTP_BUF_NEXT(m_notify) = NULL;
if (sctp_sbspace(&stcb->asoc, &stcb->sctp_socket->so_rcv) < SCTP_BUF_LEN(m_notify)) {
/* no space */
@ -3567,6 +3584,7 @@ sctp_notify_stream_reset(struct sctp_tcb *stcb,
return;
}
strreset = mtod(m_notify, struct sctp_stream_reset_event *);
memset(strreset, 0, len);
strreset->strreset_type = SCTP_STREAM_RESET_EVENT;
strreset->strreset_flags = flag;
strreset->strreset_length = len;
@ -3633,6 +3651,7 @@ sctp_notify_remote_error(struct sctp_tcb *stcb, uint16_t error, struct sctp_erro
}
SCTP_BUF_NEXT(m_notify) = NULL;
sre = mtod(m_notify, struct sctp_remote_error *);
memset(sre, 0, notif_len);
sre->sre_type = SCTP_REMOTE_ERROR;
sre->sre_flags = 0;
sre->sre_length = sizeof(struct sctp_remote_error);
@ -3708,7 +3727,7 @@ sctp_ulp_notify(uint32_t notification, struct sctp_tcb *stcb,
if (stcb->asoc.adaptation_needed && (stcb->asoc.adaptation_sent == 0)) {
sctp_notify_adaptation_layer(stcb);
}
if (stcb->asoc.peer_supports_auth == 0) {
if (stcb->asoc.auth_supported == 0) {
sctp_ulp_notify(SCTP_NOTIFY_NO_PEER_AUTH, stcb, 0,
NULL, so_locked);
}
@ -3797,7 +3816,7 @@ sctp_ulp_notify(uint32_t notification, struct sctp_tcb *stcb,
break;
case SCTP_NOTIFY_ASSOC_RESTART:
sctp_notify_assoc_change(SCTP_RESTART, stcb, error, NULL, 0, so_locked);
if (stcb->asoc.peer_supports_auth == 0) {
if (stcb->asoc.auth_supported == 0) {
sctp_ulp_notify(SCTP_NOTIFY_NO_PEER_AUTH, stcb, 0,
NULL, so_locked);
}
@ -4029,7 +4048,7 @@ sctp_abort_association(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
struct sockaddr *src, struct sockaddr *dst,
struct sctphdr *sh, struct mbuf *op_err,
#if defined(__FreeBSD__)
uint8_t use_mflowid, uint32_t mflowid,
uint8_t mflowtype, uint32_t mflowid,
#endif
uint32_t vrf_id, uint16_t port)
{
@ -4049,7 +4068,7 @@ sctp_abort_association(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
}
sctp_send_abort(m, iphlen, src, dst, sh, vtag, op_err,
#if defined(__FreeBSD__)
use_mflowid, mflowid,
mflowtype, mflowid,
#endif
vrf_id, port);
if (stcb != NULL) {
@ -4216,8 +4235,9 @@ void
sctp_handle_ootb(struct mbuf *m, int iphlen, int offset,
struct sockaddr *src, struct sockaddr *dst,
struct sctphdr *sh, struct sctp_inpcb *inp,
struct mbuf *cause,
#if defined(__FreeBSD__)
uint8_t use_mflowid, uint32_t mflowid,
uint8_t mflowtype, uint32_t mflowid,
#endif
uint32_t vrf_id, uint16_t port)
{
@ -4252,9 +4272,6 @@ sctp_handle_ootb(struct mbuf *m, int iphlen, int offset,
case SCTP_INIT:
contains_init_chunk = 1;
break;
case SCTP_COOKIE_ECHO:
/* We hit here only if the assoc is being freed */
return;
case SCTP_PACKET_DROPPED:
/* we don't respond to pkt-dropped */
return;
@ -4270,7 +4287,7 @@ sctp_handle_ootb(struct mbuf *m, int iphlen, int offset,
case SCTP_SHUTDOWN_ACK:
sctp_send_shutdown_complete2(src, dst, sh,
#if defined(__FreeBSD__)
use_mflowid, mflowid,
mflowtype, mflowid,
#endif
vrf_id, port);
return;
@ -4284,9 +4301,9 @@ sctp_handle_ootb(struct mbuf *m, int iphlen, int offset,
if ((SCTP_BASE_SYSCTL(sctp_blackhole) == 0) ||
((SCTP_BASE_SYSCTL(sctp_blackhole) == 1) &&
(contains_init_chunk == 0))) {
sctp_send_abort(m, iphlen, src, dst, sh, 0, NULL,
sctp_send_abort(m, iphlen, src, dst, sh, 0, cause,
#if defined(__FreeBSD__)
use_mflowid, mflowid,
mflowtype, mflowid,
#endif
vrf_id, port);
}
@ -5083,19 +5100,43 @@ sctp_append_to_readq(struct sctp_inpcb *inp,
*/
struct mbuf *
sctp_generate_invmanparam(int err)
sctp_generate_cause(uint16_t code, char *info)
{
/* Return a MBUF with a invalid mandatory parameter */
struct mbuf *m;
struct sctp_gen_error_cause *cause;
size_t info_len, len;
m = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr), 0, M_NOWAIT, 1, MT_DATA);
if (m) {
struct sctp_paramhdr *ph;
if ((code == 0) || (info == NULL)) {
return (NULL);
}
info_len = strlen(info);
len = sizeof(struct sctp_paramhdr) + info_len;
m = sctp_get_mbuf_for_msg(len, 0, M_NOWAIT, 1, MT_DATA);
if (m != NULL) {
SCTP_BUF_LEN(m) = len;
cause = mtod(m, struct sctp_gen_error_cause *);
cause->code = htons(code);
cause->length = htons((uint16_t)len);
memcpy(cause->info, info, info_len);
}
return (m);
}
SCTP_BUF_LEN(m) = sizeof(struct sctp_paramhdr);
ph = mtod(m, struct sctp_paramhdr *);
ph->param_length = htons(sizeof(struct sctp_paramhdr));
ph->param_type = htons(err);
struct mbuf *
sctp_generate_no_user_data_cause(uint32_t tsn)
{
struct mbuf *m;
struct sctp_error_no_user_data *no_user_data_cause;
size_t len;
len = sizeof(struct sctp_error_no_user_data);
m = sctp_get_mbuf_for_msg(len, 0, M_NOWAIT, 1, MT_DATA);
if (m != NULL) {
SCTP_BUF_LEN(m) = len;
no_user_data_cause = mtod(m, struct sctp_error_no_user_data *);
no_user_data_cause->cause.code = htons(SCTP_CAUSE_NO_USER_DATA);
no_user_data_cause->cause.length = htons((uint16_t)len);
no_user_data_cause->tsn = tsn; /* tsn is passed in as NBO */
}
return (m);
}
@ -5151,6 +5192,7 @@ sctp_release_pr_sctp_chunk(struct sctp_tcb *stcb, struct sctp_tmit_chunk *tp1,
int ret_sz = 0;
int notdone;
int do_wakeup_routine = 0;
#if defined(__APPLE__)
if (so_locked) {
sctp_lock_assert(SCTP_INP_SO(stcb->sctp_ep));
@ -5160,6 +5202,21 @@ sctp_release_pr_sctp_chunk(struct sctp_tcb *stcb, struct sctp_tmit_chunk *tp1,
#endif
stream = tp1->rec.data.stream_number;
seq = tp1->rec.data.stream_seq;
if (sent || !(tp1->rec.data.rcv_flags & SCTP_DATA_FIRST_FRAG)) {
stcb->asoc.abandoned_sent[0]++;
stcb->asoc.abandoned_sent[PR_SCTP_POLICY(tp1->flags)]++;
stcb->asoc.strmout[stream].abandoned_sent[0]++;
#if defined(SCTP_DETAILED_STR_STATS)
stcb->asoc.strmout[stream].abandoned_sent[PR_SCTP_POLICY(tp1->flags)]++;
#endif
} else {
stcb->asoc.abandoned_unsent[0]++;
stcb->asoc.abandoned_unsent[PR_SCTP_POLICY(tp1->flags)]++;
stcb->asoc.strmout[stream].abandoned_unsent[0]++;
#if defined(SCTP_DETAILED_STR_STATS)
stcb->asoc.strmout[stream].abandoned_unsent[PR_SCTP_POLICY(tp1->flags)]++;
#endif
}
do {
ret_sz += tp1->book_size;
if (tp1->data != NULL) {
@ -5210,7 +5267,7 @@ sctp_release_pr_sctp_chunk(struct sctp_tcb *stcb, struct sctp_tmit_chunk *tp1,
*/
TAILQ_FOREACH_SAFE(tp1, &stcb->asoc.send_queue, sctp_next, tp2) {
if ((tp1->rec.data.stream_number != stream) ||
(tp1->rec.data.stream_seq != seq)) {
(tp1->rec.data.stream_seq != seq)) {
break;
}
/* save to chk in case we have some on stream out
@ -5475,7 +5532,6 @@ sctp_find_ifa_by_addr(struct sockaddr *addr, uint32_t vrf_id, int holds_lock)
vrf = sctp_find_vrf(vrf_id);
if (vrf == NULL) {
stage_right:
if (holds_lock == 0)
SCTP_IPI_ADDR_RUNLOCK();
return (NULL);
@ -5496,15 +5552,6 @@ sctp_find_ifa_by_addr(struct sockaddr *addr, uint32_t vrf_id, int holds_lock)
return (NULL);
}
LIST_FOREACH(sctp_ifap, hash_head, next_bucket) {
if (sctp_ifap == NULL) {
#ifdef INVARIANTS
panic("Huh LIST_FOREACH corrupt");
goto stage_right;
#else
SCTP_PRINTF("LIST corrupt of sctp_ifap's?\n");
goto stage_right;
#endif
}
if (addr->sa_family != sctp_ifap->address.sa.sa_family)
continue;
#ifdef INET
@ -5651,7 +5698,7 @@ sctp_sorecvmsg(struct socket *so,
*/
struct sctp_inpcb *inp = NULL;
int my_len = 0;
int cp_len = 0, error = 0;
int cp_len = 0, error = 0;
struct sctp_queued_to_read *control = NULL, *ctl = NULL, *nxt = NULL;
struct mbuf *m = NULL;
struct sctp_tcb *stcb = NULL;
@ -6159,76 +6206,50 @@ sctp_sorecvmsg(struct socket *so,
entry->flgs = control->sinfo_flags;
}
#endif
if (fromlen && from) {
#ifdef HAVE_SA_LEN
cp_len = min((size_t)fromlen, (size_t)control->whoFrom->ro._l_addr.sa.sa_len);
#endif
if ((fromlen > 0) && (from != NULL)) {
union sctp_sockstore store;
size_t len;
switch (control->whoFrom->ro._l_addr.sa.sa_family) {
#ifdef INET6
case AF_INET6:
#ifndef HAVE_SA_LEN
cp_len = min((size_t)fromlen, sizeof(struct sockaddr_in6));
#endif
((struct sockaddr_in6 *)from)->sin6_port = control->port_from;
len = sizeof(struct sockaddr_in6);
store.sin6 = control->whoFrom->ro._l_addr.sin6;
store.sin6.sin6_port = control->port_from;
break;
#endif
#ifdef INET
case AF_INET:
#ifndef HAVE_SA_LEN
cp_len = min((size_t)fromlen, sizeof(struct sockaddr_in));
#ifdef INET6
if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) {
len = sizeof(struct sockaddr_in6);
in6_sin_2_v4mapsin6(&control->whoFrom->ro._l_addr.sin,
&store.sin6);
store.sin6.sin6_port = control->port_from;
} else {
len = sizeof(struct sockaddr_in);
store.sin = control->whoFrom->ro._l_addr.sin;
store.sin.sin_port = control->port_from;
}
#else
len = sizeof(struct sockaddr_in);
store.sin = control->whoFrom->ro._l_addr.sin;
store.sin.sin_port = control->port_from;
#endif
((struct sockaddr_in *)from)->sin_port = control->port_from;
break;
#endif
#if defined(__Userspace__)
case AF_CONN:
#ifndef HAVE_SA_LEN
cp_len = min((size_t)fromlen, sizeof(struct sockaddr_conn));
#endif
((struct sockaddr_conn *)from)->sconn_port = control->port_from;
len = sizeof(struct sockaddr_conn);
store.sconn = control->whoFrom->ro._l_addr.sconn;
store.sconn.sconn_port = control->port_from;
break;
#endif
default:
#ifndef HAVE_SA_LEN
cp_len = min((size_t)fromlen, sizeof(struct sockaddr));
#endif
len = 0;
break;
}
memcpy(from, &control->whoFrom->ro._l_addr, cp_len);
#if defined(INET) && defined(INET6)
if ((sctp_is_feature_on(inp,SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) &&
(from->sa_family == AF_INET) &&
((size_t)fromlen >= sizeof(struct sockaddr_in6))) {
struct sockaddr_in *sin;
struct sockaddr_in6 sin6;
sin = (struct sockaddr_in *)from;
bzero(&sin6, sizeof(sin6));
sin6.sin6_family = AF_INET6;
#ifdef HAVE_SIN6_LEN
sin6.sin6_len = sizeof(struct sockaddr_in6);
#endif
#if defined(__Userspace_os_FreeBSD) || defined(__Userspace_os_Darwin) || defined(__Userspace_os_Windows)
((uint32_t *)&sin6.sin6_addr)[2] = htonl(0xffff);
bcopy(&sin->sin_addr,
&(((uint32_t *)&sin6.sin6_addr)[3]),
sizeof(uint32_t));
#elif defined(__Windows__)
((uint32_t *)&sin6.sin6_addr)[2] = htonl(0xffff);
bcopy(&sin->sin_addr,
&((uint32_t *)&sin6.sin6_addr)[3],
sizeof(uint32_t));
#else
sin6.sin6_addr.s6_addr32[2] = htonl(0xffff);
bcopy(&sin->sin_addr,
&sin6.sin6_addr.s6_addr32[3],
sizeof(sin6.sin6_addr.s6_addr32[3]));
#endif
sin6.sin6_port = sin->sin_port;
memcpy(from, &sin6, sizeof(struct sockaddr_in6));
}
#endif
memcpy(from, &store, min((size_t)fromlen, len));
#if defined(SCTP_EMBEDDED_V6_SCOPE)
#ifdef INET6
{
@ -6527,13 +6548,13 @@ sctp_sorecvmsg(struct socket *so,
SOCKBUF_LOCK(&so->so_rcv);
hold_sblock = 1;
}
#if defined(__APPLE__)
sbunlock(&so->so_rcv, 1);
#endif
if ((copied_so_far) && (control->length == 0) &&
(sctp_is_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE))) {
goto release;
}
#if defined(__APPLE__)
sbunlock(&so->so_rcv, 1);
#endif
if (so->so_rcv.sb_cc <= control->held_length) {
error = sbwait(&so->so_rcv);
if (error) {
@ -6775,9 +6796,7 @@ struct mbuf *
sctp_m_free(struct mbuf *m)
{
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) {
if (SCTP_BUF_IS_EXTENDED(m)) {
sctp_log_mb(m, SCTP_MBUF_IFREE);
}
sctp_log_mb(m, SCTP_MBUF_IFREE);
}
return (m_free(m));
}
@ -6882,9 +6901,12 @@ sctp_soreceive( struct socket *so,
#if defined(__APPLE__)
SCTP_SOCKET_LOCK(so, 1);
#endif
if (filling_sinfo) {
memset(&sinfo, 0, sizeof(struct sctp_extrcvinfo));
}
error = sctp_sorecvmsg(so, uio, mp0, from, fromlen, flagsp,
(struct sctp_sndrcvinfo *)&sinfo, filling_sinfo);
if ((controlp) && (filling_sinfo)) {
if (controlp != NULL) {
/* copy back the sinfo in a CMSG format */
if (filling_sinfo)
*controlp = sctp_build_ctl_nchunk(inp,
@ -7233,7 +7255,7 @@ sctp_bindx_add_address(struct socket *so, struct sctp_inpcb *inp,
uint32_t vrf_id, int *error, void *p)
{
struct sockaddr *addr_touse;
#ifdef INET6
#if defined(INET) && defined(INET6)
struct sockaddr_in sin;
#endif
#ifdef SCTP_MVRF
@ -7263,7 +7285,10 @@ sctp_bindx_add_address(struct socket *so, struct sctp_inpcb *inp,
addr_touse = sa;
#ifdef INET6
if (sa->sa_family == AF_INET6) {
#ifdef INET
struct sockaddr_in6 *sin6;
#endif
#ifdef HAVE_SA_LEN
if (sa->sa_len != sizeof(struct sockaddr_in6)) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
@ -7277,6 +7302,7 @@ sctp_bindx_add_address(struct socket *so, struct sctp_inpcb *inp,
*error = EINVAL;
return;
}
#ifdef INET
sin6 = (struct sockaddr_in6 *)addr_touse;
if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
@ -7289,6 +7315,7 @@ sctp_bindx_add_address(struct socket *so, struct sctp_inpcb *inp,
in6_sin6_2_sin(&sin, sin6);
addr_touse = (struct sockaddr *)&sin;
}
#endif
}
#endif
#ifdef INET
@ -7383,7 +7410,7 @@ sctp_bindx_delete_address(struct sctp_inpcb *inp,
uint32_t vrf_id, int *error)
{
struct sockaddr *addr_touse;
#ifdef INET6
#if defined(INET) && defined(INET6)
struct sockaddr_in sin;
#endif
#ifdef SCTP_MVRF
@ -7413,7 +7440,10 @@ sctp_bindx_delete_address(struct sctp_inpcb *inp,
addr_touse = sa;
#ifdef INET6
if (sa->sa_family == AF_INET6) {
#ifdef INET
struct sockaddr_in6 *sin6;
#endif
#ifdef HAVE_SA_LEN
if (sa->sa_len != sizeof(struct sockaddr_in6)) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
@ -7427,6 +7457,7 @@ sctp_bindx_delete_address(struct sctp_inpcb *inp,
*error = EINVAL;
return;
}
#ifdef INET
sin6 = (struct sockaddr_in6 *)addr_touse;
if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
@ -7439,6 +7470,7 @@ sctp_bindx_delete_address(struct sctp_inpcb *inp,
in6_sin6_2_sin(&sin, sin6);
addr_touse = (struct sockaddr *)&sin;
}
#endif
}
#endif
#ifdef INET
@ -7539,11 +7571,17 @@ sctp_local_addr_count(struct sctp_tcb *stcb)
if (ipv4_addr_legal) {
struct sockaddr_in *sin;
sin = (struct sockaddr_in *)&sctp_ifa->address.sa;
sin = &sctp_ifa->address.sin;
if (sin->sin_addr.s_addr == 0) {
/* skip unspecified addrs */
continue;
}
#if defined(__FreeBSD__)
if (prison_check_ip4(stcb->sctp_ep->ip_inp.inp.inp_cred,
&sin->sin_addr) != 0) {
continue;
}
#endif
if ((ipv4_local_scope == 0) &&
(IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))) {
continue;
@ -7563,10 +7601,16 @@ sctp_local_addr_count(struct sctp_tcb *stcb)
#if defined(SCTP_EMBEDDED_V6_SCOPE) && !defined(SCTP_KAME)
struct sockaddr_in6 lsa6;
#endif
sin6 = (struct sockaddr_in6 *)&sctp_ifa->address.sa;
sin6 = &sctp_ifa->address.sin6;
if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
continue;
}
#if defined(__FreeBSD__)
if (prison_check_ip6(stcb->sctp_ep->ip_inp.inp.inp_cred,
&sin6->sin6_addr) != 0) {
continue;
}
#endif
if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
if (local_scope == 0)
continue;
@ -7693,7 +7737,8 @@ sctp_log_trace(uint32_t subsys, const char *str SCTP_UNUSED, uint32_t a, uint32_
#if defined(__FreeBSD__)
#if __FreeBSD_version >= 800044
static void
sctp_recv_udp_tunneled_packet(struct mbuf *m, int off, struct inpcb *ignored)
sctp_recv_udp_tunneled_packet(struct mbuf *m, int off, struct inpcb *ignored,
const struct sockaddr *sa SCTP_UNUSED, void *ctx SCTP_UNUSED)
{
struct ip *iph;
#ifdef INET6
@ -7828,7 +7873,7 @@ sctp_over_udp_start(void)
}
/* Call the special UDP hook. */
if ((ret = udp_set_kernel_tunneling(SCTP_BASE_INFO(udp4_tun_socket),
sctp_recv_udp_tunneled_packet))) {
sctp_recv_udp_tunneled_packet, NULL))) {
sctp_over_udp_stop();
return (ret);
}
@ -7852,7 +7897,7 @@ sctp_over_udp_start(void)
}
/* Call the special UDP hook. */
if ((ret = udp_set_kernel_tunneling(SCTP_BASE_INFO(udp6_tun_socket),
sctp_recv_udp_tunneled_packet))) {
sctp_recv_udp_tunneled_packet, NULL))) {
sctp_over_udp_stop();
return (ret);
}

View File

@ -32,7 +32,7 @@
#ifdef __FreeBSD__
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: head/sys/netinet/sctputil.h 243186 2012-11-17 20:04:04Z tuexen $");
__FBSDID("$FreeBSD: head/sys/netinet/sctputil.h 276914 2015-01-10 20:49:57Z tuexen $");
#endif
#ifndef _NETINET_SCTP_UTIL_H_
@ -146,9 +146,11 @@ struct sctp_paramhdr *
sctp_get_next_param(struct mbuf *, int,
struct sctp_paramhdr *, int);
int sctp_add_pad_tombuf(struct mbuf *, int);
struct mbuf *
sctp_add_pad_tombuf(struct mbuf *, int);
int sctp_pad_lastmbuf(struct mbuf *, int, struct mbuf *);
struct mbuf *
sctp_pad_lastmbuf(struct mbuf *, int, struct mbuf *);
void sctp_ulp_notify(uint32_t, struct sctp_tcb *, uint32_t, void *, int
#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
@ -202,6 +204,7 @@ sctp_abort_an_association(struct sctp_inpcb *, struct sctp_tcb *,
void sctp_handle_ootb(struct mbuf *, int, int,
struct sockaddr *, struct sockaddr *,
struct sctphdr *, struct sctp_inpcb *,
struct mbuf *,
#if defined(__FreeBSD__)
uint8_t, uint32_t,
#endif
@ -239,10 +242,10 @@ sctp_recover_scope(struct sockaddr_in6 *, struct sockaddr_in6 *);
} while (0)
#else
#define sctp_recover_scope_mac(addr, store) do { \
if ((addr->sin6_family == AF_INET6) && \
(IN6_IS_SCOPE_LINKLOCAL(&addr->sin6_addr))) { \
if ((addr->sin6_family == AF_INET6) && \
(IN6_IS_SCOPE_LINKLOCAL(&addr->sin6_addr))) { \
*store = *addr; \
if (addr->sin6_scope_id == 0) { \
if (addr->sin6_scope_id == 0) { \
if (!in6_recoverscope(store, &store->sin6_addr, \
NULL)) { \
addr = store; \
@ -251,7 +254,7 @@ sctp_recover_scope(struct sockaddr_in6 *, struct sockaddr_in6 *);
in6_clearscope(&addr->sin6_addr); \
addr = store; \
} \
} \
} \
} while (0)
#endif
#endif
@ -269,7 +272,8 @@ sctp_release_pr_sctp_chunk(struct sctp_tcb *, struct sctp_tmit_chunk *,
#endif
);
struct mbuf *sctp_generate_invmanparam(int);
struct mbuf *sctp_generate_cause(uint16_t, char *);
struct mbuf *sctp_generate_no_user_data_cause(uint32_t);
void sctp_bindx_add_address(struct socket *so, struct sctp_inpcb *inp,
struct sockaddr *sa, sctp_assoc_t assoc_id,
@ -289,42 +293,42 @@ sctp_free_bufspace(struct sctp_tcb *, struct sctp_association *,
#define sctp_free_bufspace(stcb, asoc, tp1, chk_cnt) \
do { \
if (tp1->data != NULL) { \
atomic_subtract_int(&((asoc)->chunks_on_out_queue), chk_cnt); \
atomic_subtract_int(&((asoc)->chunks_on_out_queue), chk_cnt); \
if ((asoc)->total_output_queue_size >= tp1->book_size) { \
atomic_subtract_int(&((asoc)->total_output_queue_size), tp1->book_size); \
} else { \
(asoc)->total_output_queue_size = 0; \
} \
if (stcb->sctp_socket && ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || \
(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL))) { \
if (stcb->sctp_socket && ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || \
(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL))) { \
if (stcb->sctp_socket->so_snd.sb_cc >= tp1->book_size) { \
atomic_subtract_int(&((stcb)->sctp_socket->so_snd.sb_cc), tp1->book_size); \
} else { \
stcb->sctp_socket->so_snd.sb_cc = 0; \
} \
} \
} \
} \
} while (0)
#endif
#define sctp_free_spbufspace(stcb, asoc, sp) \
do { \
if (sp->data != NULL) { \
if (sp->data != NULL) { \
if ((asoc)->total_output_queue_size >= sp->length) { \
atomic_subtract_int(&(asoc)->total_output_queue_size, sp->length); \
} else { \
(asoc)->total_output_queue_size = 0; \
} \
if (stcb->sctp_socket && ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || \
(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL))) { \
if (stcb->sctp_socket && ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || \
(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL))) { \
if (stcb->sctp_socket->so_snd.sb_cc >= sp->length) { \
atomic_subtract_int(&stcb->sctp_socket->so_snd.sb_cc,sp->length); \
} else { \
stcb->sctp_socket->so_snd.sb_cc = 0; \
} \
} \
} \
} \
} while (0)
#define sctp_snd_sb_alloc(stcb, sz) \
@ -365,9 +369,14 @@ void sctp_log_strm_del_alt(struct sctp_tcb *stcb, uint32_t, uint16_t, uint16_t,
void sctp_log_nagle_event(struct sctp_tcb *stcb, int action);
#ifdef SCTP_MBUF_LOGGING
void
sctp_log_mb(struct mbuf *m, int from);
void
sctp_log_mbc(struct mbuf *m, int from);
#endif
void
sctp_sblog(struct sockbuf *sb,
struct sctp_tcb *stcb, int from, int incr);
@ -385,7 +394,6 @@ void sctp_log_lock(struct sctp_inpcb *inp, struct sctp_tcb *stcb, uint8_t from);
void sctp_log_maxburst(struct sctp_tcb *stcb, struct sctp_nets *, int, int, uint8_t);
void sctp_log_block(uint8_t, struct sctp_association *, int);
void sctp_log_rwnd(uint8_t, uint32_t, uint32_t, uint32_t);
void sctp_log_mbcnt(uint8_t, uint32_t, uint32_t, uint32_t, uint32_t);
void sctp_log_rwnd_set(uint8_t, uint32_t, uint32_t, uint32_t, uint32_t);
int sctp_fill_stat_log(void *, size_t *);
void sctp_log_fr(uint32_t, uint32_t, uint32_t, int);

View File

@ -32,7 +32,7 @@
#ifdef __FreeBSD__
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: head/sys/netinet6/sctp6_usrreq.c 257555 2013-11-02 20:12:19Z tuexen $");
__FBSDID("$FreeBSD: head/sys/netinet6/sctp6_usrreq.c 276914 2015-01-10 20:49:57Z tuexen $");
#endif
#include <netinet/sctp_os.h>
@ -79,6 +79,7 @@ extern struct protosw inetsw[];
int ip6_v6only=0;
#endif
#if defined(__Userspace__)
#ifdef INET
void
in6_sin6_2_sin(struct sockaddr_in *sin, struct sockaddr_in6 *sin6)
{
@ -96,7 +97,6 @@ in6_sin6_2_sin(struct sockaddr_in *sin, struct sockaddr_in6 *sin6)
temp = temp << 16;
temp = temp | sin6->sin6_addr.s6_addr16[6];
sin->sin_addr.s_addr = temp;
sctp_print_address((struct sockaddr*)sin);
#else
sin->sin_addr.s_addr = sin6->sin6_addr.s6_addr32[3];
#endif
@ -113,6 +113,29 @@ in6_sin6_2_sin_in_sock(struct sockaddr *nam)
sin_p = (struct sockaddr_in *)nam;
in6_sin6_2_sin(sin_p, &sin6);
}
void
in6_sin_2_v4mapsin6(struct sockaddr_in *sin, struct sockaddr_in6 *sin6)
{
bzero(sin6, sizeof(struct sockaddr_in6));
sin6->sin6_family = AF_INET6;
#ifdef HAVE_SIN6_LEN
sin6->sin6_len = sizeof(struct sockaddr_in6);
#endif
sin6->sin6_port = sin->sin_port;
#if defined(__Userspace_os_Windows)
((uint32_t *)&sin6->sin6_addr)[0] = 0;
((uint32_t *)&sin6->sin6_addr)[1] = 0;
((uint32_t *)&sin6->sin6_addr)[2] = htonl(0xffff);
((uint32_t *)&sin6->sin6_addr)[3] = sin->sin_addr.s_addr;
#else
sin6->sin6_addr.s6_addr32[0] = 0;
sin6->sin6_addr.s6_addr32[1] = 0;
sin6->sin6_addr.s6_addr32[2] = htonl(0xffff);
sin6->sin6_addr.s6_addr32[3] = sin->sin_addr.s_addr;
#endif
}
#endif
#endif
#if !defined(__Userspace__)
@ -139,7 +162,7 @@ sctp6_input(struct mbuf **i_pak, int *offp, int proto)
#endif
#if defined(__FreeBSD__)
uint32_t mflowid;
uint8_t use_mflowid;
uint8_t mflowtype;
#endif
#if !(defined(__APPLE__) || defined (__FreeBSD__))
uint16_t port = 0;
@ -163,13 +186,7 @@ sctp6_input(struct mbuf **i_pak, int *offp, int proto)
#ifdef SCTP_MBUF_LOGGING
/* Log in any input mbufs */
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) {
struct mbuf *mat;
for (mat = m; mat; mat = SCTP_BUF_NEXT(mat)) {
if (SCTP_BUF_IS_EXTENDED(mat)) {
sctp_log_mb(mat, SCTP_MBUF_INPUT);
}
}
sctp_log_mbc(m, SCTP_MBUF_INPUT);
}
#endif
#ifdef SCTP_PACKET_LOGGING
@ -214,14 +231,9 @@ sctp6_input(struct mbuf **i_pak, int *offp, int proto)
m->m_pkthdr.csum_flags);
#endif
#if defined(__FreeBSD__)
if (m->m_flags & M_FLOWID) {
mflowid = m->m_pkthdr.flowid;
use_mflowid = 1;
} else {
mflowid = 0;
use_mflowid = 0;
}
#endif
mflowid = m->m_pkthdr.flowid;
mflowtype = M_HASHTYPE_GET(m);
#endif
SCTP_STAT_INCR(sctps_recvpackets);
SCTP_STAT_INCR_COUNTER64(sctps_inpackets);
/* Get IP, SCTP, and first chunk header together in the first mbuf. */
@ -246,7 +258,7 @@ sctp6_input(struct mbuf **i_pak, int *offp, int proto)
#if defined(__APPLE__)
/* XXX: This code should also be used on Apple */
#endif
if (in6_setscope(&src.sin6_addr, m->m_pkthdr.rcvif, NULL) != 0) {
if (in6_setscope(&src.sin6_addr, m->m_pkthdr.rcvif, NULL) != 0) {
goto out;
}
#endif
@ -261,13 +273,7 @@ sctp6_input(struct mbuf **i_pak, int *offp, int proto)
#if defined(__APPLE__)
/* XXX: This code should also be used on Apple */
#endif
if (in6_setscope(&dst.sin6_addr, m->m_pkthdr.rcvif, NULL) != 0) {
goto out;
}
#endif
#ifdef __FreeBSD__
if (faithprefix_p != NULL && (*faithprefix_p) (&dst.sin6_addr)) {
/* XXX send icmp6 host/port unreach? */
if (in6_setscope(&dst.sin6_addr, m->m_pkthdr.rcvif, NULL) != 0) {
goto out;
}
#endif
@ -318,7 +324,7 @@ sctp6_input(struct mbuf **i_pak, int *offp, int proto)
#endif
ecn_bits,
#if defined(__FreeBSD__)
use_mflowid, mflowid,
mflowtype, mflowid,
#endif
vrf_id, port);
out:
@ -1184,7 +1190,7 @@ sctp6_connect(struct socket *so, struct mbuf *nam, struct proc *p)
#ifdef INET
struct in6pcb *inp6;
struct sockaddr_in6 *sin6;
struct sockaddr_storage ss;
union sctp_sockstore store;
#endif
#ifdef INET
@ -1273,8 +1279,8 @@ sctp6_connect(struct socket *so, struct mbuf *nam, struct proc *p)
}
if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
/* convert v4-mapped into v4 addr */
in6_sin6_2_sin((struct sockaddr_in *)&ss, sin6);
addr = (struct sockaddr *)&ss;
in6_sin6_2_sin(&store.sin, sin6);
addr = &store.sa;
}
#endif /* INET */
/* Now do we connect? */
@ -1424,7 +1430,7 @@ sctp6_getaddr(struct socket *so, struct mbuf *nam)
if (laddr->ifa->address.sa.sa_family == AF_INET6) {
struct sockaddr_in6 *sin_a;
sin_a = (struct sockaddr_in6 *)&laddr->ifa->address.sin6;
sin_a = &laddr->ifa->address.sin6;
sin6->sin6_addr = sin_a->sin6_addr;
fnd = 1;
break;
@ -1544,8 +1550,13 @@ sctp6_peeraddr(struct socket *so, struct mbuf *nam)
}
#ifdef SCTP_EMBEDDED_V6_SCOPE
#ifdef SCTP_KAME
if ((error = sa6_recoverscope(sin6)) != 0)
if ((error = sa6_recoverscope(sin6)) != 0) {
#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
SCTP_FREE_SONAME(sin6);
#endif
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, error);
return (error);
}
#else
in6_recoverscope(sin6, &sin6->sin6_addr, NULL);
#endif /* SCTP_KAME */
@ -1729,7 +1740,7 @@ struct pr_usrreqs sctp6_usrreqs = {
.pru_sockaddr = sctp6_in6getaddr,
.pru_sosend = sctp_sosend,
.pru_soreceive = sctp_soreceive,
.pru_sopoll = sopoll
.pru_sopoll = sopoll
#elif defined(__Windows__)
sctp6_abort,
sctp_accept,

View File

@ -39,7 +39,11 @@ __FBSDID("$FreeBSD: head/sys/netinet6/sctp6_var.h 243186 2012-11-17 20:04:04Z tu
#define _NETINET6_SCTP6_VAR_H_
#if defined(__Userspace__)
extern void in6_sin6_2_sin(struct sockaddr_in *, struct sockaddr_in6 *sin6);
#ifdef INET
extern void in6_sin6_2_sin(struct sockaddr_in *, struct sockaddr_in6 *);
extern void in6_sin6_2_sin_in_sock(struct sockaddr *);
extern void in6_sin_2_v4mapsin6(struct sockaddr_in *, struct sockaddr_in6 *);
#endif
#endif
#if defined(_KERNEL)
@ -73,10 +77,9 @@ int sctp6_output(struct sctp_inpcb *, struct mbuf *, struct sockaddr *,
void sctp6_ctlinput(int, struct sockaddr *, void *);
#endif
#if !(defined(__FreeBSD__) || defined(__APPLE__))
extern void in6_sin_2_v4mapsin6(struct sockaddr_in *sin,
struct sockaddr_in6 *sin6);
extern void in6_sin6_2_sin(struct sockaddr_in *, struct sockaddr_in6 *sin6);
extern void in6_sin6_2_sin_in_sock(struct sockaddr *nam);
extern void in6_sin_2_v4mapsin6(struct sockaddr_in *, struct sockaddr_in6 *);
extern void in6_sin6_2_sin(struct sockaddr_in *, struct sockaddr_in6 *);
extern void in6_sin6_2_sin_in_sock(struct sockaddr *);
#endif
extern void sctp6_notify(struct sctp_inpcb *, struct icmp6_hdr *,
struct sctphdr *, struct sockaddr *,

View File

@ -107,11 +107,4 @@ extern u_short ip_id;
/* necessary for sctp_pcb.c */
extern int ip_defttl;
/* dummy definitions used (temporarily?) for inpcb userspace port */
/* called in sctp_usrreq.c */
#define in6_sin_2_v4mapsin6(arg1, arg2) /* STUB */
#endif

View File

@ -54,6 +54,7 @@ struct icmphdr {
};
#if defined(__Userspace_os_Windows)
#pragma pack (push, 1)
struct icmp6_hdr {
u_int8_t icmp6_type;
u_int8_t icmp6_code;
@ -63,7 +64,8 @@ struct icmp6_hdr {
u_int16_t icmp6_un_data16[2];
u_int8_t icmp6_un_data8[4];
} icmp6_dataun;
} __packed;
};
#pragma pack()
#define icmp6_data32 icmp6_dataun.icmp6_un_data32
#define icmp6_mtu icmp6_data32[0]

View File

@ -46,8 +46,8 @@
#elif defined(SCTP_STDINT_INCLUDE)
#include SCTP_STDINT_INCLUDE
#else
#define uint32_t unsigned __int32
#define uint64_t unsigned __int64
#define uint32_t unsigned __int32
#define uint64_t unsigned __int64
#endif
#include <winsock2.h>
#endif

View File

@ -54,7 +54,7 @@ struct sctp_route {
* retransmission behavior and are included in the routing structure.
*/
struct sctp_rt_metrics_lite {
u_long rmx_mtu; /* MTU for this path */
uint32_t rmx_mtu; /* MTU for this path */
#if 0
u_long rmx_expire; /* lifetime for route, e.g. redirect */
u_long rmx_pksent; /* packets sent using this route */

View File

@ -46,7 +46,9 @@
#define __FAVOR_BSD /* (on Ubuntu at least) enables UDP header field names like BSD in RFC 768 */
#endif
#if !defined (__Userspace_os_Windows)
#if defined INET || defined INET6
#include <netinet/udp.h>
#endif
#include <arpa/inet.h>
#else
#include <user_socketvar.h>
@ -708,6 +710,7 @@ userspace_sctp_sendmsg(struct socket *so,
struct uio auio;
struct iovec iov[1];
memset(sinfo, 0, sizeof(struct sctp_sndrcvinfo));
sinfo->sinfo_ppid = ppid;
sinfo->sinfo_flags = flags;
sinfo->sinfo_stream = stream_no;
@ -1377,7 +1380,7 @@ sbreserve_locked(struct sockbuf *sb, u_long cc, struct socket *so)
{
SOCKBUF_LOCK_ASSERT(sb);
sb->sb_mbmax = (u_int)min(cc * sb_efficiency, sb_max);
sb->sb_hiwat = cc;
sb->sb_hiwat = (u_int)cc;
if (sb->sb_lowat > (int)sb->sb_hiwat)
sb->sb_lowat = (int)sb->sb_hiwat;
return (1);
@ -1933,7 +1936,7 @@ usrsctp_get_non_blocking(struct socket *so)
return (-1);
}
SOCK_LOCK(so);
if (so->so_state | SS_NBIO) {
if (so->so_state & SS_NBIO) {
result = 1;
} else {
result = 0;
@ -2341,6 +2344,12 @@ userspace_getsockopt(struct socket *so, int level, int option_name,
return (usrsctp_getsockopt(so, level, option_name, option_value, option_len));
}
int
usrsctp_set_ulpinfo(struct socket *so, void *ulp_info)
{
return (register_ulp_info(so, ulp_info));
}
int
usrsctp_bindx(struct socket *so, struct sockaddr *addrs, int addrcnt, int flags)
{
@ -2446,7 +2455,7 @@ usrsctp_bindx(struct socket *so, struct sockaddr *addrs, int addrcnt, int flags)
for (i = 0; i < addrcnt; i++) {
#ifndef HAVE_SA_LEN
size_t sa_len;
#endif
#endif
memset(gaddrs, 0, argsz);
gaddrs->sget_assoc_id = 0;
#ifdef HAVE_SA_LEN
@ -2478,6 +2487,7 @@ usrsctp_bindx(struct socket *so, struct sockaddr *addrs, int addrcnt, int flags)
* first address has that port to make sure it fails or
* succeeds correctly.
*/
#if defined(INET) || defined(INET6)
if ((i == 0) && (sport != 0)) {
switch (gaddrs->addr->sa_family) {
#ifdef INET
@ -2494,6 +2504,7 @@ usrsctp_bindx(struct socket *so, struct sockaddr *addrs, int addrcnt, int flags)
#endif
}
}
#endif
if (usrsctp_setsockopt(so, IPPROTO_SCTP, flags, gaddrs, (socklen_t)argsz) != 0) {
free(gaddrs);
return (-1);
@ -2551,6 +2562,7 @@ usrsctp_connectx(struct socket *so,
return (-1);
}
#endif
#ifdef INET
if (IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)at)->sin6_addr)) {
in6_sin6_2_sin((struct sockaddr_in *)cpto, (struct sockaddr_in6 *)at);
cpto = ((caddr_t)cpto + sizeof(struct sockaddr_in));
@ -2560,6 +2572,11 @@ usrsctp_connectx(struct socket *so,
cpto = ((caddr_t)cpto + sizeof(struct sockaddr_in6));
len += sizeof(struct sockaddr_in6);
}
#else
memcpy(cpto, at, sizeof(struct sockaddr_in6));
cpto = ((caddr_t)cpto + sizeof(struct sockaddr_in6));
len += sizeof(struct sockaddr_in6);
#endif
at = (struct sockaddr *)((caddr_t)at + sizeof(struct sockaddr_in6));
break;
#endif
@ -2982,7 +2999,7 @@ void sctp_userspace_ip6_output(int *result, struct mbuf *o_pak,
memset((void *)&dst, 0, sizeof(struct sockaddr_in6));
dst.sin6_family = AF_INET6;
dst.sin6_addr = ip6->ip6_dst;
#ifdef HAVE_SIN6_LEN
#ifdef HAVE_SIN6_LEN
dst.sin6_len = sizeof(struct sockaddr_in6);
#endif
@ -3152,7 +3169,7 @@ usrsctp_dumppacket(void *buf, size_t len, int outbound)
strncpy_s(dump_buf + pos, strlen(HEADER) + 1, HEADER, strlen(HEADER));
#else
strcpy(dump_buf + pos, HEADER);
#endif
#endif
pos += strlen(HEADER);
packet = (char *)buf;
for (i = 0; i < len; i++) {
@ -3243,6 +3260,12 @@ USRSCTP_SYSCTL_SET_DEF(sctp_recvspace)
USRSCTP_SYSCTL_SET_DEF(sctp_auto_asconf)
USRSCTP_SYSCTL_SET_DEF(sctp_multiple_asconfs)
USRSCTP_SYSCTL_SET_DEF(sctp_ecn_enable)
USRSCTP_SYSCTL_SET_DEF(sctp_pr_enable)
USRSCTP_SYSCTL_SET_DEF(sctp_auth_enable)
USRSCTP_SYSCTL_SET_DEF(sctp_asconf_enable)
USRSCTP_SYSCTL_SET_DEF(sctp_reconfig_enable)
USRSCTP_SYSCTL_SET_DEF(sctp_nrsack_enable)
USRSCTP_SYSCTL_SET_DEF(sctp_pktdrop_enable)
USRSCTP_SYSCTL_SET_DEF(sctp_strict_sacks)
#if !defined(SCTP_WITH_NO_CSUM)
USRSCTP_SYSCTL_SET_DEF(sctp_no_csum_on_loopback)
@ -3274,10 +3297,7 @@ USRSCTP_SYSCTL_SET_DEF(sctp_add_more_threshold)
USRSCTP_SYSCTL_SET_DEF(sctp_nr_outgoing_streams_default)
USRSCTP_SYSCTL_SET_DEF(sctp_cmt_on_off)
USRSCTP_SYSCTL_SET_DEF(sctp_cmt_use_dac)
USRSCTP_SYSCTL_SET_DEF(sctp_nr_sack_on_off)
USRSCTP_SYSCTL_SET_DEF(sctp_use_cwnd_based_maxburst)
USRSCTP_SYSCTL_SET_DEF(sctp_asconf_auth_nochk)
USRSCTP_SYSCTL_SET_DEF(sctp_auth_disable)
USRSCTP_SYSCTL_SET_DEF(sctp_nat_friendly)
USRSCTP_SYSCTL_SET_DEF(sctp_L2_abc_variable)
USRSCTP_SYSCTL_SET_DEF(sctp_mbuf_threshold_count)
@ -3297,6 +3317,7 @@ USRSCTP_SYSCTL_SET_DEF(sctp_udp_tunneling_port)
USRSCTP_SYSCTL_SET_DEF(sctp_enable_sack_immediately)
USRSCTP_SYSCTL_SET_DEF(sctp_vtag_time_wait)
USRSCTP_SYSCTL_SET_DEF(sctp_blackhole)
USRSCTP_SYSCTL_SET_DEF(sctp_diag_info_code)
USRSCTP_SYSCTL_SET_DEF(sctp_fr_max_burst_default)
USRSCTP_SYSCTL_SET_DEF(sctp_path_pf_threshold)
USRSCTP_SYSCTL_SET_DEF(sctp_default_ss_module)
@ -3321,6 +3342,12 @@ USRSCTP_SYSCTL_GET_DEF(sctp_recvspace)
USRSCTP_SYSCTL_GET_DEF(sctp_auto_asconf)
USRSCTP_SYSCTL_GET_DEF(sctp_multiple_asconfs)
USRSCTP_SYSCTL_GET_DEF(sctp_ecn_enable)
USRSCTP_SYSCTL_GET_DEF(sctp_pr_enable)
USRSCTP_SYSCTL_GET_DEF(sctp_auth_enable)
USRSCTP_SYSCTL_GET_DEF(sctp_asconf_enable)
USRSCTP_SYSCTL_GET_DEF(sctp_reconfig_enable)
USRSCTP_SYSCTL_GET_DEF(sctp_nrsack_enable)
USRSCTP_SYSCTL_GET_DEF(sctp_pktdrop_enable)
USRSCTP_SYSCTL_GET_DEF(sctp_strict_sacks)
#if !defined(SCTP_WITH_NO_CSUM)
USRSCTP_SYSCTL_GET_DEF(sctp_no_csum_on_loopback)
@ -3352,10 +3379,7 @@ USRSCTP_SYSCTL_GET_DEF(sctp_add_more_threshold)
USRSCTP_SYSCTL_GET_DEF(sctp_nr_outgoing_streams_default)
USRSCTP_SYSCTL_GET_DEF(sctp_cmt_on_off)
USRSCTP_SYSCTL_GET_DEF(sctp_cmt_use_dac)
USRSCTP_SYSCTL_GET_DEF(sctp_nr_sack_on_off)
USRSCTP_SYSCTL_GET_DEF(sctp_use_cwnd_based_maxburst)
USRSCTP_SYSCTL_GET_DEF(sctp_asconf_auth_nochk)
USRSCTP_SYSCTL_GET_DEF(sctp_auth_disable)
USRSCTP_SYSCTL_GET_DEF(sctp_nat_friendly)
USRSCTP_SYSCTL_GET_DEF(sctp_L2_abc_variable)
USRSCTP_SYSCTL_GET_DEF(sctp_mbuf_threshold_count)
@ -3375,6 +3399,7 @@ USRSCTP_SYSCTL_GET_DEF(sctp_udp_tunneling_port)
USRSCTP_SYSCTL_GET_DEF(sctp_enable_sack_immediately)
USRSCTP_SYSCTL_GET_DEF(sctp_vtag_time_wait)
USRSCTP_SYSCTL_GET_DEF(sctp_blackhole)
USRSCTP_SYSCTL_GET_DEF(sctp_diag_info_code)
USRSCTP_SYSCTL_GET_DEF(sctp_fr_max_burst_default)
USRSCTP_SYSCTL_GET_DEF(sctp_path_pf_threshold)
USRSCTP_SYSCTL_GET_DEF(sctp_default_ss_module)

View File

@ -42,7 +42,7 @@
/* #include <sys/_lock.h> was 0 byte file */
/* #include <sys/_mutex.h> was 0 byte file */
/* #include <sys/_sx.h> */ /*__Userspace__ alternative?*/
#if !defined(__Userspace_os_DragonFly) && !defined(__Userspace_os_FreeBSD) && !defined(__Userspace_os_NetBSD) && !defined(__Userspace_os_Windows)
#if !defined(__Userspace_os_DragonFly) && !defined(__Userspace_os_FreeBSD) && !defined(__Userspace_os_NetBSD) && !defined(__Userspace_os_Windows) && !defined(__Userspace_os_NaCl)
#include <sys/uio.h>
#endif
#define SOCK_MAXADDRLEN 255
@ -54,7 +54,7 @@
#define SS_CANTRCVMORE 0x020
#define SS_CANTSENDMORE 0x010
#if defined(__Userspace_os_Darwin) || defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD) || defined(__Userspace_os_OpenBSD) || defined (__Userspace_os_Windows)
#if defined(__Userspace_os_Darwin) || defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD) || defined(__Userspace_os_OpenBSD) || defined (__Userspace_os_Windows) || defined(__Userspace_os_NaCl)
#define UIO_MAXIOV 1024
#define ERESTART (-1)
#endif

View File

@ -35,6 +35,7 @@
extern "C" {
#endif
#include <errno.h>
#include <sys/types.h>
#ifdef _WIN32
#ifdef _MSC_VER
@ -776,28 +777,6 @@ struct sctp_cc_option {
struct sctp_assoc_value aid_value;
};
struct sctp_cwnd_args {
struct sctp_nets *net; /* network to */ /* FIXME: LP64 issue */
uint32_t cwnd_new_value; /* cwnd in k */
uint32_t pseudo_cumack;
uint16_t inflight; /* flightsize in k */
uint16_t cwnd_augment; /* increment to it */
uint8_t meets_pseudo_cumack;
uint8_t need_new_pseudo_cumack;
uint8_t cnt_in_send;
uint8_t cnt_in_str;
};
struct sctp_blk_args {
uint32_t onsb; /* in 1k bytes */
uint32_t sndlen; /* len of send being attempted */
uint32_t peer_rwnd; /* rwnd of peer */
uint16_t send_sent_qcnt; /* chnk cnt */
uint16_t stream_qcnt; /* chnk cnt */
uint16_t chunks_on_oque; /* chunks out */
uint16_t flight_size; /* flight size in k */
};
struct sctp_timeouts {
sctp_assoc_t stimo_assoc_id;
uint32_t stimo_init;
@ -848,6 +827,8 @@ struct sctp_timeouts {
/******************** System calls *************/
struct socket;
void
usrsctp_init(uint16_t,
int (*)(void *addr, void *buffer, size_t length, uint8_t tos, uint8_t set_df),
@ -973,6 +954,9 @@ usrsctp_register_address(void *);
void
usrsctp_deregister_address(void *);
int
usrsctp_set_ulpinfo(struct socket *, void *);
#define SCTP_DUMP_OUTBOUND 1
#define SCTP_DUMP_INBOUND 0
@ -982,7 +966,7 @@ usrsctp_dumppacket(void *, size_t, int);
void
usrsctp_freedumpbuffer(char *);
#define USRSCTP_SYSCTL_DECL(__field) \
#define USRSCTP_SYSCTL_DECL(__field) \
void usrsctp_sysctl_set_ ## __field(uint32_t value);\
uint32_t usrsctp_sysctl_get_ ## __field(void);
@ -991,6 +975,12 @@ USRSCTP_SYSCTL_DECL(sctp_recvspace)
USRSCTP_SYSCTL_DECL(sctp_auto_asconf)
USRSCTP_SYSCTL_DECL(sctp_multiple_asconfs)
USRSCTP_SYSCTL_DECL(sctp_ecn_enable)
USRSCTP_SYSCTL_DECL(sctp_pr_enable)
USRSCTP_SYSCTL_DECL(sctp_auth_enable)
USRSCTP_SYSCTL_DECL(sctp_asconf_enable)
USRSCTP_SYSCTL_DECL(sctp_reconfig_enable)
USRSCTP_SYSCTL_DECL(sctp_nrsack_enable)
USRSCTP_SYSCTL_DECL(sctp_pktdrop_enable)
USRSCTP_SYSCTL_DECL(sctp_strict_sacks)
#if !defined(SCTP_WITH_NO_CSUM)
USRSCTP_SYSCTL_DECL(sctp_no_csum_on_loopback)
@ -1023,10 +1013,7 @@ USRSCTP_SYSCTL_DECL(sctp_nr_incoming_streams_default)
USRSCTP_SYSCTL_DECL(sctp_nr_outgoing_streams_default)
USRSCTP_SYSCTL_DECL(sctp_cmt_on_off)
USRSCTP_SYSCTL_DECL(sctp_cmt_use_dac)
USRSCTP_SYSCTL_DECL(sctp_nr_sack_on_off)
USRSCTP_SYSCTL_DECL(sctp_use_cwnd_based_maxburst)
USRSCTP_SYSCTL_DECL(sctp_asconf_auth_nochk)
USRSCTP_SYSCTL_DECL(sctp_auth_disable)
USRSCTP_SYSCTL_DECL(sctp_nat_friendly)
USRSCTP_SYSCTL_DECL(sctp_L2_abc_variable)
USRSCTP_SYSCTL_DECL(sctp_mbuf_threshold_count)
@ -1046,6 +1033,7 @@ USRSCTP_SYSCTL_DECL(sctp_udp_tunneling_port)
USRSCTP_SYSCTL_DECL(sctp_enable_sack_immediately)
USRSCTP_SYSCTL_DECL(sctp_vtag_time_wait)
USRSCTP_SYSCTL_DECL(sctp_blackhole)
USRSCTP_SYSCTL_DECL(sctp_diag_info_code)
USRSCTP_SYSCTL_DECL(sctp_fr_max_burst_default)
USRSCTP_SYSCTL_DECL(sctp_path_pf_threshold)
USRSCTP_SYSCTL_DECL(sctp_default_ss_module)