author | Randell Jesup <rjesup@jesup.org> |
Wed, 12 Mar 2014 02:09:31 -0400 | |
changeset 191329 | de392d555da8e0b8255a3713705a6706273c8dc7 |
parent 191328 | dab8e386596703c1809d8a88d64a07d34c856c3a |
child 191330 | 01ca94b4729ffa8ba577cb55e0176f66b836fe48 |
push id | 474 |
push user | asasaki@mozilla.com |
push date | Mon, 02 Jun 2014 21:01:02 +0000 |
treeherder | mozilla-release@967f4cf1b31c [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | jesup, tuexen |
bugs | 916427 |
milestone | 30.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/netwerk/sctp/sctp_update.log +++ b/netwerk/sctp/sctp_update.log @@ -8,8 +8,9 @@ sctp updated from CVS on Mon Aug 6 04:1 sctp updated to version 8119 from SVN on Wed Aug 29 21:52:12 EDT 2012 sctp updated to version 8131 from SVN on Tue Sep 4 00:26:11 EDT 2012 sctp updated to version 8165 from SVN on Wed Sep 5 09:39:43 EDT 2012 sctp updated to version 8176 from SVN on Wed Sep 5 18:02:08 EDT 2012 sctp updated to version 8263 from SVN on Sun Sep 16 00:48:48 EDT 2012 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
--- a/netwerk/sctp/src/netinet/sctp.h +++ b/netwerk/sctp/src/netinet/sctp.h @@ -27,17 +27,17 @@ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp.h 246595 2013-02-09 17:26:14Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp.h 254248 2013-08-12 13:52:15Z tuexen $"); #endif #ifndef _NETINET_SCTP_H_ #define _NETINET_SCTP_H_ #if (defined(__APPLE__) || defined(__Userspace_os_Linux) || defined(__Userspace_os_Darwin)) #include <stdint.h> #endif @@ -434,17 +434,17 @@ struct sctp_error_unrecognized_chunk { #define SCTP_COOKIE_ECHO 0x0a #define SCTP_COOKIE_ACK 0x0b #define SCTP_ECN_ECHO 0x0c #define SCTP_ECN_CWR 0x0d #define SCTP_SHUTDOWN_COMPLETE 0x0e /* RFC4895 */ #define SCTP_AUTHENTICATION 0x0f /* EY nr_sack chunk id*/ -#define SCTP_NR_SELECTIVE_ACK 0x10 +#define SCTP_NR_SELECTIVE_ACK 0x10 /************0x40 series ***********/ /************0x80 series ***********/ /* RFC5061 */ #define SCTP_ASCONF_ACK 0x80 /* draft-ietf-stewart-pktdrpsctp */ #define SCTP_PACKET_DROPPED 0x81 /* draft-ietf-stewart-strreset-xxx */ #define SCTP_STREAM_RESET 0x82 @@ -528,48 +528,48 @@ struct sctp_error_unrecognized_chunk { #define SCTP_PCB_COPY_FLAGS (SCTP_PCB_FLAGS_BOUNDALL|\ SCTP_PCB_FLAGS_WAKEINPUT|\ SCTP_PCB_FLAGS_BOUND_V6) #endif /* * PCB Features (in sctp_features bitmask) */ -#define SCTP_PCB_FLAGS_DO_NOT_PMTUD 0x00000001 -#define SCTP_PCB_FLAGS_EXT_RCVINFO 0x00000002 /* deprecated */ -#define SCTP_PCB_FLAGS_DONOT_HEARTBEAT 0x00000004 -#define SCTP_PCB_FLAGS_FRAG_INTERLEAVE 0x00000008 -#define SCTP_PCB_FLAGS_INTERLEAVE_STRMS 0x00000010 -#define SCTP_PCB_FLAGS_DO_ASCONF 0x00000020 -#define SCTP_PCB_FLAGS_AUTO_ASCONF 0x00000040 -#define SCTP_PCB_FLAGS_ZERO_COPY_ACTIVE 0x00000080 +#define SCTP_PCB_FLAGS_DO_NOT_PMTUD 0x0000000000000001 +#define SCTP_PCB_FLAGS_EXT_RCVINFO 0x0000000000000002 /* deprecated */ +#define SCTP_PCB_FLAGS_DONOT_HEARTBEAT 0x0000000000000004 +#define SCTP_PCB_FLAGS_FRAG_INTERLEAVE 0x0000000000000008 +#define SCTP_PCB_FLAGS_INTERLEAVE_STRMS 0x0000000000000010 +#define SCTP_PCB_FLAGS_DO_ASCONF 0x0000000000000020 +#define SCTP_PCB_FLAGS_AUTO_ASCONF 0x0000000000000040 +#define SCTP_PCB_FLAGS_ZERO_COPY_ACTIVE 0x0000000000000080 /* socket options */ -#define SCTP_PCB_FLAGS_NODELAY 0x00000100 -#define SCTP_PCB_FLAGS_AUTOCLOSE 0x00000200 -#define SCTP_PCB_FLAGS_RECVDATAIOEVNT 0x00000400 /* deprecated */ -#define SCTP_PCB_FLAGS_RECVASSOCEVNT 0x00000800 -#define SCTP_PCB_FLAGS_RECVPADDREVNT 0x00001000 -#define SCTP_PCB_FLAGS_RECVPEERERR 0x00002000 -#define SCTP_PCB_FLAGS_RECVSENDFAILEVNT 0x00004000 /* deprecated */ -#define SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT 0x00008000 -#define SCTP_PCB_FLAGS_ADAPTATIONEVNT 0x00010000 -#define SCTP_PCB_FLAGS_PDAPIEVNT 0x00020000 -#define SCTP_PCB_FLAGS_AUTHEVNT 0x00040000 -#define SCTP_PCB_FLAGS_STREAM_RESETEVNT 0x00080000 -#define SCTP_PCB_FLAGS_NO_FRAGMENT 0x00100000 -#define SCTP_PCB_FLAGS_EXPLICIT_EOR 0x00400000 -#define SCTP_PCB_FLAGS_NEEDS_MAPPED_V4 0x00800000 -#define SCTP_PCB_FLAGS_MULTIPLE_ASCONFS 0x01000000 -#define SCTP_PCB_FLAGS_PORTREUSE 0x02000000 -#define SCTP_PCB_FLAGS_DRYEVNT 0x04000000 -#define SCTP_PCB_FLAGS_RECVRCVINFO 0x08000000 -#define SCTP_PCB_FLAGS_RECVNXTINFO 0x10000000 -#define SCTP_PCB_FLAGS_ASSOC_RESETEVNT 0x20000000 -#define SCTP_PCB_FLAGS_STREAM_CHANGEEVNT 0x40000000 -#define SCTP_PCB_FLAGS_RECVNSENDFAILEVNT 0x80000000 +#define SCTP_PCB_FLAGS_NODELAY 0x0000000000000100 +#define SCTP_PCB_FLAGS_AUTOCLOSE 0x0000000000000200 +#define SCTP_PCB_FLAGS_RECVDATAIOEVNT 0x0000000000000400 /* deprecated */ +#define SCTP_PCB_FLAGS_RECVASSOCEVNT 0x0000000000000800 +#define SCTP_PCB_FLAGS_RECVPADDREVNT 0x0000000000001000 +#define SCTP_PCB_FLAGS_RECVPEERERR 0x0000000000002000 +#define SCTP_PCB_FLAGS_RECVSENDFAILEVNT 0x0000000000004000 /* deprecated */ +#define SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT 0x0000000000008000 +#define SCTP_PCB_FLAGS_ADAPTATIONEVNT 0x0000000000010000 +#define SCTP_PCB_FLAGS_PDAPIEVNT 0x0000000000020000 +#define SCTP_PCB_FLAGS_AUTHEVNT 0x0000000000040000 +#define SCTP_PCB_FLAGS_STREAM_RESETEVNT 0x0000000000080000 +#define SCTP_PCB_FLAGS_NO_FRAGMENT 0x0000000000100000 +#define SCTP_PCB_FLAGS_EXPLICIT_EOR 0x0000000000400000 +#define SCTP_PCB_FLAGS_NEEDS_MAPPED_V4 0x0000000000800000 +#define SCTP_PCB_FLAGS_MULTIPLE_ASCONFS 0x0000000001000000 +#define SCTP_PCB_FLAGS_PORTREUSE 0x0000000002000000 +#define SCTP_PCB_FLAGS_DRYEVNT 0x0000000004000000 +#define SCTP_PCB_FLAGS_RECVRCVINFO 0x0000000008000000 +#define SCTP_PCB_FLAGS_RECVNXTINFO 0x0000000010000000 +#define SCTP_PCB_FLAGS_ASSOC_RESETEVNT 0x0000000020000000 +#define SCTP_PCB_FLAGS_STREAM_CHANGEEVNT 0x0000000040000000 +#define SCTP_PCB_FLAGS_RECVNSENDFAILEVNT 0x0000000080000000 /*- * mobility_features parameters (by micchie).Note * these features are applied against the * sctp_mobility_features flags.. not the sctp_features * flags. */ #define SCTP_MOBILITY_BASE 0x00000001
--- a/netwerk/sctp/src/netinet/sctp_asconf.c +++ b/netwerk/sctp/src/netinet/sctp_asconf.c @@ -27,17 +27,17 @@ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_asconf.c 246595 2013-02-09 17:26:14Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp_asconf.c 257803 2013-11-07 17:08:09Z tuexen $"); #endif #include <netinet/sctp_os.h> #include <netinet/sctp_var.h> #include <netinet/sctp_sysctl.h> #include <netinet/sctp_pcb.h> #include <netinet/sctp_header.h> #include <netinet/sctputil.h> @@ -150,34 +150,38 @@ sctp_asconf_error_response(uint32_t id, static struct mbuf * sctp_process_asconf_add_ip(struct sockaddr *src, struct sctp_asconf_paramhdr *aph, struct sctp_tcb *stcb, int send_hb, int response_required) { struct sctp_nets *net; struct mbuf *m_reply = NULL; struct sockaddr_storage sa_store; struct sctp_paramhdr *ph; - uint16_t param_type, param_length, aparam_length; + uint16_t param_type, aparam_length; +#if defined(INET) || defined(INET6) + uint16_t param_length; +#endif struct sockaddr *sa; int zero_address = 0; int bad_address = 0; #ifdef INET struct sockaddr_in *sin; struct sctp_ipv4addr_param *v4addr; #endif #ifdef INET6 struct sockaddr_in6 *sin6; struct sctp_ipv6addr_param *v6addr; #endif aparam_length = ntohs(aph->ph.param_length); ph = (struct sctp_paramhdr *)(aph + 1); param_type = ntohs(ph->param_type); +#if defined(INET) || defined(INET6) param_length = ntohs(ph->param_length); - +#endif sa = (struct sockaddr *)&sa_store; switch (param_type) { #ifdef INET case SCTP_IPV4_ADDRESS: if (param_length != sizeof(struct sctp_ipv4addr_param)) { /* invalid param size */ return (NULL); } @@ -300,34 +304,38 @@ sctp_asconf_del_remote_addrs_except(stru static struct mbuf * sctp_process_asconf_delete_ip(struct sockaddr *src, struct sctp_asconf_paramhdr *aph, struct sctp_tcb *stcb, int response_required) { struct mbuf *m_reply = NULL; struct sockaddr_storage sa_store; struct sctp_paramhdr *ph; - uint16_t param_type, param_length, aparam_length; + uint16_t param_type, aparam_length; +#if defined(INET) || defined(INET6) + uint16_t param_length; +#endif struct sockaddr *sa; int zero_address = 0; int result; #ifdef INET struct sockaddr_in *sin; struct sctp_ipv4addr_param *v4addr; #endif #ifdef INET6 struct sockaddr_in6 *sin6; struct sctp_ipv6addr_param *v6addr; #endif aparam_length = ntohs(aph->ph.param_length); ph = (struct sctp_paramhdr *)(aph + 1); param_type = ntohs(ph->param_type); +#if defined(INET) || defined(INET6) param_length = ntohs(ph->param_length); - +#endif sa = (struct sockaddr *)&sa_store; switch (param_type) { #ifdef INET case SCTP_IPV4_ADDRESS: if (param_length != sizeof(struct sctp_ipv4addr_param)) { /* invalid param size */ return (NULL); } @@ -432,33 +440,37 @@ sctp_process_asconf_delete_ip(struct soc static struct mbuf * sctp_process_asconf_set_primary(struct sockaddr *src, struct sctp_asconf_paramhdr *aph, struct sctp_tcb *stcb, int response_required) { struct mbuf *m_reply = NULL; struct sockaddr_storage sa_store; struct sctp_paramhdr *ph; - uint16_t param_type, param_length, aparam_length; + uint16_t param_type, aparam_length; +#if defined(INET) || defined(INET6) + uint16_t param_length; +#endif struct sockaddr *sa; int zero_address = 0; #ifdef INET struct sockaddr_in *sin; struct sctp_ipv4addr_param *v4addr; #endif #ifdef INET6 struct sockaddr_in6 *sin6; struct sctp_ipv6addr_param *v6addr; #endif aparam_length = ntohs(aph->ph.param_length); ph = (struct sctp_paramhdr *)(aph + 1); param_type = ntohs(ph->param_type); +#if defined(INET) || defined(INET6) param_length = ntohs(ph->param_length); - +#endif sa = (struct sockaddr *)&sa_store; switch (param_type) { #ifdef INET case SCTP_IPV4_ADDRESS: if (param_length != sizeof(struct sctp_ipv4addr_param)) { /* invalid param size */ return (NULL); } @@ -868,47 +880,49 @@ sctp_asconf_addr_match(struct sctp_ascon } /* * does the address match? returns 0 if not, 1 if so */ static uint32_t sctp_addr_match(struct sctp_paramhdr *ph, struct sockaddr *sa) { +#if defined(INET) || defined(INET6) uint16_t param_type, param_length; param_type = ntohs(ph->param_type); param_length = ntohs(ph->param_length); +#endif switch (sa->sa_family) { #ifdef INET6 case AF_INET6: { /* XXX scopeid */ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa; struct sctp_ipv6addr_param *v6addr; v6addr = (struct sctp_ipv6addr_param *)ph; if ((param_type == SCTP_IPV6_ADDRESS) && - param_length == sizeof(struct sctp_ipv6addr_param) && + (param_length == sizeof(struct sctp_ipv6addr_param)) && (memcmp(&v6addr->addr, &sin6->sin6_addr, sizeof(struct in6_addr)) == 0)) { return (1); } break; } #endif #ifdef INET case AF_INET: { struct sockaddr_in *sin = (struct sockaddr_in *)sa; struct sctp_ipv4addr_param *v4addr; v4addr = (struct sctp_ipv4addr_param *)ph; if ((param_type == SCTP_IPV4_ADDRESS) && - param_length == sizeof(struct sctp_ipv4addr_param) && + (param_length == sizeof(struct sctp_ipv4addr_param)) && (memcmp(&v4addr->addr, &sin->sin_addr, sizeof(struct in_addr)) == 0)) { return (1); } break; } #endif default: @@ -1201,17 +1215,16 @@ sctp_asconf_addr_mgmt_ack(struct sctp_tc * an address already scheduled for add. If a duplicate operation is found, * ignore the new one. */ static int sctp_asconf_queue_mgmt(struct sctp_tcb *stcb, struct sctp_ifa *ifa, uint16_t type) { struct sctp_asconf_addr *aa, *aa_next; - struct sockaddr *sa; /* make sure the request isn't already in the queue */ TAILQ_FOREACH_SAFE(aa, &stcb->asoc.asconf_queue, next, aa_next) { /* address match? */ if (sctp_asconf_addr_match(aa, &ifa->address.sa) == 0) continue; /* is the request already in queue but not sent? * pass the request already sent in order to resolve the following case: @@ -1264,33 +1277,31 @@ sctp_asconf_queue_mgmt(struct sctp_tcb * /* correlation_id filled in during send routine later... */ switch (ifa->address.sa.sa_family) { #ifdef INET6 case AF_INET6: { struct sockaddr_in6 *sin6; sin6 = (struct sockaddr_in6 *)&ifa->address.sa; - sa = (struct sockaddr *)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) + sizeof(struct sctp_ipv6addr_param); memcpy(&aa->ap.addrp.addr, &sin6->sin6_addr, sizeof(struct in6_addr)); break; } #endif #ifdef INET case AF_INET: { struct sockaddr_in *sin; sin= (struct sockaddr_in *)&ifa->address.sa; - sa = (struct sockaddr *)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) + sizeof(struct sctp_ipv4addr_param); memcpy(&aa->ap.addrp.addr, &sin->sin_addr, sizeof(struct in_addr)); break; } @@ -1303,23 +1314,23 @@ sctp_asconf_queue_mgmt(struct sctp_tcb * } aa->sent = 0; /* clear sent flag */ TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next); #ifdef SCTP_DEBUG if (SCTP_BASE_SYSCTL(sctp_debug_on) & SCTP_DEBUG_ASCONF2) { if (type == SCTP_ADD_IP_ADDRESS) { SCTP_PRINTF("asconf_queue_mgmt: inserted asconf ADD_IP_ADDRESS: "); - SCTPDBG_ADDR(SCTP_DEBUG_ASCONF2, sa); + SCTPDBG_ADDR(SCTP_DEBUG_ASCONF2, &ifa->address.sa); } else if (type == SCTP_DEL_IP_ADDRESS) { SCTP_PRINTF("asconf_queue_mgmt: appended asconf DEL_IP_ADDRESS: "); - SCTPDBG_ADDR(SCTP_DEBUG_ASCONF2, sa); + SCTPDBG_ADDR(SCTP_DEBUG_ASCONF2, &ifa->address.sa); } else { SCTP_PRINTF("asconf_queue_mgmt: appended asconf SET_PRIM_ADDR: "); - SCTPDBG_ADDR(SCTP_DEBUG_ASCONF2, sa); + SCTPDBG_ADDR(SCTP_DEBUG_ASCONF2, &ifa->address.sa); } } #endif return (0); } @@ -2604,17 +2615,18 @@ sctp_compose_asconf(struct sctp_tcb *stc /* add parameters... up to smallest MTU allowed */ TAILQ_FOREACH(aa, &stcb->asoc.asconf_queue, next) { if (aa->sent) continue; /* get the parameter length */ p_length = SCTP_SIZE32(aa->ap.aph.ph.param_length); /* will it fit in current chunk? */ - if (SCTP_BUF_LEN(m_asconf) + p_length > stcb->asoc.smallest_mtu) { + if ((SCTP_BUF_LEN(m_asconf) + p_length > stcb->asoc.smallest_mtu) || + (SCTP_BUF_LEN(m_asconf) + p_length > MCLBYTES)) { /* won't fit, so we're done with this chunk */ break; } /* assign (and store) a correlation id */ aa->ap.aph.correlation_id = correlation_id++; /* * fill in address if we're doing a delete this is a simple @@ -2725,17 +2737,17 @@ sctp_compose_asconf(struct sctp_tcb *stc lookup->ph.param_length = htons(SCTP_SIZE32(sizeof(struct sctp_ipv4addr_param))); bzero(lookup->addr, sizeof(struct in_addr)); SCTP_BUF_LEN(m_asconf_chk) += SCTP_SIZE32(sizeof(struct sctp_ipv4addr_param)); } } /* chain it all together */ SCTP_BUF_NEXT(m_asconf_chk) = m_asconf; *retlen = SCTP_BUF_LEN(m_asconf_chk) + SCTP_BUF_LEN(m_asconf); - acp->ch.chunk_length = ntohs(*retlen); + acp->ch.chunk_length = htons(*retlen); return (m_asconf_chk); } /* * section to handle address changes before an association is up eg. changes * during INIT/INIT-ACK/COOKIE-ECHO handshake */
--- a/netwerk/sctp/src/netinet/sctp_auth.c +++ b/netwerk/sctp/src/netinet/sctp_auth.c @@ -27,17 +27,17 @@ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_auth.c 243882 2012-12-05 08:04:20Z glebius $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp_auth.c 257804 2013-11-07 18:50:11Z tuexen $"); #endif #include <netinet/sctp_os.h> #include <netinet/sctp.h> #include <netinet/sctp_header.h> #include <netinet/sctp_pcb.h> #include <netinet/sctp_var.h> #include <netinet/sctp_sysctl.h> @@ -330,20 +330,16 @@ sctp_get_keylen(sctp_key_t *key) /* * generate a new random key of length 'keylen' */ sctp_key_t * sctp_generate_random_key(uint32_t keylen) { sctp_key_t *new_key; - /* validate keylen */ - if (keylen > SCTP_AUTH_RANDOM_SIZE_MAX) - keylen = SCTP_AUTH_RANDOM_SIZE_MAX; - new_key = sctp_alloc_key(keylen); if (new_key == NULL) { /* out of memory */ return (NULL); } SCTP_READ_RANDOM(new_key->key, keylen); new_key->keylen = keylen; return (new_key); @@ -371,60 +367,46 @@ sctp_set_key(uint8_t *key, uint32_t keyl */ static int sctp_compare_key(sctp_key_t *key1, sctp_key_t *key2) { uint32_t maxlen; uint32_t i; uint32_t key1len, key2len; uint8_t *key_1, *key_2; - uint8_t temp[SCTP_AUTH_RANDOM_SIZE_MAX]; + uint8_t val1, val2; /* sanity/length check */ key1len = sctp_get_keylen(key1); key2len = sctp_get_keylen(key2); if ((key1len == 0) && (key2len == 0)) return (0); else if (key1len == 0) return (-1); else if (key2len == 0) return (1); - if (key1len != key2len) { - if (key1len >= key2len) - maxlen = key1len; - else - maxlen = key2len; - bzero(temp, maxlen); - if (key1len < maxlen) { - /* prepend zeroes to key1 */ - bcopy(key1->key, temp + (maxlen - key1len), key1len); - key_1 = temp; - key_2 = key2->key; - } else { - /* prepend zeroes to key2 */ - bcopy(key2->key, temp + (maxlen - key2len), key2len); - key_1 = key1->key; - key_2 = temp; - } + if (key1len < key2len) { + maxlen = key2len; } else { maxlen = key1len; - key_1 = key1->key; - key_2 = key2->key; } - + key_1 = key1->key; + key_2 = key2->key; + /* check for numeric equality */ for (i = 0; i < maxlen; i++) { - if (*key_1 > *key_2) - return (1); - else if (*key_1 < *key_2) - return (-1); - key_1++; - key_2++; + /* left-pad with zeros */ + val1 = (i < (maxlen - key1len)) ? 0 : *(key_1++); + val2 = (i < (maxlen - key2len)) ? 0 : *(key_2++); + if (val1 > val2) { + return (1); + } else if (val1 < val2) { + return (-1); + } } - /* keys are equal value, so check lengths */ if (key1len == key2len) return (0); else if (key1len < key2len) return (-1); else return (1); } @@ -698,26 +680,22 @@ sctp_auth_add_hmacid(sctp_hmaclist_t *li int i; if (list == NULL) return (-1); if (list->num_algo == list->max_algo) { SCTPDBG(SCTP_DEBUG_AUTH1, "SCTP: HMAC id list full, ignoring add %u\n", hmac_id); return (-1); } +#if defined(SCTP_SUPPORT_HMAC_SHA256) if ((hmac_id != SCTP_AUTH_HMAC_ID_SHA1) && -#ifdef HAVE_SHA224 - (hmac_id != SCTP_AUTH_HMAC_ID_SHA224) && + (hmac_id != SCTP_AUTH_HMAC_ID_SHA256)) { +#else + if (hmac_id != SCTP_AUTH_HMAC_ID_SHA1) { #endif -#ifdef HAVE_SHA2 - (hmac_id != SCTP_AUTH_HMAC_ID_SHA256) && - (hmac_id != SCTP_AUTH_HMAC_ID_SHA384) && - (hmac_id != SCTP_AUTH_HMAC_ID_SHA512) && -#endif - 1) { return (-1); } /* Now is it already in the list */ for (i = 0; i < list->num_algo; i++) { if (list->hmac[i] == hmac_id) { /* already in list */ return (-1); } @@ -747,21 +725,28 @@ sctp_copy_hmaclist(sctp_hmaclist_t *list return (new_list); } sctp_hmaclist_t * sctp_default_supported_hmaclist(void) { sctp_hmaclist_t *new_list; +#if defined(SCTP_SUPPORT_HMAC_SHA256) new_list = sctp_alloc_hmaclist(2); +#else + new_list = sctp_alloc_hmaclist(1); +#endif if (new_list == NULL) return (NULL); +#if defined(SCTP_SUPPORT_HMAC_SHA256) + /* We prefer SHA256, so list it first */ + (void)sctp_auth_add_hmacid(new_list, SCTP_AUTH_HMAC_ID_SHA256); +#endif (void)sctp_auth_add_hmacid(new_list, SCTP_AUTH_HMAC_ID_SHA1); - (void)sctp_auth_add_hmacid(new_list, SCTP_AUTH_HMAC_ID_SHA256); return (new_list); } /*- * HMAC algos are listed in priority/preference order * find the best HMAC id to use for the peer based on local support */ uint16_t @@ -807,29 +792,23 @@ sctp_serialize_hmaclist(sctp_hmaclist_t } return (list->num_algo * sizeof(hmac_id)); } int sctp_verify_hmac_param (struct sctp_auth_hmac_algo *hmacs, uint32_t num_hmacs) { uint32_t i; - uint16_t hmac_id; - uint32_t sha1_supported = 0; for (i = 0; i < num_hmacs; i++) { - hmac_id = ntohs(hmacs->hmac_ids[i]); - if (hmac_id == SCTP_AUTH_HMAC_ID_SHA1) - sha1_supported = 1; + if (ntohs(hmacs->hmac_ids[i]) == SCTP_AUTH_HMAC_ID_SHA1) { + return (0); + } } - /* all HMAC id's are supported */ - if (sha1_supported == 0) - return (-1); - else - return (0); + return (-1); } sctp_authinfo_t * sctp_alloc_authinfo(void) { sctp_authinfo_t *new_authinfo; SCTP_MALLOC(new_authinfo, sctp_authinfo_t *, sizeof(*new_authinfo), @@ -873,141 +852,96 @@ sctp_get_auth_chunk_len(uint16_t hmac_al } uint32_t sctp_get_hmac_digest_len(uint16_t hmac_algo) { switch (hmac_algo) { case SCTP_AUTH_HMAC_ID_SHA1: return (SCTP_AUTH_DIGEST_LEN_SHA1); -#ifdef HAVE_SHA224 - case SCTP_AUTH_HMAC_ID_SHA224: - return (SCTP_AUTH_DIGEST_LEN_SHA224); -#endif -#ifdef HAVE_SHA2 +#if defined(SCTP_SUPPORT_HMAC_SHA256) case SCTP_AUTH_HMAC_ID_SHA256: return (SCTP_AUTH_DIGEST_LEN_SHA256); - case SCTP_AUTH_HMAC_ID_SHA384: - return (SCTP_AUTH_DIGEST_LEN_SHA384); - case SCTP_AUTH_HMAC_ID_SHA512: - return (SCTP_AUTH_DIGEST_LEN_SHA512); #endif default: /* unknown HMAC algorithm: can't do anything */ return (0); } /* end switch */ } static inline int sctp_get_hmac_block_len(uint16_t hmac_algo) { switch (hmac_algo) { case SCTP_AUTH_HMAC_ID_SHA1: -#ifdef HAVE_SHA224 - case SCTP_AUTH_HMAC_ID_SHA224: -#endif return (64); -#ifdef HAVE_SHA2 +#if defined(SCTP_SUPPORT_HMAC_SHA256) case SCTP_AUTH_HMAC_ID_SHA256: return (64); - case SCTP_AUTH_HMAC_ID_SHA384: - case SCTP_AUTH_HMAC_ID_SHA512: - return (128); #endif case SCTP_AUTH_HMAC_ID_RSVD: default: /* unknown HMAC algorithm: can't do anything */ return (0); } /* end switch */ } #if defined(__Userspace__) /* __Userspace__ SHA1_Init is defined in libcrypto.a (libssl-dev on Ubuntu) */ #endif static void sctp_hmac_init(uint16_t hmac_algo, sctp_hash_context_t *ctx) { switch (hmac_algo) { case SCTP_AUTH_HMAC_ID_SHA1: - SHA1_Init(&ctx->sha1); + SCTP_SHA1_INIT(&ctx->sha1); break; -#ifdef HAVE_SHA224 - case SCTP_AUTH_HMAC_ID_SHA224: - break; -#endif -#ifdef HAVE_SHA2 +#if defined(SCTP_SUPPORT_HMAC_SHA256) case SCTP_AUTH_HMAC_ID_SHA256: - SHA256_Init(&ctx->sha256); - break; - case SCTP_AUTH_HMAC_ID_SHA384: - SHA384_Init(&ctx->sha384); - break; - case SCTP_AUTH_HMAC_ID_SHA512: - SHA512_Init(&ctx->sha512); + SCTP_SHA256_INIT(&ctx->sha256); break; #endif case SCTP_AUTH_HMAC_ID_RSVD: default: /* unknown HMAC algorithm: can't do anything */ return; } /* end switch */ } static void sctp_hmac_update(uint16_t hmac_algo, sctp_hash_context_t *ctx, uint8_t *text, uint32_t textlen) { switch (hmac_algo) { case SCTP_AUTH_HMAC_ID_SHA1: - SHA1_Update(&ctx->sha1, text, textlen); + SCTP_SHA1_UPDATE(&ctx->sha1, text, textlen); break; -#ifdef HAVE_SHA224 - case SCTP_AUTH_HMAC_ID_SHA224: - break; -#endif -#ifdef HAVE_SHA2 +#if defined(SCTP_SUPPORT_HMAC_SHA256) case SCTP_AUTH_HMAC_ID_SHA256: - SHA256_Update(&ctx->sha256, text, textlen); - break; - case SCTP_AUTH_HMAC_ID_SHA384: - SHA384_Update(&ctx->sha384, text, textlen); - break; - case SCTP_AUTH_HMAC_ID_SHA512: - SHA512_Update(&ctx->sha512, text, textlen); + SCTP_SHA256_UPDATE(&ctx->sha256, text, textlen); break; #endif case SCTP_AUTH_HMAC_ID_RSVD: default: /* unknown HMAC algorithm: can't do anything */ return; } /* end switch */ } static void sctp_hmac_final(uint16_t hmac_algo, sctp_hash_context_t *ctx, uint8_t *digest) { switch (hmac_algo) { case SCTP_AUTH_HMAC_ID_SHA1: - SHA1_Final(digest, &ctx->sha1); + SCTP_SHA1_FINAL(digest, &ctx->sha1); break; -#ifdef HAVE_SHA224 - case SCTP_AUTH_HMAC_ID_SHA224: - break; -#endif -#ifdef HAVE_SHA2 +#if defined(SCTP_SUPPORT_HMAC_SHA256) case SCTP_AUTH_HMAC_ID_SHA256: - SHA256_Final(digest, &ctx->sha256); - break; - case SCTP_AUTH_HMAC_ID_SHA384: - /* SHA384 is truncated SHA512 */ - SHA384_Final(digest, &ctx->sha384); - break; - case SCTP_AUTH_HMAC_ID_SHA512: - SHA512_Final(digest, &ctx->sha512); + SCTP_SHA256_FINAL(digest, &ctx->sha256); break; #endif case SCTP_AUTH_HMAC_ID_RSVD: default: /* unknown HMAC algorithm: can't do anything */ return; } /* end switch */ }
--- a/netwerk/sctp/src/netinet/sctp_auth.h +++ b/netwerk/sctp/src/netinet/sctp_auth.h @@ -27,43 +27,38 @@ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_auth.h 235828 2012-05-23 11:26:28Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp_auth.h 257804 2013-11-07 18:50:11Z tuexen $"); #endif #ifndef _NETINET_SCTP_AUTH_H_ #define _NETINET_SCTP_AUTH_H_ +#include <netinet/sctp_os.h> /* digest lengths */ #define SCTP_AUTH_DIGEST_LEN_SHA1 20 -#define SCTP_AUTH_DIGEST_LEN_SHA224 28 #define SCTP_AUTH_DIGEST_LEN_SHA256 32 -#define SCTP_AUTH_DIGEST_LEN_SHA384 48 -#define SCTP_AUTH_DIGEST_LEN_SHA512 64 -#define SCTP_AUTH_DIGEST_LEN_MAX 64 +#define SCTP_AUTH_DIGEST_LEN_MAX SCTP_AUTH_DIGEST_LEN_SHA256 /* random sizes */ #define SCTP_AUTH_RANDOM_SIZE_DEFAULT 32 #define SCTP_AUTH_RANDOM_SIZE_REQUIRED 32 -#define SCTP_AUTH_RANDOM_SIZE_MAX 256 /* union of all supported HMAC algorithm contexts */ typedef union sctp_hash_context { - SHA1_CTX sha1; -#ifdef HAVE_SHA2 - SHA256_CTX sha256; - SHA384_CTX sha384; - SHA512_CTX sha512; + SCTP_SHA1_CTX sha1; +#if defined(SCTP_SUPPORT_HMAC_SHA256) + SCTP_SHA256_CTX sha256; #endif } sctp_hash_context_t; typedef struct sctp_key { uint32_t keylen; uint8_t key[]; } sctp_key_t;
--- a/netwerk/sctp/src/netinet/sctp_bsd_addr.c +++ b/netwerk/sctp/src/netinet/sctp_bsd_addr.c @@ -27,40 +27,35 @@ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_bsd_addr.c 239035 2012-08-04 08:03:30Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp_bsd_addr.c 258765 2013-11-30 12:51:19Z tuexen $"); #endif #include <netinet/sctp_os.h> #include <netinet/sctp_var.h> #include <netinet/sctp_pcb.h> #include <netinet/sctp_header.h> #include <netinet/sctputil.h> #include <netinet/sctp_output.h> #include <netinet/sctp_bsd_addr.h> #include <netinet/sctp_uio.h> #include <netinet/sctputil.h> #include <netinet/sctp_timer.h> #include <netinet/sctp_asconf.h> #include <netinet/sctp_sysctl.h> #include <netinet/sctp_indata.h> -#if !defined(__Userspace_os_Windows) -#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__ MALLOC_DEFINE(SCTP_M_MAP, "sctp_map", "sctp asoc map descriptor"); MALLOC_DEFINE(SCTP_M_STRMI, "sctp_stri", "sctp stream in array"); MALLOC_DEFINE(SCTP_M_STRMO, "sctp_stro", "sctp stream out array"); MALLOC_DEFINE(SCTP_M_ASC_ADDR, "sctp_aadr", "sctp asconf address"); MALLOC_DEFINE(SCTP_M_ASC_IT, "sctp_a_it", "sctp asconf iterator"); @@ -160,77 +155,59 @@ sctp_iterator_thread(void *v SCTP_UNUSED } #if !defined(__FreeBSD__) /* Now this thread needs to be terminated */ sctp_cleanup_itqueue(); sctp_it_ctl.iterator_flags |= SCTP_ITERATOR_EXITED; SCTP_IPI_ITERATOR_WQ_UNLOCK(); #if defined(__Userspace__) sctp_wakeup_iterator(); -#if !defined(__Userspace_os_Windows) - pthread_exit(NULL); -#else - ExitThread(0); -#endif + return (NULL); #else wakeup(&sctp_it_ctl.iterator_flags); thread_terminate(current_thread()); -#endif #ifdef INVARIANTS panic("Hmm. thread_terminate() continues..."); #endif -#if defined(__Userspace__) - return (NULL); #endif #endif } void sctp_startup_iterator(void) { - static int called = 0; -#if defined(__FreeBSD__) || (defined(__Userspace__) && !defined(__Userspace_os_Windows)) - int ret; -#endif - - if (called) { + if (sctp_it_ctl.thread_proc) { /* You only get one */ return; } - /* init the iterator head */ - called = 1; - sctp_it_ctl.iterator_running = 0; - sctp_it_ctl.iterator_flags = 0; - sctp_it_ctl.cur_it = NULL; + /* Initialize global locks here, thus only once. */ SCTP_ITERATOR_LOCK_INIT(); SCTP_IPI_ITERATOR_WQ_INIT(); TAILQ_INIT(&sctp_it_ctl.iteratorhead); #if defined(__FreeBSD__) #if __FreeBSD_version <= 701000 - ret = kthread_create(sctp_iterator_thread, + kthread_create(sctp_iterator_thread, #else - ret = kproc_create(sctp_iterator_thread, + kproc_create(sctp_iterator_thread, #endif - (void *)NULL, - &sctp_it_ctl.thread_proc, - RFPROC, - SCTP_KTHREAD_PAGES, - SCTP_KTRHEAD_NAME); + (void *)NULL, + &sctp_it_ctl.thread_proc, + RFPROC, + SCTP_KTHREAD_PAGES, + SCTP_KTRHEAD_NAME); #elif defined(__APPLE__) - (void)kernel_thread_start((thread_continue_t)sctp_iterator_thread, NULL, &sctp_it_ctl.thread_proc); + kernel_thread_start((thread_continue_t)sctp_iterator_thread, NULL, &sctp_it_ctl.thread_proc); #elif defined(__Userspace__) #if defined(__Userspace_os_Windows) if ((sctp_it_ctl.thread_proc = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&sctp_iterator_thread, NULL, 0, NULL)) == NULL) { - SCTP_PRINTF("ERROR; Creating sctp_iterator_thread failed\n"); +#else + if (pthread_create(&sctp_it_ctl.thread_proc, NULL, &sctp_iterator_thread, NULL)) { +#endif + SCTP_PRINTF("ERROR: Creating sctp_iterator_thread failed.\n"); } -#else - if ((ret = pthread_create(&sctp_it_ctl.thread_proc, NULL, &sctp_iterator_thread, NULL))) { - SCTP_PRINTF("ERROR; return code from sctp_iterator_thread pthread_create() is %d\n", ret); - } -#endif #endif } #ifdef INET6 #if defined(__Userspace__) /* __Userspace__ TODO. struct in6_ifaddr is defined in sys/netinet6/in6_var.h ip6_use_deprecated is defined as int ip6_use_deprecated = 1; in /src/sys/netinet6/in6_proto.c @@ -336,21 +313,23 @@ sctp_is_vmware_interface(struct ifnet *i #endif #ifdef FREE #undef FREE #define FREE(x) HeapFree(GetProcessHeap(), 0, (x)) #endif static void sctp_init_ifns_for_vrf(int vrfid) { +#if defined(INET) || defined(INET6) struct ifaddrs *ifa; struct sctp_ifa *sctp_ifa; DWORD Err, AdapterAddrsSize; - PIP_ADAPTER_ADDRESSES pAdapterAddrs, pAdapterAddrs6, pAdapt; + PIP_ADAPTER_ADDRESSES pAdapterAddrs, pAdapt; PIP_ADAPTER_UNICAST_ADDRESS pUnicast; +#endif #ifdef INET AdapterAddrsSize = 0; if ((Err = GetAdaptersAddresses(AF_INET, 0, NULL, NULL, &AdapterAddrsSize)) != 0) { if ((Err != ERROR_BUFFER_OVERFLOW) && (Err != ERROR_INSUFFICIENT_BUFFER)) { SCTP_PRINTF("GetAdaptersV4Addresses() sizing failed with error code %d\n", Err); SCTP_PRINTF("err = %d; AdapterAddrsSize = %d\n", Err, AdapterAddrsSize); @@ -367,16 +346,19 @@ sctp_init_ifns_for_vrf(int vrfid) if ((Err = GetAdaptersAddresses(AF_INET, 0, NULL, pAdapterAddrs, &AdapterAddrsSize)) != ERROR_SUCCESS) { SCTP_PRINTF("GetAdaptersV4Addresses() failed with error code %d\n", Err); return; } /* Enumerate through each returned adapter and save its information */ for (pAdapt = pAdapterAddrs; pAdapt; pAdapt = pAdapt->Next) { if (pAdapt->IfType == IF_TYPE_IEEE80211 || pAdapt->IfType == IF_TYPE_ETHERNET_CSMACD) { for (pUnicast = pAdapt->FirstUnicastAddress; pUnicast; pUnicast = pUnicast->Next) { + if (IN4_ISLINKLOCAL_ADDRESS(&(((struct sockaddr_in *)(pUnicast->Address.lpSockaddr))->sin_addr))) { + continue; + } ifa = (struct ifaddrs*)malloc(sizeof(struct ifaddrs)); 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)); sctp_ifa = sctp_add_addr_to_vrf(0, ifa, @@ -402,27 +384,27 @@ sctp_init_ifns_for_vrf(int vrfid) if ((Err = GetAdaptersAddresses(AF_INET6, 0, NULL, NULL, &AdapterAddrsSize)) != 0) { if ((Err != ERROR_BUFFER_OVERFLOW) && (Err != ERROR_INSUFFICIENT_BUFFER)) { SCTP_PRINTF("GetAdaptersV6Addresses() sizing failed with error code %d\n", Err); SCTP_PRINTF("err = %d; AdapterAddrsSize = %d\n", Err, AdapterAddrsSize); return; } } /* Allocate memory from sizing information */ - if ((pAdapterAddrs6 = (PIP_ADAPTER_ADDRESSES) GlobalAlloc(GPTR, AdapterAddrsSize)) == NULL) { + if ((pAdapterAddrs = (PIP_ADAPTER_ADDRESSES) GlobalAlloc(GPTR, AdapterAddrsSize)) == NULL) { SCTP_PRINTF("Memory allocation error!\n"); return; } /* Get actual adapter information */ - if ((Err = GetAdaptersAddresses(AF_INET6, 0, NULL, pAdapterAddrs6, &AdapterAddrsSize)) != ERROR_SUCCESS) { + if ((Err = GetAdaptersAddresses(AF_INET6, 0, NULL, pAdapterAddrs, &AdapterAddrsSize)) != ERROR_SUCCESS) { SCTP_PRINTF("GetAdaptersV6Addresses() failed with error code %d\n", Err); return; } /* Enumerate through each returned adapter and save its information */ - for (pAdapt = pAdapterAddrs6; pAdapt; pAdapt = pAdapt->Next) { + for (pAdapt = pAdapterAddrs; pAdapt; pAdapt = pAdapt->Next) { 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_flags = pAdapt->Flags; ifa->ifa_addr = (struct sockaddr *)malloc(sizeof(struct sockaddr_in6)); memcpy(ifa->ifa_addr, pUnicast->Address.lpSockaddr, sizeof(struct sockaddr_in6)); sctp_ifa = sctp_add_addr_to_vrf(0, @@ -435,69 +417,82 @@ sctp_init_ifns_for_vrf(int vrfid) ifa->ifa_flags, 0); if (sctp_ifa) { sctp_ifa->localifa_flags &= ~SCTP_ADDR_DEFER_USE; } } } } - if (pAdapterAddrs6) - FREE(pAdapterAddrs6); + if (pAdapterAddrs) + FREE(pAdapterAddrs); #endif } #elif defined(__Userspace__) static void sctp_init_ifns_for_vrf(int vrfid) { - /* __Userspace__ TODO struct ifaddr is defined in net/if_var.h - * This struct contains struct ifnet, which is also defined in - * net/if_var.h. Currently a zero byte if_var.h file is present for Linux boxes - */ +#if defined(INET) || defined(INET6) int rc; struct ifaddrs *ifa = NULL; struct sctp_ifa *sctp_ifa; uint32_t ifa_flags; rc = getifaddrs(&g_interfaces); if (rc != 0) { return; } - for (ifa = g_interfaces; ifa; ifa = ifa->ifa_next) { if (ifa->ifa_addr == NULL) { continue; } +#if !defined(INET) + if (ifa->ifa_addr->sa_family != AF_INET6) { + /* non inet6 skip */ + continue; + } +#elif !defined(INET6) + if (ifa->ifa_addr->sa_family != AF_INET) { + /* non inet skip */ + continue; + } +#else if ((ifa->ifa_addr->sa_family != AF_INET) && (ifa->ifa_addr->sa_family != AF_INET6)) { /* non inet/inet6 skip */ continue; } +#endif +#if defined(INET6) if ((ifa->ifa_addr->sa_family == AF_INET6) && IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr)) { /* skip unspecifed addresses */ continue; } +#endif +#if defined(INET) if (ifa->ifa_addr->sa_family == AF_INET && ((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr == 0) { continue; } +#endif ifa_flags = 0; sctp_ifa = sctp_add_addr_to_vrf(vrfid, ifa, if_nametoindex(ifa->ifa_name), 0, ifa->ifa_name, (void *)ifa, ifa->ifa_addr, ifa_flags, 0); if (sctp_ifa) { sctp_ifa->localifa_flags &= ~SCTP_ADDR_DEFER_USE; } } +#endif } #endif #if defined(__APPLE__) static void sctp_init_ifns_for_vrf(int vrfid) { /* Here we must apply ANY locks needed by the @@ -825,22 +820,22 @@ sctp_get_mbuf_for_msg(unsigned int space MGETHDR(m, how, type); } else { MGET(m, how, type); } if (m == NULL) { return (NULL); } if (allonebuf == 0) - mbuf_threshold = SCTP_BASE_SYSCTL(sctp_mbuf_threshold_count); + mbuf_threshold = SCTP_BASE_SYSCTL(sctp_mbuf_threshold_count); else mbuf_threshold = 1; - if (space_needed > (((mbuf_threshold - 1) * MLEN) + MHLEN)) { + if ((int)space_needed > (((mbuf_threshold - 1) * MLEN) + MHLEN)) { MCLGET(m, how); if (m == NULL) { return (NULL); } if (SCTP_BUF_IS_EXTENDED(m) == 0) { sctp_m_freem(m); return (NULL);
--- a/netwerk/sctp/src/netinet/sctp_constants.h +++ b/netwerk/sctp/src/netinet/sctp_constants.h @@ -27,17 +27,17 @@ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_constants.h 243157 2012-11-16 19:39:10Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp_constants.h 256556 2013-10-15 20:21:27Z tuexen $"); #endif #ifndef _NETINET_SCTP_CONSTANTS_H_ #define _NETINET_SCTP_CONSTANTS_H_ #if defined(__Userspace_os_Windows) extern void getwintimeofday(struct timeval *tv); #endif @@ -552,19 +552,16 @@ extern void getwintimeofday(struct timev * what is the default number of mbufs in a chain I allow before switching to * a cluster */ #define SCTP_DEFAULT_MBUFS_IN_CHAIN 5 /* How long a cookie lives in milli-seconds */ #define SCTP_DEFAULT_COOKIE_LIFE 60000 -/* resource limit of streams */ -#define MAX_SCTP_STREAMS 2048 - /* Maximum the mapping array will grow to (TSN mapping array) */ #define SCTP_MAPPING_ARRAY 512 /* size of the inital malloc on the mapping array */ #define SCTP_INITIAL_MAPPING_ARRAY 16 /* how much we grow the mapping array each call */ #define SCTP_MAPPING_ARRAY_INCR 32 @@ -697,16 +694,17 @@ extern void getwintimeofday(struct timev #define SCTP_DEF_MAX_PATH_RTX 5 #define SCTP_DEF_PATH_PF_THRESHOLD SCTP_DEF_MAX_PATH_RTX #define SCTP_DEF_PMTU_RAISE_SEC 600 /* 10 min between raise attempts */ /* How many streams I request initally by default */ #define SCTP_OSTREAM_INITIAL 10 +#define SCTP_ISTREAM_INITIAL 2048 /* * How many smallest_mtu's need to increase before a window update sack is * sent (should be a power of 2). */ /* Send window update (incr * this > hiwat). Should be a power of 2 */ #define SCTP_MINIMAL_RWND (4096) /* minimal rwnd */ @@ -771,17 +769,16 @@ extern void getwintimeofday(struct timev #define SCTP_DEFAULT_MAXSEGMENT 65535 #define SCTP_CHUNK_BUFFER_SIZE 512 #define SCTP_PARAM_BUFFER_SIZE 512 /* small chunk store for looking at chunk_list in auth */ #define SCTP_SMALL_CHUNK_STORE 260 -#define SCTP_DEFAULT_MINSEGMENT 512 /* MTU size ... if no mtu disc */ #define SCTP_HOW_MANY_SECRETS 2 /* how many secrets I keep */ #define SCTP_NUMBER_OF_SECRETS 8 /* or 8 * 4 = 32 octets */ #define SCTP_SECRET_SIZE 32 /* number of octets in a 256 bits */ /* * SCTP upper layer notifications @@ -1045,16 +1042,20 @@ extern void getwintimeofday(struct timev (((uint8_t *)&(a)->s_addr)[1] == 168))) #define IN4_ISLOOPBACK_ADDRESS(a) \ ((((uint8_t *)&(a)->s_addr)[0] == 127) && \ (((uint8_t *)&(a)->s_addr)[1] == 0) && \ (((uint8_t *)&(a)->s_addr)[2] == 0) && \ (((uint8_t *)&(a)->s_addr)[3] == 1)) +#define IN4_ISLINKLOCAL_ADDRESS(a) \ + ((((uint8_t *)&(a)->s_addr)[0] == 169) && \ + (((uint8_t *)&(a)->s_addr)[1] == 254)) + #if defined(__Userspace__) #if defined(__Userspace_os_Windows) #define SCTP_GETTIME_TIMEVAL(x) getwintimeofday(x) #define SCTP_GETPTIME_TIMEVAL(x) getwintimeofday(x) /* this doesn't seem to ever be used.. */ #else #define SCTP_GETTIME_TIMEVAL(x) gettimeofday(x, NULL) #define SCTP_GETPTIME_TIMEVAL(x) gettimeofday(x, NULL) #endif
--- a/netwerk/sctp/src/netinet/sctp_crc32.c +++ b/netwerk/sctp/src/netinet/sctp_crc32.c @@ -35,16 +35,18 @@ __FBSDID("$FreeBSD: head/sys/netinet/sctp_crc32.c 235828 2012-05-23 11:26:28Z tuexen $"); #endif #include <netinet/sctp_os.h> #include <netinet/sctp.h> #include <netinet/sctp_crc32.h> #include <netinet/sctp_pcb.h> + +#if !defined(SCTP_WITH_NO_CSUM) #if defined(__FreeBSD__) && __FreeBSD_version >= 800000 #else /** * * Routine Description: * * Computes the CRC32c checksum for the specified buffer using the slicing by 8 * algorithm over 64 bit quantities. @@ -703,18 +705,16 @@ calculate_crc32c(uint32_t crc32c, if (length < 4) { return (singletable_crc32c(crc32c, buffer, length)); } else { return (multitable_crc32c(crc32c, buffer, length)); } } #endif /* FreeBSD < 80000 || other OS */ -#if !defined(SCTP_WITH_NO_CSUM) - static uint32_t sctp_finalize_crc32c(uint32_t crc32c) { uint32_t result; #if BYTE_ORDER == BIG_ENDIAN uint8_t byte0, byte1, byte2, byte3; @@ -780,16 +780,17 @@ sctp_calculate_cksum(struct mbuf *m, uin at = SCTP_BUF_NEXT(at); } base = sctp_finalize_crc32c(base); return (base); } #endif /* !defined(SCTP_WITH_NO_CSUM) */ +#if defined(__FreeBSD__) void sctp_delayed_cksum(struct mbuf *m, uint32_t offset) { #if defined(SCTP_WITH_NO_CSUM) #ifdef INVARIANTS panic("sctp_delayed_cksum() called when using no SCTP CRC."); #endif #else @@ -808,9 +809,10 @@ sctp_delayed_cksum(struct mbuf *m, uint3 * behavior may be to insert the checksum in the appropriate * next mbuf in the chain. */ return; } *(uint32_t *) (m->m_data + offset) = checksum; #endif } +#endif
--- a/netwerk/sctp/src/netinet/sctp_crc32.h +++ b/netwerk/sctp/src/netinet/sctp_crc32.h @@ -37,16 +37,18 @@ #ifndef _NETINET_SCTP_CRC32_H_ #define _NETINET_SCTP_CRC32_H_ #if defined(_KERNEL) #if !defined(SCTP_WITH_NO_CSUM) uint32_t sctp_calculate_cksum(struct mbuf *, uint32_t); #endif +#if defined(__FreeBSD__) void sctp_delayed_cksum(struct mbuf *, uint32_t offset); +#endif #endif /* _KERNEL */ #if defined(__Userspace__) #if !defined(SCTP_WITH_NO_CSUM) uint32_t sctp_calculate_cksum(struct mbuf *, uint32_t); #endif #endif #endif /* __crc32c_h__ */
deleted file mode 100755 --- a/netwerk/sctp/src/netinet/sctp_dtrace_declare.h +++ /dev/null @@ -1,89 +0,0 @@ -/*- - * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved. - * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * a) Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * b) Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the distribution. - * - * c) Neither the name of Cisco Systems, Inc. nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifdef __FreeBSD__ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_dtrace_declare.h 235828 2012-05-23 11:26:28Z tuexen $"); -#endif - -#ifndef _NETINET_SCTP_DTRACE_DECLARE_H_ -#define _NETINET_SCTP_DTRACE_DECLARE_H_ - -#if defined(__FreeBSD__) && __FreeBSD_version >= 803000 -#include "opt_kdtrace.h" -#include <sys/kernel.h> -#include <sys/sdt.h> - -/* Declare the SCTP provider */ -SDT_PROVIDER_DECLARE(sctp); - -/* The probes we have so far: */ - -/* One to track a net's cwnd */ -/* initial */ -SDT_PROBE_DECLARE(sctp, cwnd, net, init); -/* update at a ack -- increase */ -SDT_PROBE_DECLARE(sctp, cwnd, net, ack); -/* update at a fast retransmit -- decrease */ -SDT_PROBE_DECLARE(sctp, cwnd, net, fr); -/* update at a time-out -- decrease */ -SDT_PROBE_DECLARE(sctp, cwnd, net, to); -/* update at a burst-limit -- decrease */ -SDT_PROBE_DECLARE(sctp, cwnd, net, bl); -/* update at a ECN -- decrease */ -SDT_PROBE_DECLARE(sctp, cwnd, net, ecn); -/* update at a Packet-Drop -- decrease */ -SDT_PROBE_DECLARE(sctp, cwnd, net, pd); -/* Rttvar probe declaration */ -SDT_PROBE_DECLARE(sctp, cwnd, net, rttvar); -SDT_PROBE_DECLARE(sctp, cwnd, net, rttstep); - -/* One to track an associations rwnd */ -SDT_PROBE_DECLARE(sctp, rwnd, assoc, val); - -/* One to track a net's flight size */ -SDT_PROBE_DECLARE(sctp, flightsize, net, val); - -/* One to track an associations flight size */ -SDT_PROBE_DECLARE(sctp, flightsize, assoc, val); - - - - - - -#else -/* All other platforms not defining dtrace probes */ -#ifndef SDT_PROBE -#define SDT_PROBE(a, b, c, d, e, f, g, h, i) -#endif -#endif -#endif
deleted file mode 100755 --- a/netwerk/sctp/src/netinet/sctp_dtrace_define.h +++ /dev/null @@ -1,243 +0,0 @@ -/*- - * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved. - * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * a) Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * b) Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the distribution. - * - * c) Neither the name of Cisco Systems, Inc. nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifdef __FreeBSD__ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_dtrace_define.h 235828 2012-05-23 11:26:28Z tuexen $"); -#endif - -#ifndef _NETINET_SCTP_DTRACE_DEFINE_H_ -#define _NETINET_SCTP_DTRACE_DEFINE_H_ - -#if defined(__FreeBSD__) && __FreeBSD_version >= 803000 -#include "opt_kdtrace.h" -#include <sys/kernel.h> -#include <sys/sdt.h> - -SDT_PROVIDER_DEFINE(sctp); - -/********************************************************/ -/* Cwnd probe - tracks changes in the congestion window on a netp */ -/********************************************************/ -/* Initial */ -SDT_PROBE_DEFINE(sctp, cwnd, net, init, init); -/* The Vtag for this end */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, init, 0, "uint32_t"); -/* The port number of the local side << 16 | port number of remote - * in network byte order. - */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, init, 1, "uint32_t"); -/* The pointer to the struct sctp_nets * changing */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, init, 2, "uintptr_t"); -/* The old value of the cwnd */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, init, 3, "int"); -/* The new value of the cwnd */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, init, 4, "int"); - - -/* ACK-INCREASE */ -SDT_PROBE_DEFINE(sctp, cwnd, net, ack, ack); -/* The Vtag for this end */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, ack, 0, "uint32_t"); -/* The port number of the local side << 16 | port number of remote - * in network byte order. - */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, ack, 1, "uint32_t"); -/* The pointer to the struct sctp_nets * changing */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, ack, 2, "uintptr_t"); -/* The old value of the cwnd */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, ack, 3, "int"); -/* The new value of the cwnd */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, ack, 4, "int"); - - -/* ACK-INCREASE */ -SDT_PROBE_DEFINE(sctp, cwnd, net, rttvar, rttvar); -/* The Vtag << 32 | localport << 16 | remoteport */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, rttvar, 0, "uint64_t"); -/* obw | nbw */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, rttvar, 1, "uint64_t"); -/* bwrtt | newrtt */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, rttvar, 2, "uint64_t"); -/* flight */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, rttvar, 3, "uint64_t"); -/* (cwnd << 32) | point << 16 | retval(0/1) */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, rttvar, 4, "uint64_t"); - - -SDT_PROBE_DEFINE(sctp, cwnd, net, rttstep, rttstep); -/* The Vtag << 32 | localport << 16 | remoteport */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, rttstep, 0, "uint64_t"); -/* obw | nbw */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, rttstep, 1, "uint64_t"); -/* bwrtt | nrtt */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, rttstep, 2, "uint64_t"); -/* cwnd_saved | stepcnt << 16 | oldstep */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, rttstep, 3, "uint64_t"); -/* (cwnd << 32) | point << 16 | retval(0/1) */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, rttstep, 4, "uint64_t"); - - -/* FastRetransmit-DECREASE */ -SDT_PROBE_DEFINE(sctp, cwnd, net, fr, fr); -/* The Vtag for this end */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, fr, 0, "uint32_t"); -/* The port number of the local side << 16 | port number of remote - * in network byte order. - */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, fr, 1, "uint32_t"); -/* The pointer to the struct sctp_nets * changing */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, fr, 2, "uintptr_t"); -/* The old value of the cwnd */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, fr, 3, "int"); -/* The new value of the cwnd */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, fr, 4, "int"); - - -/* TimeOut-DECREASE */ -SDT_PROBE_DEFINE(sctp, cwnd, net, to, to); -/* The Vtag for this end */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, to, 0, "uint32_t"); -/* The port number of the local side << 16 | port number of remote - * in network byte order. - */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, to, 1, "uint32_t"); -/* The pointer to the struct sctp_nets * changing */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, to, 2, "uintptr_t"); -/* The old value of the cwnd */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, to, 3, "int"); -/* The new value of the cwnd */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, to, 4, "int"); - - -/* BurstLimit-DECREASE */ -SDT_PROBE_DEFINE(sctp, cwnd, net, bl, bl); -/* The Vtag for this end */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, bl, 0, "uint32_t"); -/* The port number of the local side << 16 | port number of remote - * in network byte order. - */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, bl, 1, "uint32_t"); -/* The pointer to the struct sctp_nets * changing */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, bl, 2, "uintptr_t"); -/* The old value of the cwnd */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, bl, 3, "int"); -/* The new value of the cwnd */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, bl, 4, "int"); - - -/* ECN-DECREASE */ -SDT_PROBE_DEFINE(sctp, cwnd, net, ecn, ecn); -/* The Vtag for this end */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, ecn, 0, "uint32_t"); -/* The port number of the local side << 16 | port number of remote - * in network byte order. - */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, ecn, 1, "uint32_t"); -/* The pointer to the struct sctp_nets * changing */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, ecn, 2, "uintptr_t"); -/* The old value of the cwnd */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, ecn, 3, "int"); -/* The new value of the cwnd */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, ecn, 4, "int"); - - -/* PacketDrop-DECREASE */ -SDT_PROBE_DEFINE(sctp, cwnd, net, pd, pd); -/* The Vtag for this end */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, pd, 0, "uint32_t"); -/* The port number of the local side << 16 | port number of remote - * in network byte order. - */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, pd, 1, "uint32_t"); -/* The pointer to the struct sctp_nets * changing */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, pd, 2, "uintptr_t"); -/* The old value of the cwnd */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, pd, 3, "int"); -/* The new value of the cwnd */ -SDT_PROBE_ARGTYPE(sctp, cwnd, net, pd, 4, "int"); - - - -/********************************************************/ -/* Rwnd probe - tracks changes in the receiver window for an assoc */ -/********************************************************/ -SDT_PROBE_DEFINE(sctp, rwnd, assoc, val, val); -/* The Vtag for this end */ -SDT_PROBE_ARGTYPE(sctp, rwnd, assoc, val, 0, "uint32_t"); -/* The port number of the local side << 16 | port number of remote - * in network byte order. - */ -SDT_PROBE_ARGTYPE(sctp, rwnd, assoc, val, 1, "uint32_t"); -/* The up/down amount */ -SDT_PROBE_ARGTYPE(sctp, rwnd, assoc, val, 2, "int"); -/* The new value of the cwnd */ -SDT_PROBE_ARGTYPE(sctp, rwnd, assoc, val, 3, "int"); - -/********************************************************/ -/* flight probe - tracks changes in the flight size on a net or assoc */ -/********************************************************/ -SDT_PROBE_DEFINE(sctp, flightsize, net, val, val); -/* The Vtag for this end */ -SDT_PROBE_ARGTYPE(sctp, flightsize, net, val, 0, "uint32_t"); -/* The port number of the local side << 16 | port number of remote - * in network byte order. - */ -SDT_PROBE_ARGTYPE(sctp, flightsize, net, val, 1, "uint32_t"); -/* The pointer to the struct sctp_nets * changing */ -SDT_PROBE_ARGTYPE(sctp, flightsize, net, val, 2, "uintptr_t"); -/* The up/down amount */ -SDT_PROBE_ARGTYPE(sctp, flightsize, net, val, 3, "int"); -/* The new value of the cwnd */ -SDT_PROBE_ARGTYPE(sctp, flightsize, net, val, 4, "int"); -/********************************************************/ -/* The total flight version */ -/********************************************************/ -SDT_PROBE_DEFINE(sctp, flightsize, assoc, val, val); -/* The Vtag for this end */ -SDT_PROBE_ARGTYPE(sctp, flightsize, assoc, val, 0, "uint32_t"); -/* The port number of the local side << 16 | port number of remote - * in network byte order. - */ -SDT_PROBE_ARGTYPE(sctp, flightsize, assoc, val, 1, "uint32_t"); -/* The up/down amount */ -SDT_PROBE_ARGTYPE(sctp, flightsize, assoc, val, 2, "int"); -/* The new value of the cwnd */ -SDT_PROBE_ARGTYPE(sctp, flightsize, assoc, val, 3, "int"); -#else /* to #if Freebsd */ -/* All other platforms not defining dtrace probes */ -#ifndef SDT_PROBE -#define SDT_PROBE(a, b, c, d, e, f, g, h, i) -#endif - -#endif - -#endif
deleted file mode 100755 --- a/netwerk/sctp/src/netinet/sctp_hashdriver.c +++ /dev/null @@ -1,284 +0,0 @@ -/*- - * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved. - * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved. - * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * a) Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * b) Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the distribution. - * - * c) Neither the name of Cisco Systems, Inc. nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifdef __FreeBSD__ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); -#endif - -#include <netinet/sctp_os.h> - -#include <netinet/sctp_constants.h> -#ifdef USE_MD5 -#include <crypto/md5.h> -#else -#if !defined(__APPLE__) && !defined(__Userspace__) -#include <netinet/sctp_sha1.h> -#endif -#endif /* USE_MD5 */ -#include <netinet/sctp_hashdriver.h> - -/* - * Main driver for SCTP's hashing. passing a two pointers and two lengths, - * returning a digest pointer filled. The md5 code was taken directly from - * the RFC (2104) so to understand it you may want to go look at the RFC - * referenced in the SCTP spec. We did modify this code to either user OURs - * implementation of SLA1 or the MD5 that comes from its RFC. SLA1 may have - * IPR issues so you need to check in to this if you wish to use it... Or at - * least that is what the FIP-180.1 web page says. - */ - -void -sctp_hash_digest(char *key, int key_len, char *text, int text_len, - unsigned char *digest) -{ -#ifdef USE_MD5 - md5_ctxt context; - -#else -#if defined(__APPLE__) || defined(__Userspace__) - SHA1_CTX context; -#else - struct sha1_context context; -#endif - -#endif /* USE_MD5 */ - /* inner padding - key XORd with ipad */ - unsigned char k_ipad[65]; - - /* outer padding - key XORd with opad */ - unsigned char k_opad[65]; - unsigned char tk[20]; - int i; - - if (key_len > 64) { -#ifdef USE_MD5 - md5_ctxt tctx; - - MD5Init(&tctx); - MD5Update(&tctx, key, key_len); - MD5Final(tk, &tctx); - key = tk; - key_len = 16; -#else -#if defined(__APPLE__) || defined(__Userspace__) - SHA1_CTX tctx; -#else - struct sha1_context tctx; -#endif - - SHA1_Init(&tctx); - SHA1_Update(&tctx, (unsigned char *)key, key_len); - SHA1_Final(tk, &tctx); - key = (char *)tk; - key_len = 20; -#endif /* USE_MD5 */ - } - /* - * the HMAC_MD5 transform looks like: - * - * MD5(K XOR opad, MD5(K XOR ipad, text)) - * - * where K is an n byte key ipad is the byte 0x36 repeated 64 times - * opad is the byte 0x5c repeated 64 times and text is the data - * being protected - */ - - /* start out by storing key in pads */ - bzero(k_ipad, sizeof k_ipad); - bzero(k_opad, sizeof k_opad); - bcopy(key, k_ipad, key_len); - bcopy(key, k_opad, key_len); - - /* XOR key with ipad and opad values */ - for (i = 0; i < 64; i++) { - k_ipad[i] ^= 0x36; - k_opad[i] ^= 0x5c; - } - /* - * perform inner MD5 - */ -#ifdef USE_MD5 - MD5Init(&context); /* init context for 1st pass */ - MD5Update(&context, k_ipad, 64); /* start with inner pad */ - MD5Update(&context, text, text_len); /* then text of datagram */ - MD5Final(digest, &context); /* finish up 1st pass */ -#else - SHA1_Init(&context); /* init context for 1st pass */ - SHA1_Update(&context, k_ipad, 64); /* start with inner pad */ - SHA1_Update(&context, - (unsigned char *)text, - text_len); /* then text of datagram */ - SHA1_Final(digest, &context); /* finish up 1st pass */ -#endif /* USE_MD5 */ - - /* - * perform outer MD5 - */ -#ifdef USE_MD5 - MD5Init(&context); /* init context for 2nd pass */ - MD5Update(&context, k_opad, 64); /* start with outer pad */ - MD5Update(&context, digest, 16); /* then results of 1st hash */ - MD5Final(digest, &context); /* finish up 2nd pass */ -#else - SHA1_Init(&context); /* init context for 2nd pass */ - SHA1_Update(&context, k_opad, 64); /* start with outer pad */ - SHA1_Update(&context, - (unsigned char *)digest, 20); /* then results of 1st hash */ - SHA1_Final(digest, &context); /* finish up 2nd pass */ -#endif /* USE_MD5 */ -} - -void -sctp_hash_digest_m(char *key, int key_len, struct mbuf *m, int offset, - unsigned char *digest) -{ - struct mbuf *m_at; - -#ifdef USE_MD5 - md5_ctxt context; - -#else -#if defined(__APPLE__) || defined(__Userspace__) - SHA1_CTX context; -#else - struct sha1_context context; -#endif - -#endif /* USE_MD5 */ - /* inner padding - key XORd with ipad */ - unsigned char k_ipad[65]; - - /* outer padding - key XORd with opad */ - unsigned char k_opad[65]; - unsigned char tk[20]; - int i; - - if (key_len > 64) { -#ifdef USE_MD5 - md5_ctxt tctx; - - MD5Init(&tctx); - MD5Update(&tctx, key, key_len); - MD5Final(tk, &tctx); - key = tk; - key_len = 16; -#else -#if defined(__APPLE__) || defined(__Userspace__) - SHA1_CTX tctx; -#else - struct sha1_context tctx; -#endif - - SHA1_Init(&tctx); - SHA1_Update(&tctx, (unsigned char *)key, key_len); - SHA1_Final(tk, &tctx); - key = (char *)tk; - key_len = 20; -#endif /* USE_MD5 */ - } - /* - * the HMAC_MD5 transform looks like: - * - * MD5(K XOR opad, MD5(K XOR ipad, text)) - * - * where K is an n byte key ipad is the byte 0x36 repeated 64 times - * opad is the byte 0x5c repeated 64 times and text is the data - * being protected - */ - - /* start out by storing key in pads */ - bzero(k_ipad, sizeof k_ipad); - bzero(k_opad, sizeof k_opad); - bcopy(key, k_ipad, key_len); - bcopy(key, k_opad, key_len); - - /* XOR key with ipad and opad values */ - for (i = 0; i < 64; i++) { - k_ipad[i] ^= 0x36; - k_opad[i] ^= 0x5c; - } - - /* find the correct mbuf and offset into mbuf */ - m_at = m; - while ((m_at != NULL) && (offset > SCTP_BUF_LEN(m_at))) { - offset -= SCTP_BUF_LEN(m_at); /* update remaining offset left */ - m_at = SCTP_BUF_NEXT(m_at); - } - /* - * perform inner MD5 - */ -#ifdef USE_MD5 - MD5Init(&context); /* init context for 1st pass */ - MD5Update(&context, k_ipad, 64); /* start with inner pad */ - /******/ - while (m_at != NULL) { - /* then text of datagram... */ - MD5Update(&context, mtod(m_at, char *)+offset, - SCTP_BUF_LEN(m_at) - offset); - /* only offset on the first mbuf */ - offset = 0; - m_at = SCTP_BUF_NEXT(m_at); - } - /******/ - MD5Final(digest, &context); /* finish up 1st pass */ -#else - SHA1_Init(&context); /* init context for 1st pass */ - SHA1_Update(&context, k_ipad, 64); /* start with inner pad */ - /******/ - while (m_at != NULL) { - /* then text of datagram */ - SHA1_Update(&context, mtod(m_at, unsigned char *)+offset, - SCTP_BUF_LEN(m_at) - offset); - /* only offset on the first mbuf */ - offset = 0; - m_at = SCTP_BUF_NEXT(m_at); - } - /******/ - SHA1_Final(digest, &context); /* finish up 1st pass */ -#endif /* USE_MD5 */ - - /* - * perform outer MD5 - */ -#ifdef USE_MD5 - MD5Init(&context); /* init context for 2nd pass */ - MD5Update(&context, k_opad, 64); /* start with outer pad */ - MD5Update(&context, digest, 16); /* then results of 1st hash */ - MD5Final(digest, &context); /* finish up 2nd pass */ -#else - SHA1_Init(&context); /* init context for 2nd pass */ - SHA1_Update(&context, k_opad, 64); /* start with outer pad */ - SHA1_Update(&context, digest, 20); /* then results of 1st hash */ - SHA1_Final(digest, &context); /* finish up 2nd pass */ -#endif /* USE_MD5 */ -}
deleted file mode 100755 --- a/netwerk/sctp/src/netinet/sctp_hashdriver.h +++ /dev/null @@ -1,46 +0,0 @@ -/*- - * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved. - * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved. - * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * a) Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * b) Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the distribution. - * - * c) Neither the name of Cisco Systems, Inc. nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifdef __FreeBSD__ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); -#endif - -#ifndef _NETINET_SCTP_HASHDRIVER_H_ -#define _NETINET_SCTP_HASHDRIVER_H_ - - -void sctp_hash_digest(char *, int, char *, int, unsigned char *); - -void sctp_hash_digest_m(char *, int, struct mbuf *, int, unsigned char *); - -#endif
--- a/netwerk/sctp/src/netinet/sctp_indata.c +++ b/netwerk/sctp/src/netinet/sctp_indata.c @@ -27,17 +27,17 @@ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_indata.c 246674 2013-02-11 13:57:03Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp_indata.c 258228 2013-11-16 16:09:09Z tuexen $"); #endif #include <netinet/sctp_os.h> #include <netinet/sctp_var.h> #include <netinet/sctp_sysctl.h> #include <netinet/sctp_pcb.h> #include <netinet/sctp_header.h> #include <netinet/sctputil.h> @@ -801,23 +801,22 @@ sctp_deliver_reasm_check(struct sctp_tcb if ((chk->rec.data.rcv_flags & SCTP_DATA_FIRST_FRAG) && (nxt_todel == chk->rec.data.stream_seq || (chk->rec.data.rcv_flags & SCTP_DATA_UNORDERED))) { /* * Yep the first one is here and its ok to deliver * but should we? */ if (stcb->sctp_socket) { - pd_point = min(SCTP_SB_LIMIT_RCV(stcb->sctp_socket), + pd_point = min(SCTP_SB_LIMIT_RCV(stcb->sctp_socket) >> SCTP_PARTIAL_DELIVERY_SHIFT, stcb->sctp_ep->partial_delivery_point); } else { pd_point = stcb->sctp_ep->partial_delivery_point; } if (sctp_is_all_msg_on_reasm(asoc, &tsize) || (tsize >= pd_point)) { - /* * Yes, we setup to start reception, by * backing down the TSN just in case we * can't deliver. If we */ asoc->fragmented_delivery_inprogress = 1; asoc->tsn_last_delivered = chk->rec.data.TSN_seq - 1; @@ -1427,17 +1426,16 @@ sctp_does_tsn_belong_to_reasm(struct sct return (0); } } } } return (0); } - static int sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc, struct mbuf **m, int offset, struct sctp_data_chunk *ch, int chk_length, struct sctp_nets *net, uint32_t *high_tsn, int *abort_flag, int *break_flag, int last_chunk) { /* Process a data chunk */ /* struct sctp_tmit_chunk *chk; */ @@ -1737,17 +1735,16 @@ sctp_process_a_data_chunk(struct sctp_tc * And there is room for it in the socket buffer. Lets just * stuff it up the buffer.... */ /* It would be nice to avoid this copy if we could :< */ sctp_alloc_a_readq(stcb, control); sctp_build_readq_entry_mac(control, stcb, asoc->context, net, tsn, protocol_id, - stcb->asoc.context, strmno, strmseq, chunk_flags, dmbuf); if (control == NULL) { goto failed_express_del; } SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, gap); if (SCTP_TSN_GT(tsn, asoc->highest_tsn_inside_nr_map)) { @@ -1799,17 +1796,16 @@ failed_express_del: goto failed_pdapi_express_del; } SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, gap); if (SCTP_TSN_GT(tsn, asoc->highest_tsn_inside_nr_map)) { asoc->highest_tsn_inside_nr_map = tsn; } SCTP_STAT_INCR(sctps_recvexpressm); - control->sinfo_tsn = tsn; asoc->tsn_last_delivered = tsn; asoc->fragment_flags = chunk_flags; asoc->tsn_of_pdapi_last_delivered = tsn; asoc->last_flags_delivered = chunk_flags; asoc->last_strm_seq_delivered = strmseq; asoc->last_strm_no_delivered = strmno; if (end) { /* clean up the flags and such */ @@ -1863,17 +1859,16 @@ failed_express_del: chk->send_size = the_len; chk->whoTo = net; atomic_add_int(&net->ref_count, 1); chk->data = dmbuf; } else { sctp_alloc_a_readq(stcb, control); sctp_build_readq_entry_mac(control, stcb, asoc->context, net, tsn, protocol_id, - stcb->asoc.context, strmno, strmseq, chunk_flags, dmbuf); if (control == NULL) { /* No memory so we drop the chunk */ SCTP_STAT_INCR(sctps_nomem); if (last_chunk == 0) { /* we copied it, free the copy */ @@ -2501,17 +2496,17 @@ sctp_service_queues(struct sctp_tcb *stc */ /* * Before we start though either all of the message should * be here or the socket buffer max or nothing on the * delivery queue and something can be delivered. */ if (stcb->sctp_socket) { - pd_point = min(SCTP_SB_LIMIT_RCV(stcb->sctp_socket), + pd_point = min(SCTP_SB_LIMIT_RCV(stcb->sctp_socket) >> SCTP_PARTIAL_DELIVERY_SHIFT, stcb->sctp_ep->partial_delivery_point); } else { pd_point = stcb->sctp_ep->partial_delivery_point; } if (sctp_is_all_msg_on_reasm(asoc, &tsize) || (tsize >= pd_point)) { asoc->fragmented_delivery_inprogress = 1; asoc->tsn_last_delivered = chk->rec.data.TSN_seq - 1; asoc->str_of_pdapi = chk->rec.data.stream_number; @@ -3690,16 +3685,17 @@ sctp_try_advance_peer_ack_point(struct s } static int sctp_fs_audit(struct sctp_association *asoc) { struct sctp_tmit_chunk *chk; int inflight = 0, resend = 0, inbetween = 0, acked = 0, above = 0; int entry_flight, entry_cnt, ret; + entry_flight = asoc->total_flight; entry_cnt = asoc->total_flight_count; ret = 0; if (asoc->pr_sctp_cnt >= asoc->sent_queue_cnt) return (0); TAILQ_FOREACH(chk, &asoc->sent_queue, sctp_next) { @@ -4738,17 +4734,17 @@ sctp_handle_sack(struct mbuf *m, int off asoc->strmout[tp1->rec.data.stream_number].chunks_on_queues--; #ifdef INVARIANTS } else { panic("No chunks on the queues for sid %u.", tp1->rec.data.stream_number); #endif } } TAILQ_REMOVE(&asoc->sent_queue, tp1, sctp_next); - if (tp1->pr_sctp_on) { + if (PR_SCTP_ENABLED(tp1->flags)) { if (asoc->pr_sctp_cnt != 0) asoc->pr_sctp_cnt--; } asoc->sent_queue_cnt--; if (tp1->data) { /* sa_ignore NO_NULL_CHK */ sctp_free_bufspace(stcb, asoc, tp1, 1); sctp_m_freem(tp1->data);
--- a/netwerk/sctp/src/netinet/sctp_indata.h +++ b/netwerk/sctp/src/netinet/sctp_indata.h @@ -27,41 +27,41 @@ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_indata.h 237715 2012-06-28 16:01:08Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp_indata.h 252585 2013-07-03 18:48:43Z tuexen $"); #endif #ifndef _NETINET_SCTP_INDATA_H_ #define _NETINET_SCTP_INDATA_H_ #if defined(_KERNEL) || defined(__Userspace__) struct sctp_queued_to_read * sctp_build_readq_entry(struct sctp_tcb *stcb, struct sctp_nets *net, uint32_t tsn, uint32_t ppid, uint32_t context, uint16_t stream_no, uint16_t stream_seq, uint8_t flags, struct mbuf *dm); -#define sctp_build_readq_entry_mac(_ctl, in_it, a, net, tsn, ppid, context, stream_no, stream_seq, flags, dm) do { \ +#define sctp_build_readq_entry_mac(_ctl, in_it, context, net, tsn, ppid, stream_no, stream_seq, flags, dm) do { \ if (_ctl) { \ atomic_add_int(&((net)->ref_count), 1); \ (_ctl)->sinfo_stream = stream_no; \ (_ctl)->sinfo_ssn = stream_seq; \ (_ctl)->sinfo_flags = (flags << 8); \ (_ctl)->sinfo_ppid = ppid; \ - (_ctl)->sinfo_context = a; \ + (_ctl)->sinfo_context = context; \ (_ctl)->sinfo_timetolive = 0; \ (_ctl)->sinfo_tsn = tsn; \ (_ctl)->sinfo_cumtsn = tsn; \ (_ctl)->sinfo_assoc_id = sctp_get_associd((in_it)); \ (_ctl)->length = 0; \ (_ctl)->held_length = 0; \ (_ctl)->whoFrom = net; \ (_ctl)->data = dm; \
--- a/netwerk/sctp/src/netinet/sctp_input.c +++ b/netwerk/sctp/src/netinet/sctp_input.c @@ -27,17 +27,17 @@ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_input.c 246595 2013-02-09 17:26:14Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp_input.c 262252 2014-02-20 20:14:43Z tuexen $"); #endif #include <netinet/sctp_os.h> #include <netinet/sctp_var.h> #include <netinet/sctp_sysctl.h> #include <netinet/sctp_pcb.h> #include <netinet/sctp_header.h> #include <netinet/sctputil.h> @@ -407,35 +407,31 @@ sctp_process_init(struct sctp_init_chunk ctl->whoFrom = NULL; sctp_m_freem(ctl->data); ctl->data = NULL; sctp_free_a_readq(stcb, ctl); } } SCTP_FREE(asoc->strmin, SCTP_M_STRMI); } - asoc->streamincnt = ntohs(init->num_outbound_streams); - if (asoc->streamincnt > MAX_SCTP_STREAMS) { - asoc->streamincnt = MAX_SCTP_STREAMS; + if (asoc->max_inbound_streams > ntohs(init->num_outbound_streams)) { + asoc->streamincnt = ntohs(init->num_outbound_streams); + } else { + asoc->streamincnt = asoc->max_inbound_streams; } SCTP_MALLOC(asoc->strmin, struct sctp_stream_in *, asoc->streamincnt * sizeof(struct sctp_stream_in), SCTP_M_STRMI); if (asoc->strmin == NULL) { /* we didn't get memory for the streams! */ SCTPDBG(SCTP_DEBUG_INPUT2, "process_init: couldn't get memory for the streams!\n"); return (-1); } for (i = 0; i < asoc->streamincnt; i++) { asoc->strmin[i].stream_no = i; asoc->strmin[i].last_sequence_delivered = 0xffff; - /* - * U-stream ranges will be set when the cookie is unpacked. - * Or for the INIT sender they are un set (if pr-sctp not - * supported) when the INIT-ACK arrives. - */ TAILQ_INIT(&asoc->strmin[i].inqueue); asoc->strmin[i].delivery_started = 0; } /* * load_address_from_init will put the addresses into the * association when the COOKIE is processed or the INIT-ACK is * processed. Both types of COOKIE's existing and new call this * routine. It will remove addresses that are no longer in the @@ -463,17 +459,16 @@ sctp_process_init_ack(struct mbuf *m, in struct sctp_association *asoc; struct mbuf *op_err; int retval, abort_flag; uint32_t initack_limit; int nat_friendly = 0; /* First verify that we have no illegal param's */ abort_flag = 0; - op_err = NULL; op_err = sctp_arethere_unrecognized_parameters(m, (offset + sizeof(struct sctp_init_chunk)), &abort_flag, (struct sctp_chunkhdr *)cp, &nat_friendly); if (abort_flag) { /* Send an abort and notify peer */ sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); *abort_no_unlock = 1; @@ -1063,22 +1058,23 @@ sctp_handle_shutdown_ack(struct sctp_shu return; } #endif sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket); #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) SCTP_SOCKET_UNLOCK(so, 1); #endif } - /* are the queues empty? */ +#ifdef INVARIANTS if (!TAILQ_EMPTY(&asoc->send_queue) || !TAILQ_EMPTY(&asoc->sent_queue) || !stcb->asoc.ss_functions.sctp_ss_is_empty(stcb, asoc)) { - sctp_report_all_outbound(stcb, 0, 0, SCTP_SO_NOT_LOCKED); - } + panic("Queues are not empty when handling SHUTDOWN-ACK"); + } +#endif /* stop the timer */ sctp_timer_stop(SCTP_TIMER_TYPE_SHUTDOWN, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INPUT+SCTP_LOC_9); /* send SHUTDOWN-COMPLETE */ sctp_send_shutdown_complete(stcb, net, 0); /* notify upper layer protocol */ if (stcb->sctp_socket) { if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) { @@ -1609,17 +1605,17 @@ sctp_process_cookie_existing(struct mbuf * tag t'. Which means we would throw away the CE and send * ours instead. Basically this is case C (throw away side). */ if (how_indx < sizeof(asoc->cookie_how)) asoc->cookie_how[how_indx] = 17; return (NULL); } - switch SCTP_GET_STATE(asoc) { + switch (SCTP_GET_STATE(asoc)) { case SCTP_STATE_COOKIE_WAIT: case SCTP_STATE_COOKIE_ECHOED: /* * INIT was sent but got a COOKIE_ECHO with the * correct tags... just accept it...but we must * process the init so that we can make sure we * have the right seq no's. */ @@ -1921,30 +1917,34 @@ sctp_process_cookie_existing(struct mbuf return (stcb); } if ((ntohl(initack_cp->init.initiate_tag) != asoc->my_vtag && ntohl(init_cp->init.initiate_tag) != asoc->peer_vtag) && cookie->tie_tag_my_vtag == asoc->my_vtag_nonce && cookie->tie_tag_peer_vtag == asoc->peer_vtag_nonce && cookie->tie_tag_peer_vtag != 0) { struct sctpasochead *head; +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) + struct socket *so; +#endif + if (asoc->peer_supports_nat) { - /* This is a gross gross hack. - * just call the cookie_new code since we - * are allowing a duplicate association. I hope - * this works... - */ - return (sctp_process_cookie_new(m, iphlen, offset, src, dst, - sh, cookie, cookie_len, - inp, netp, init_src,notification, - auth_skipped, auth_offset, auth_len, + /* This is a gross gross hack. + * Just call the cookie_new code since we + * are allowing a duplicate association. + * I hope this works... + */ + return (sctp_process_cookie_new(m, iphlen, offset, src, dst, + sh, cookie, cookie_len, + inp, netp, init_src,notification, + auth_skipped, auth_offset, auth_len, #if defined(__FreeBSD__) - use_mflowid, mflowid, -#endif - vrf_id, port)); + use_mflowid, mflowid, +#endif + vrf_id, port)); } /* * case A in Section 5.2.4 Table 2: XXMM (peer restarted) */ /* temp code */ if (how_indx < sizeof(asoc->cookie_how)) asoc->cookie_how[how_indx] = 12; sctp_timer_stop(SCTP_TIMER_TYPE_INIT, inp, stcb, net, SCTP_FROM_SCTP_INPUT+SCTP_LOC_15); @@ -1987,24 +1987,28 @@ sctp_process_cookie_existing(struct mbuf memset(asoc->mapping_array, 0, asoc->mapping_array_size); } if (asoc->nr_mapping_array) { memset(asoc->nr_mapping_array, 0, asoc->mapping_array_size); } SCTP_TCB_UNLOCK(stcb); +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) + so = SCTP_INP_SO(stcb->sctp_ep); + SCTP_SOCKET_LOCK(so, 1); +#endif SCTP_INP_INFO_WLOCK(); SCTP_INP_WLOCK(stcb->sctp_ep); SCTP_TCB_LOCK(stcb); atomic_add_int(&stcb->asoc.refcnt, -1); /* send up all the data */ SCTP_TCB_SEND_LOCK(stcb); - sctp_report_all_outbound(stcb, 0, 1, SCTP_SO_NOT_LOCKED); + sctp_report_all_outbound(stcb, 0, 1, SCTP_SO_LOCKED); for (i = 0; i < stcb->asoc.streamoutcnt; i++) { stcb->asoc.strmout[i].chunks_on_queues = 0; stcb->asoc.strmout[i].stream_no = i; stcb->asoc.strmout[i].next_sequence_send = 0; stcb->asoc.strmout[i].last_msg_incomplete = 0; } /* process the INIT-ACK info (my info) */ asoc->my_vtag = ntohl(initack_cp->init.initiate_tag); @@ -2016,21 +2020,25 @@ sctp_process_cookie_existing(struct mbuf head = &SCTP_BASE_INFO(sctp_asochash)[SCTP_PCBHASH_ASOC(stcb->asoc.my_vtag, SCTP_BASE_INFO(hashasocmark))]; /* * put it in the bucket in the vtag hash of assoc's for the * system */ LIST_INSERT_HEAD(head, stcb, sctp_asocs); - /* process the INIT info (peer's info) */ SCTP_TCB_SEND_UNLOCK(stcb); SCTP_INP_WUNLOCK(stcb->sctp_ep); SCTP_INP_INFO_WUNLOCK(); - +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) + SCTP_SOCKET_UNLOCK(so, 1); +#endif + asoc->total_flight = 0; + asoc->total_flight_count = 0; + /* process the INIT info (peer's info) */ retval = sctp_process_init(init_cp, stcb); if (retval < 0) { if (how_indx < sizeof(asoc->cookie_how)) asoc->cookie_how[how_indx] = 13; return (NULL); } /* @@ -3330,23 +3338,24 @@ sctp_handle_shutdown_complete(struct sct SCTPDBG(SCTP_DEBUG_INPUT2, "sctp_handle_shutdown_complete: not in SCTP_STATE_SHUTDOWN_ACK_SENT --- ignore\n"); SCTP_TCB_UNLOCK(stcb); return; } /* notify upper layer protocol */ if (stcb->sctp_socket) { sctp_ulp_notify(SCTP_NOTIFY_ASSOC_DOWN, stcb, 0, NULL, SCTP_SO_NOT_LOCKED); - /* are the queues empty? they should be */ - if (!TAILQ_EMPTY(&asoc->send_queue) || - !TAILQ_EMPTY(&asoc->sent_queue) || - !stcb->asoc.ss_functions.sctp_ss_is_empty(stcb, asoc)) { - sctp_report_all_outbound(stcb, 0, 0, SCTP_SO_NOT_LOCKED); - } - } + } +#ifdef INVARIANTS + if (!TAILQ_EMPTY(&asoc->send_queue) || + !TAILQ_EMPTY(&asoc->sent_queue) || + !stcb->asoc.ss_functions.sctp_ss_is_empty(stcb, asoc)) { + panic("Queues are not empty when handling SHUTDOWN-COMPLETE"); + } +#endif /* stop the timer */ sctp_timer_stop(SCTP_TIMER_TYPE_SHUTDOWNACK, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INPUT+SCTP_LOC_22); SCTP_STAT_INCR_COUNTER32(sctps_shutdown); /* free the TCB */ SCTPDBG(SCTP_DEBUG_INPUT2, "sctp_handle_shutdown_complete: calls free-asoc\n"); #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) so = SCTP_INP_SO(stcb->sctp_ep); @@ -3594,17 +3603,17 @@ process_chunk_drop(struct sctp_tcb *stcb case SCTP_ECN_CWR: default: break; } return (0); } void -sctp_reset_in_stream(struct sctp_tcb *stcb, uint32_t number_entries, uint16_t * list) +sctp_reset_in_stream(struct sctp_tcb *stcb, uint32_t number_entries, uint16_t *list) { uint32_t i; uint16_t temp; /* * We set things to 0xffff since this is the last delivered sequence * and we will be sending in 0 after the reset. */ @@ -3622,35 +3631,34 @@ sctp_reset_in_stream(struct sctp_tcb *st for (i = 0; i < stcb->asoc.streamincnt; i++) { stcb->asoc.strmin[i].last_sequence_delivered = 0xffff; } } sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_RECV, stcb, number_entries, (void *)list, SCTP_SO_NOT_LOCKED); } static void -sctp_reset_out_streams(struct sctp_tcb *stcb, int number_entries, uint16_t * list) +sctp_reset_out_streams(struct sctp_tcb *stcb, uint32_t number_entries, uint16_t *list) { - int i; - - if (number_entries == 0) { - for (i = 0; i < stcb->asoc.streamoutcnt; i++) { - stcb->asoc.strmout[i].next_sequence_send = 0; - } - } else if (number_entries) { + uint32_t i; + uint16_t temp; + + if (number_entries > 0) { for (i = 0; i < number_entries; i++) { - uint16_t temp; - temp = ntohs(list[i]); if (temp >= stcb->asoc.streamoutcnt) { /* no such stream */ continue; } stcb->asoc.strmout[temp].next_sequence_send = 0; } + } else { + for (i = 0; i < stcb->asoc.streamoutcnt; i++) { + stcb->asoc.strmout[i].next_sequence_send = 0; + } } sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_SEND, stcb, number_entries, (void *)list, SCTP_SO_NOT_LOCKED); } struct sctp_stream_reset_out_request * sctp_find_stream_reset(struct sctp_tcb *stcb, uint32_t seq, struct sctp_tmit_chunk **bchk) { @@ -3727,17 +3735,17 @@ sctp_handle_stream_reset_response(struct uint32_t seq, uint32_t action, struct sctp_stream_reset_response *respin) { uint16_t type; int lparm_len; struct sctp_association *asoc = &stcb->asoc; struct sctp_tmit_chunk *chk; struct sctp_stream_reset_out_request *srparam; - int number_entries; + uint32_t number_entries; if (asoc->stream_reset_outstanding == 0) { /* duplicate */ return (0); } if (seq == stcb->asoc.str_reset_seq_out) { srparam = sctp_find_stream_reset(stcb, seq, &chk); if (srparam) { @@ -4074,17 +4082,17 @@ sctp_handle_str_reset_add_strm(struct sc num_stream = ntohs(str_add->number_of_streams); /* Now what would be the new total? */ if (asoc->str_reset_seq_in == seq) { num_stream += stcb->asoc.streamincnt; stcb->asoc.last_reset_action[1] = stcb->asoc.last_reset_action[0]; if (!(asoc->local_strreset_support & SCTP_ENABLE_CHANGE_ASSOC_REQ)) { asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; } else if ((num_stream > stcb->asoc.max_inbound_streams) || - (num_stream > 0xffff)) { + (num_stream > 0xffff)) { /* We must reject it they ask for to many */ denied: stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; } else { /* Ok, we can do that :-) */ struct sctp_stream_in *oldstrm; /* save off the old */ @@ -4686,18 +4694,20 @@ sctp_process_control(struct mbuf *m, int } return (NULL); } asoc = &stcb->asoc; /* ABORT and SHUTDOWN can use either v_tag... */ if ((ch->chunk_type == SCTP_ABORT_ASSOCIATION) || (ch->chunk_type == SCTP_SHUTDOWN_COMPLETE) || (ch->chunk_type == SCTP_PACKET_DROPPED)) { - if ((vtag_in == asoc->my_vtag) || - ((ch->chunk_flags & SCTP_HAD_NO_TCB) && + /* Take the T-bit always into account. */ + if ((((ch->chunk_flags & SCTP_HAD_NO_TCB) == 0) && + (vtag_in == asoc->my_vtag)) || + (((ch->chunk_flags & SCTP_HAD_NO_TCB) == SCTP_HAD_NO_TCB) && (vtag_in == asoc->peer_vtag))) { /* this is valid */ } else { /* drop this packet... */ SCTP_STAT_INCR(sctps_badvtag); if (locked_tcb) { SCTP_TCB_UNLOCK(locked_tcb); } @@ -5699,16 +5709,17 @@ sctp_process_control(struct mbuf *m, int #ifdef __GNUC__ __attribute__((noinline)) #endif void sctp_validate_no_locks(struct sctp_inpcb *inp) { #ifndef __APPLE__ struct sctp_tcb *lstcb; + LIST_FOREACH(lstcb, &inp->sctp_asoc_list, sctp_tcblist) { if (mtx_owned(&lstcb->tcb_mtx)) { panic("Own lock on stcb at return from input"); } } if (mtx_owned(&inp->inp_create_mtx)) { panic("Own create lock on inp"); } @@ -5848,26 +5859,34 @@ sctp_common_input_processing(struct mbuf * I very much doubt any of the IPSEC stuff will work but I have no * idea, so I will leave it in place. */ if (inp != NULL) { switch (dst->sa_family) { #ifdef INET case AF_INET: if (ipsec4_in_reject(m, &inp->ip_inp.inp)) { +#if defined(__FreeBSD__) && (__FreeBSD_version > 1000036) + IPSECSTAT_INC(ips_in_polvio); +#else MODULE_GLOBAL(ipsec4stat).in_polvio++; +#endif SCTP_STAT_INCR(sctps_hdrops); goto out; } break; #endif #ifdef INET6 case AF_INET6: if (ipsec6_in_reject(m, &inp->ip_inp.inp)) { +#if defined(__FreeBSD__) && (__FreeBSD_version > 1000036) + IPSEC6STAT_INC(ips_in_polvio); +#else MODULE_GLOBAL(ipsec6stat).in_polvio++; +#endif SCTP_STAT_INCR(sctps_hdrops); goto out; } break; #endif default: break; } @@ -6204,17 +6223,23 @@ sctp_input(i_pak, va_alist) } #endif #ifdef SCTP_PACKET_LOGGING if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LAST_PACKET_TRACING) { sctp_packet_log(m); } #endif #if defined(__FreeBSD__) -#if __FreeBSD_version >= 800000 +#if __FreeBSD_version > 1000049 + SCTPDBG(SCTP_DEBUG_CRCOFFLOAD, + "sctp_input(): Packet of length %d received on %s with csum_flags 0x%b.\n", + m->m_pkthdr.len, + if_name(m->m_pkthdr.rcvif), + (int)m->m_pkthdr.csum_flags, CSUM_BITS); +#elif __FreeBSD_version >= 800000 SCTPDBG(SCTP_DEBUG_CRCOFFLOAD, "sctp_input(): Packet of length %d received on %s with csum_flags 0x%x.\n", m->m_pkthdr.len, if_name(m->m_pkthdr.rcvif), m->m_pkthdr.csum_flags); #else SCTPDBG(SCTP_DEBUG_CRCOFFLOAD, "sctp_input(): Packet of length %d received on %s with csum_flags 0x%x.\n",
--- a/netwerk/sctp/src/netinet/sctp_os_userspace.h +++ b/netwerk/sctp/src/netinet/sctp_os_userspace.h @@ -39,18 +39,16 @@ * We will place them in userspace stack build directory. */ #include <errno.h> #if defined(__Userspace_os_Windows) #include <winsock2.h> #include <ws2tcpip.h> -#include <ws2ipdef.h> -#include <ws2def.h> #include <iphlpapi.h> #include <Mswsock.h> #include <Windows.h> #include "user_environment.h" typedef CRITICAL_SECTION userland_mutex_t; #if WINVER < 0x0600 enum { C_SIGNAL = 0, @@ -58,49 +56,58 @@ enum { C_MAX_EVENTS = 2 }; typedef struct { u_int waiters_count; CRITICAL_SECTION waiters_count_lock; HANDLE events_[C_MAX_EVENTS]; } userland_cond_t; +void InitializeXPConditionVariable(userland_cond_t *); +void DeleteXPConditionVariable(userland_cond_t *); +int SleepXPConditionVariable(userland_cond_t *, userland_mutex_t *); +void WakeAllXPConditionVariable(userland_cond_t *); #define InitializeConditionVariable(cond) InitializeXPConditionVariable(cond) #define DeleteConditionVariable(cond) DeleteXPConditionVariable(cond) #define SleepConditionVariableCS(cond, mtx, time) SleepXPConditionVariable(cond, mtx) #define WakeAllConditionVariable(cond) WakeAllXPConditionVariable(cond) #else #define DeleteConditionVariable(cond) typedef CONDITION_VARIABLE userland_cond_t; #endif typedef HANDLE userland_thread_t; #define ADDRESS_FAMILY unsigned __int8 #define IPVERSION 4 #define MAXTTL 255 +/* VS2010 comes with stdint.h */ +#if _MSC_VER >= 1600 +#include <stdint.h> +#else #define uint64_t unsigned __int64 +#define uint32_t unsigned __int32 +#define int32_t __int32 +#define uint16_t unsigned __int16 +#define int16_t __int16 +#define uint8_t unsigned __int8 +#define int8_t __int8 +#endif +#ifndef _SIZE_T_DEFINED +#define size_t __int32 +#endif #define u_long unsigned __int64 #define u_int unsigned __int32 -#define uint32_t unsigned __int32 #define u_int32_t unsigned __int32 -#define int32_t __int32 -#define int16_t __int16 -#define uint16_t unsigned __int16 #define u_int16_t unsigned __int16 -#define uint8_t unsigned __int8 #define u_int8_t unsigned __int8 -#define int8_t __int8 #define u_char unsigned char #define n_short unsigned __int16 #define u_short unsigned __int16 -#define ssize_t __int64 -#define size_t __int32 -#define in_addr_t unsigned __int32 -#define in_port_t unsigned __int16 #define n_time unsigned __int32 #define sa_family_t unsigned __int8 +#define ssize_t __int64 #define IFNAMSIZ 64 #define __func__ __FUNCTION__ #ifndef EWOULDBLOCK #define EWOULDBLOCK WSAEWOULDBLOCK #endif #ifndef EINPROGRESS #define EINPROGRESS WSAEINPROGRESS @@ -205,38 +212,50 @@ typedef HANDLE userland_thread_t; #define ESTALE WSAESTALE #endif #ifndef EREMOTE #define EREMOTE WSAEREMOTE #endif typedef char* caddr_t; +int Win_getifaddrs(struct ifaddrs**); #define getifaddrs(interfaces) (int)Win_getifaddrs(interfaces) -#define if_nametoindex(x) (int)win_if_nametoindex(x) +int win_if_nametoindex(const char *); +#define if_nametoindex(x) win_if_nametoindex(x) #define bzero(buf, len) memset(buf, 0, len) #define bcopy(srcKey, dstKey, len) memcpy(dstKey, srcKey, len) #define snprintf(data, size, format, name) _snprintf_s(data, size, _TRUNCATE, format, name) #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 */ #ifdef CMSG_DATA #undef CMSG_DATA #endif +/* + * The following definitions should apply iff WINVER < 0x0600 + * but that check doesn't work in all cases. So be more pedantic... + */ #define CMSG_DATA(x) WSA_CMSG_DATA(x) #define CMSG_ALIGN(x) WSA_CMSGDATA_ALIGN(x) -#if WINVER < 0x0600 +#ifndef CMSG_FIRSTHDR #define CMSG_FIRSTHDR(x) WSA_CMSG_FIRSTHDR(x) +#endif +#ifndef CMSG_NXTHDR #define CMSG_NXTHDR(x, y) WSA_CMSG_NXTHDR(x, y) +#endif +#ifndef CMSG_SPACE #define CMSG_SPACE(x) WSA_CMSG_SPACE(x) +#endif +#ifndef CMSG_LEN #define CMSG_LEN(x) WSA_CMSG_LEN(x) #endif /**** from sctp_os_windows.h ***************/ #define SCTP_IFN_IS_IFT_LOOP(ifn) ((ifn)->ifn_type == IFT_LOOP) #define SCTP_ROUTE_IS_REAL_LOOP(ro) ((ro)->ro_rt && (ro)->ro_rt->rt_ifa && (ro)->ro_rt->rt_ifa->ifa_ifp && (ro)->ro_rt->rt_ifa->ifa_ifp->if_type == IFT_LOOP) /* @@ -378,31 +397,33 @@ struct udphdr { unsigned __int16 uh_dport; unsigned __int16 uh_ulen; unsigned __int16 uh_sum; }; #else /* !defined(Userspace_os_Windows) */ #include <sys/cdefs.h> /* needed? added from old __FreeBSD__ */ #include <sys/socket.h> -#if defined(__Userspace_os_FreeBSD) || defined(__Userspace_os_OpenBSD) || defined(ANDROID) +#if defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD) || defined(__Userspace_os_Linux) || defined(__Userspace_os_NetBSD) || defined(__Userspace_os_OpenBSD) #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) #define mtx_unlock(arg1) #define mtx_assert(arg1,arg2) #define MA_OWNED 7 /* sys/mutex.h typically on FreeBSD */ #if !defined(__Userspace_os_FreeBSD) struct mtx {int dummy;}; +#if !defined(__Userspace_os_NetBSD) struct selinfo {int dummy;}; +#endif struct sx {int dummy;}; #endif #include <stdio.h> #include <string.h> /* #include <sys/param.h> in FreeBSD defines MSIZE */ /* #include <sys/ktr.h> */ /* #include <sys/systm.h> */ @@ -458,17 +479,17 @@ struct sx {int dummy;}; #include <user_ip_icmp.h> #endif /* #include <netinet/in_pcb.h> ported to userspace */ #include <user_inpcb.h> /* for getifaddrs */ #include <sys/types.h> #if !defined(__Userspace_os_Windows) -#if !defined(ANDROID) +#if defined(INET) || defined(INET6) #include <ifaddrs.h> #endif /* for ioctl */ #include <sys/ioctl.h> /* for close, etc. */ #include <unistd.h> @@ -495,17 +516,17 @@ struct sx {int dummy;}; #endif #ifdef IPSEC #include <netipsec/ipsec6.h> #endif #if !defined(__Userspace_os_Windows) #include <netinet/ip6.h> #include <netinet/icmp6.h> #endif -#if defined(__Userspace_os_Linux) || defined(__Userspace_os_Darwin) || defined(__Userspace_os_FreeBSD) || defined(__Userspace_os_OpenBSD) ||defined(__Userspace_os_Windows) +#if defined(__Userspace_os_Darwin) || defined(__Userspace_os_FreeBSD) || defined(__Userspace_os_Linux) || defined(__Userspace_os_NetBSD) || defined(__Userspace_os_OpenBSD) || defined(__Userspace_os_Windows) #include "user_ip6_var.h" #else #include <netinet6/ip6_var.h> #endif #if defined(__Userspace_os_FreeBSD) #include <netinet6/in6_pcb.h> #include <netinet6/ip6protosw.h> /* #include <netinet6/nd6.h> was a 0 byte file */ @@ -513,16 +534,18 @@ struct sx {int dummy;}; #endif #endif /* INET6 */ #if defined(HAVE_SCTP_PEELOFF_SOCKOPT) #include <sys/file.h> #include <sys/filedesc.h> #endif +#include "netinet/sctp_sha1.h" + #if __FreeBSD_version >= 700000 #include <netinet/ip_options.h> #endif #define SCTP_PRINTF(...) \ if (SCTP_BASE_VAR(debug_printf)) { \ SCTP_BASE_VAR(debug_printf)(__VA_ARGS__); \ } @@ -577,31 +600,31 @@ MALLOC_DECLARE(SCTP_M_SOCKOPT); * */ #if !defined(__Userspace_os_Darwin) #define USER_ADDR_NULL (NULL) /* FIX ME: temp */ #endif #if defined(SCTP_DEBUG) #include <netinet/sctp_constants.h> -#define SCTPDBG(level, ...) \ -{ \ - do { \ - if (SCTP_BASE_SYSCTL(sctp_debug_on) & level) { \ - SCTP_PRINTF(__VA_ARGS__); \ - } \ - } while (0); \ +#define SCTPDBG(level, ...) \ +{ \ + do { \ + if (SCTP_BASE_SYSCTL(sctp_debug_on) & level) { \ + SCTP_PRINTF(__VA_ARGS__); \ + } \ + } while (0); \ } -#define SCTPDBG_ADDR(level, addr) \ -{ \ - do { \ - if (SCTP_BASE_SYSCTL(sctp_debug_on) & level ) { \ - sctp_print_address(addr); \ - } \ - } while (0); \ +#define SCTPDBG_ADDR(level, addr) \ +{ \ + do { \ + if (SCTP_BASE_SYSCTL(sctp_debug_on) & level ) { \ + sctp_print_address(addr); \ + } \ + } while (0); \ } #else #define SCTPDBG(level, ...) #define SCTPDBG_ADDR(level, addr) #endif #ifdef SCTP_LTRACE_CHUNKS #define SCTP_LTRACE_CHK(a, b, c, d) if(sctp_logging_level & SCTP_LTRACE_CHUNK_ENABLE) CTR6(KTR_SUBSYS, "SCTP:%d[%d]:%x-%x-%x-%x", SCTP_LOG_CHUNK_PROC, 0, a, b, c, d) @@ -649,27 +672,27 @@ MALLOC_DECLARE(SCTP_M_SOCKOPT); #define SCTP_GET_IFN_VOID_FROM_ROUTE(ro) (void *)ro->ro_rt->rt_ifp #define SCTP_GET_IF_INDEX_FROM_ROUTE(ro) 1 /* compiles... TODO use routing socket to determine */ #define SCTP_ROUTE_HAS_VALID_IFN(ro) ((ro)->ro_rt && (ro)->ro_rt->rt_ifp) #endif /* * general memory allocation */ -#define SCTP_MALLOC(var, type, size, name) \ - do { \ - MALLOC(var, type, size, name, M_NOWAIT); \ - } while (0) +#define SCTP_MALLOC(var, type, size, name) \ + do { \ + MALLOC(var, type, size, name, M_NOWAIT); \ + } while (0) #define SCTP_FREE(var, type) FREE(var, type) -#define SCTP_MALLOC_SONAME(var, type, size) \ - do { \ - MALLOC(var, type, size, M_SONAME, (M_WAITOK | M_ZERO)); \ - } while (0) +#define SCTP_MALLOC_SONAME(var, type, size) \ + do { \ + MALLOC(var, type, size, M_SONAME, (M_WAITOK | M_ZERO)); \ + } while (0) #define SCTP_FREE_SONAME(var) FREE(var, M_SONAME) #define SCTP_PROCESS_STRUCT struct proc * /* * zone allocation functions */ @@ -973,82 +996,28 @@ int sctp_userspace_get_mtu_from_ifn(uint #define SCTP_SB_LIMIT_RCV(so) so->so_rcv.sb_hiwat #define SCTP_SB_LIMIT_SND(so) so->so_snd.sb_hiwat /* Future zero copy wakeup/send function */ #define SCTP_ZERO_COPY_EVENT(inp, so) /* This is re-pulse ourselves for sendbuf */ #define SCTP_ZERO_COPY_SENDQ_EVENT(inp, so) - -/* - * SCTP AUTH - */ -/* USE_SCTP_SHA1 is defined if you need sctp_sha1.[ch]. SHA1_* functions are defined - * there. On Linux, they are also defined in libcrypto.a once you install - * the libssl-dev package (on Ubuntu, at least). - */ -/* #define USE_SCTP_SHA1 */ - -/* #define HAVE_SHA2 sha2.h exists on Linux? */ - - #define SCTP_READ_RANDOM(buf, len) read_random(buf, len) - -#ifdef USE_SCTP_SHA1 -#include <netinet/sctp_sha1.h> -#else -#if 0 /*this was old _KERNEL code... */ -#include <crypto/sha1.h> -/* map standard crypto API names */ -#define SHA1_Init SHA1Init -#define SHA1_Update SHA1Update -#define SHA1_Final(x,y) SHA1Final((caddr_t)x, y) -#endif -#endif - -#if defined(HAVE_SHA2) -#include <crypto/sha2/sha2.h> -#endif -#if 0 -/* going to have to port so generic across OS's... */ -#if 1 /* openssl header files on FreeBSD 6.3 on Emulab and libssl-dev for Ubuntu */ -#include <openssl/md5.h> -#include <openssl/sha.h> -/* libssl-dev calls this SHA_CTX, but it's refered to as SHA1_CTX within the - * SCTP stack code so here we typedef (or macro?) to equate the two. - */ -typedef SHA_CTX SHA1_CTX; - -#else /* only _KERNEL? */ - -#include <sys/md5.h> -/* map standard crypto API names */ -#define MD5_Init MD5Init -#define MD5_Update MD5Update -#define MD5_Final MD5Final -#endif -#endif - +#define SCTP_SHA1_CTX struct sctp_sha1_context +#define SCTP_SHA1_INIT sctp_sha1_init +#define SCTP_SHA1_UPDATE sctp_sha1_update +#define SCTP_SHA1_FINAL(x,y) sctp_sha1_final((unsigned char *)x, y) /* start OOTB only stuff */ - - /* TODO IFT_LOOP is in net/if_types.h on Linux */ #define IFT_LOOP 0x18 /* sctp_pcb.h */ -/* typedef int SHA1_CTX; */ -/* typedef int MD5_CTX; */ -#ifdef HAVE_SHA2 -typedef int SHA256_CTX; -typedef int SHA384_CTX; -typedef int SHA512_CTX; -#endif #if defined(__Userspace_os_Windows) #define SHUT_RD 1 #define SHUT_WR 2 #define SHUT_RDWR 3 #endif #define PRU_FLUSH_RD SHUT_RD #define PRU_FLUSH_WR SHUT_WR @@ -1066,16 +1035,21 @@ struct sockaddr_conn { uint8_t sconn_len; #endif uint8_t sconn_family; uint16_t sconn_port; void *sconn_addr; }; /* + * SCTP protocol specific mbuf flags. + */ +#define M_NOTIFICATION M_PROTO5 /* SCTP notification */ + +/* * IP output routines */ /* Defining SCTP_IP_ID macro. In netinet/ip_output.c, we have u_short ip_id; In netinet/ip_var.h, we have extern u_short ip_id; (enclosed within _KERNEL_) See static __inline uint16_t ip_newid(void) in netinet/ip_var.h */ @@ -1112,19 +1086,21 @@ extern void sctp_userspace_ip6_output(in struct mbuf * sctp_get_mbuf_for_msg(unsigned int space_needed, int want_header, int how, int allonebuf, int type); /* 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_FreeBSD) || defined(__Userspace_os_OpenBSD) +#if defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD) || defined(__Userspace_os_OpenBSD) /* stolen from /usr/include/sys/socket.h */ #define CMSG_ALIGN(n) _ALIGN(n) +#elif defined(__Userspace_os_NetBSD) +#define CMSG_ALIGN(n) (((n) + __ALIGNBYTES) & ~__ALIGNBYTES) #elif defined(__Userspace_os_Darwin) #if !defined(__DARWIN_ALIGNBYTES) #define __DARWIN_ALIGNBYTES (sizeof(__darwin_size_t) - 1) #endif #if !defined(__DARWIN_ALIGN) #define __DARWIN_ALIGN(p) ((__darwin_size_t)((char *)(uintptr_t)(p) + __DARWIN_ALIGNBYTES) &~ __DARWIN_ALIGNBYTES) #endif @@ -1151,19 +1127,26 @@ sctp_get_mbuf_for_msg(unsigned int space if ((tp1)->tv_usec < 0) { \ (tp1)->tv_sec--; \ (tp1)->tv_usec += 1000000; \ } \ } while (0) #endif #if defined(__Userspace_os_Linux) +#if !defined(TAILQ_FOREACH_SAFE) #define TAILQ_FOREACH_SAFE(var, head, field, tvar) \ for ((var) = ((head)->tqh_first); \ (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \ (var) = (tvar)) - +#endif +#if !defined(LIST_FOREACH_SAFE) #define LIST_FOREACH_SAFE(var, head, field, tvar) \ for ((var) = ((head)->lh_first); \ (var) && ((tvar) = LIST_NEXT((var), field), 1); \ (var) = (tvar)) #endif #endif +#if defined(__Userspace_os_DragonFly) +#define TAILQ_FOREACH_SAFE TAILQ_FOREACH_MUTABLE +#define LIST_FOREACH_SAFE LIST_FOREACH_MUTABLE +#endif +#endif
--- a/netwerk/sctp/src/netinet/sctp_output.c +++ b/netwerk/sctp/src/netinet/sctp_output.c @@ -27,17 +27,17 @@ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_output.c 246687 2013-02-11 21:02:49Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp_output.c 262252 2014-02-20 20:14:43Z tuexen $"); #endif #include <netinet/sctp_os.h> #ifdef __FreeBSD__ #include <sys/proc.h> #endif #include <netinet/sctp_var.h> #include <netinet/sctp_sysctl.h> @@ -1967,34 +1967,37 @@ sctp_is_address_in_scope(struct sctp_ifa return (0); } return (1); } static struct mbuf * sctp_add_addr_to_mbuf(struct mbuf *m, struct sctp_ifa *ifa, uint16_t *len) { +#if defined(INET) || defined(INET6) struct sctp_paramhdr *parmh; struct mbuf *mret; uint16_t plen; +#endif switch (ifa->address.sa.sa_family) { #ifdef INET case AF_INET: plen = (uint16_t)sizeof(struct sctp_ipv4addr_param); break; #endif #ifdef INET6 case AF_INET6: plen = (uint16_t)sizeof(struct sctp_ipv6addr_param); break; #endif default: return (m); } +#if defined(INET) || defined(INET6) if (M_TRAILINGSPACE(m) >= plen) { /* easy side we just drop it on the end */ parmh = (struct sctp_paramhdr *)(SCTP_BUF_AT(m, SCTP_BUF_LEN(m))); mret = m; } else { /* Need more space */ mret = m; while (SCTP_BUF_NEXT(mret) != NULL) { @@ -2047,16 +2050,17 @@ sctp_add_addr_to_mbuf(struct mbuf *m, st #endif default: return (m); } if (len != NULL) { *len += plen; } return (mret); +#endif } struct mbuf * sctp_add_addresses_to_i_ia(struct sctp_inpcb *inp, struct sctp_tcb *stcb, struct sctp_scoping *scope, struct mbuf *m_at, int cnt_inits_to, uint16_t *padding_len, uint16_t *chunk_len) @@ -3441,17 +3445,21 @@ sctp_find_cmsg(int c_type, void *data, s sndrcvinfo->sinfo_context = sndinfo.snd_context; sndrcvinfo->sinfo_assoc_id = sndinfo.snd_assoc_id; break; case SCTP_PRINFO: if ((size_t)(cmh.cmsg_len - CMSG_ALIGN(sizeof(cmh))) < sizeof(struct sctp_prinfo)) { return (found); } m_copydata(control, at + CMSG_ALIGN(sizeof(cmh)), sizeof(struct sctp_prinfo), (caddr_t)&prinfo); - sndrcvinfo->sinfo_timetolive = prinfo.pr_value; + if (prinfo.pr_policy != SCTP_PR_SCTP_NONE) { + sndrcvinfo->sinfo_timetolive = prinfo.pr_value; + } else { + sndrcvinfo->sinfo_timetolive = 0; + } sndrcvinfo->sinfo_flags |= prinfo.pr_policy; break; case SCTP_AUTHINFO: if ((size_t)(cmh.cmsg_len - CMSG_ALIGN(sizeof(cmh))) < sizeof(struct sctp_authinfo)) { return (found); } m_copydata(control, at + CMSG_ALIGN(sizeof(cmh)), sizeof(struct sctp_authinfo), (caddr_t)&authinfo); sndrcvinfo->sinfo_keynumber_valid = 1; @@ -3623,17 +3631,17 @@ sctp_process_cmsgs_for_init(struct sctp_ } at += CMSG_ALIGN(cmh.cmsg_len); } return (0); } static struct sctp_tcb * sctp_findassociation_cmsgs(struct sctp_inpcb **inp_p, - in_port_t port, + uint16_t port, struct mbuf *control, struct sctp_nets **net_p, int *error) { #if defined(__Userspace_os_Windows) WSACMSGHDR cmh; #else struct cmsghdr cmh; @@ -3729,17 +3737,16 @@ sctp_add_cookie(struct mbuf *init, int i { struct mbuf *copy_init, *copy_initack, *m_at, *sig, *mret; struct sctp_state_cookie *stc; struct sctp_paramhdr *ph; uint8_t *foo; int sig_offset; uint16_t cookie_sz; - mret = NULL; mret = sctp_get_mbuf_for_msg((sizeof(struct sctp_state_cookie) + sizeof(struct sctp_paramhdr)), 0, M_NOWAIT, 1, MT_DATA); if (mret == NULL) { return (NULL); } copy_init = SCTP_M_COPYM(init, init_offset, M_COPYALL, M_NOWAIT); if (copy_init == NULL) { @@ -3926,17 +3933,19 @@ sctp_lowlevel_chunk_output(struct sctp_i /* Will need ifdefs around this */ #ifdef __Panda__ pakhandle_type o_pak; #endif struct mbuf *newm; struct sctphdr *sctphdr; int packet_length; int ret; +#if defined(INET) || defined(INET6) uint32_t vrf_id; +#endif #if defined(INET) || defined(INET6) #if !defined(__Panda__) struct mbuf *o_pak; #endif sctp_route_t *ro = NULL; struct udphdr *udp = NULL; #endif uint8_t tos_value; @@ -3952,22 +3961,23 @@ sctp_lowlevel_chunk_output(struct sctp_i sctp_unlock_assert(SCTP_INP_SO(inp)); } #endif if ((net) && (net->dest_state & SCTP_ADDR_OUT_OF_SCOPE)) { SCTP_LTRACE_ERR_RET_PKT(m, inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EFAULT); sctp_m_freem(m); return (EFAULT); } +#if defined(INET) || defined(INET6) if (stcb) { vrf_id = stcb->asoc.vrf_id; } else { vrf_id = inp->def_vrf_id; } - +#endif /* fill in the HMAC digest for any AUTH chunk in the packet */ if ((auth != NULL) && (stcb != NULL)) { sctp_fill_hmac_digest_m(m, auth_offset, auth, stcb, auth_keyid); } if (net) { tos_value = net->dscp; } else if (stcb) { @@ -4333,17 +4343,21 @@ sctp_lowlevel_chunk_output(struct sctp_i } else { flowlabel = inp->sctp_ep.default_flowlabel; } if (flowlabel == 0) { /* * This means especially, that it is not set at the * SCTP layer. So use the value from the IP layer. */ +#if defined(__APPLE__) && (!defined(APPLE_LEOPARD) && !defined(APPLE_SNOWLEOPARD) && !defined(APPLE_LION) && !defined(APPLE_MOUNTAINLION)) + flowlabel = ntohl(inp->ip_inp.inp.inp_flow); +#else flowlabel = ntohl(((struct in6pcb *)inp)->in6p_flowinfo); +#endif } flowlabel &= 0x000fffff; len = sizeof(struct ip6_hdr) + sizeof(struct sctphdr); if (port) { len += sizeof(struct udphdr); } newm = sctp_get_mbuf_for_msg(len, 1, M_NOWAIT, 1, MT_DATA); if (newm == NULL) { @@ -4413,18 +4427,22 @@ sctp_lowlevel_chunk_output(struct sctp_i * the TCB! */ if (tos_value == 0) { /* * This means especially, that it is not set at the * SCTP layer. So use the value from the IP layer. */ #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Panda__) || defined(__Windows__) || defined(__Userspace__) +#if defined(__APPLE__) && (!defined(APPLE_LEOPARD) && !defined(APPLE_SNOWLEOPARD) && !defined(APPLE_LION) && !defined(APPLE_MOUNTAINLION)) + tos_value = (ntohl(inp->ip_inp.inp.inp_flow) >> 20) & 0xff; +#else tos_value = (ntohl(((struct in6pcb *)inp)->in6p_flowinfo) >> 20) & 0xff; #endif +#endif } tos_value &= 0xfc; if (ecn_ok) { tos_value |= sctp_get_ect(stcb); } flowinfo = 0x06; flowinfo <<= 8; flowinfo |= tos_value; @@ -4731,16 +4749,17 @@ sctp_lowlevel_chunk_output(struct sctp_i } if (net == NULL) { /* Now if we had a temp route free it */ #if defined(__FreeBSD__) && __FreeBSD_version > 901000 RO_RTFREE(ro); #else if (ro->ro_rt) { RTFREE(ro->ro_rt); + ro->ro_rt = NULL; } #endif } else { /* PMTU check versus smallest asoc MTU goes here */ if (ro->ro_rt == NULL) { /* Route was freed */ if (net->ro._s_addr && net->src_addr_selected) { @@ -4800,18 +4819,22 @@ sctp_lowlevel_chunk_output(struct sctp_i SCTP_BUF_NEXT(newm) = m; m = newm; packet_length = sctp_calculate_len(m); sctphdr = mtod(m, struct sctphdr *); sctphdr->src_port = src_port; sctphdr->dest_port = dest_port; sctphdr->v_tag = v_tag; sctphdr->checksum = 0; +#if defined(SCTP_WITH_NO_CSUM) + SCTP_STAT_INCR(sctps_sendnocrc); +#else sctphdr->checksum = sctp_calculate_cksum(m, 0); SCTP_STAT_INCR(sctps_sendswcrc); +#endif if (tos_value == 0) { tos_value = inp->ip_inp.inp.inp_ip_tos; } tos_value &= 0xfc; if (ecn_ok) { tos_value |= sctp_get_ect(stcb); } /* Don't alloc/free for each packet */ @@ -4841,19 +4864,17 @@ sctp_send_initiate(struct sctp_inpcb *in #if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING) SCTP_UNUSED #endif ) { struct mbuf *m; struct sctp_nets *net; struct sctp_init_chunk *init; -#if defined(INET) || defined(INET6) struct sctp_supported_addr_param *sup_addr; -#endif struct sctp_adaptation_layer_indication *ali; struct sctp_supported_chunk_types_param *pr_supported; struct sctp_paramhdr *ph; int cnt_inits_to = 0; int ret; uint16_t num_ext, chunk_len, padding_len, parameter_len; #if defined(__APPLE__) @@ -5725,16 +5746,24 @@ sctp_send_initiate_ack(struct sctp_inpcb if (m == NULL) { /* No memory, INIT timer will re-attempt. */ if (op_err) sctp_m_freem(op_err); return; } SCTP_BUF_LEN(m) = sizeof(struct sctp_init_chunk); + /* + * We might not overwrite the identification[] completely and on + * some platforms time_entered will contain some padding. + * Therefore zero out the cookie to avoid putting + * uninitialized memory on the wire. + */ + memset(&stc, 0, sizeof(struct sctp_state_cookie)); + /* the time I built cookie */ (void)SCTP_GETTIME_TIMEVAL(&stc.time_entered); /* populate any tie tags */ if (asoc != NULL) { /* unlock before tag selections */ stc.tie_tag_my_vtag = asoc->my_vtag_nonce; stc.tie_tag_peer_vtag = asoc->peer_vtag_nonce; @@ -5887,16 +5916,17 @@ sctp_send_initiate_ack(struct sctp_inpcb /* local from address */ stc.laddress[0] = 0; stc.laddress[1] = 0; stc.laddress[2] = 0; stc.laddress[3] = 0; memcpy(&stc.laddress, &dstconn->sconn_addr, sizeof(void *)); stc.laddr_type = SCTP_CONN_ADDRESS; /* scope_id is only for v6 */ + stc.scope_id = 0; break; } #endif default: /* TSNH */ goto do_a_abort; break; } @@ -5982,21 +6012,29 @@ sctp_send_initiate_ack(struct sctp_inpcb memcpy(&stc.laddress, &net->ro._s_addr->address.sin6.sin6_addr, sizeof(struct in6_addr)); stc.laddr_type = SCTP_IPV6_ADDRESS; break; #endif #if defined(__Userspace__) case AF_CONN: sconn = (struct sockaddr_conn *)to; + stc.address[0] = 0; + stc.address[1] = 0; + stc.address[2] = 0; + stc.address[3] = 0; memcpy(&stc.address, &sconn->sconn_addr, sizeof(void *)); stc.addr_type = SCTP_CONN_ADDRESS; + stc.laddress[0] = 0; + stc.laddress[1] = 0; + stc.laddress[2] = 0; + stc.laddress[3] = 0; memcpy(&stc.laddress, &sconn->sconn_addr, sizeof(void *)); + stc.laddr_type = SCTP_CONN_ADDRESS; stc.scope_id = 0; - stc.laddr_type = SCTP_CONN_ADDRESS; break; #endif } } /* Now lets put the SCTP header in place */ initack = mtod(m, struct sctp_init_ack_chunk *); /* Save it off for quick ref */ stc.peers_vtag = init_chk->init.initiate_tag; @@ -6422,27 +6460,26 @@ sctp_get_frag_point(struct sctp_tcb *stc siz -= (siz % 4); } return (siz); } static void sctp_set_prsctp_policy(struct sctp_stream_queue_pending *sp) { - sp->pr_sctp_on = 0; /* * We assume that the user wants PR_SCTP_TTL if the user * provides a positive lifetime but does not specify any - * PR_SCTP policy. This is a BAD assumption and causes - * problems at least with the U-Vancovers MPI folks. I will - * change this to be no policy means NO PR-SCTP. + * PR_SCTP policy. */ if (PR_SCTP_ENABLED(sp->sinfo_flags)) { sp->act_flags |= PR_SCTP_POLICY(sp->sinfo_flags); - sp->pr_sctp_on = 1; + } else if (sp->timetolive > 0) { + sp->sinfo_flags |= SCTP_PR_SCTP_TTL; + sp->act_flags |= PR_SCTP_POLICY(sp->sinfo_flags); } else { return; } switch (PR_SCTP_POLICY(sp->sinfo_flags)) { case CHUNK_FLAGS_PR_SCTP_BUF: /* * Time to live is a priority stored in tv_sec when * doing the buffer drop thing. @@ -6769,17 +6806,17 @@ sctp_sendall_iterator(struct sctp_inpcb ca = (struct sctp_copy_all *)ptr; if (ca->m == NULL) { return; } if (ca->inp != inp) { /* TSNH */ return; } - if ((ca->m) && ca->sndlen) { + if (ca->sndlen > 0) { m = SCTP_M_COPYM(ca->m, 0, M_COPYALL, M_NOWAIT); if (m == NULL) { /* can't copy so we are done */ ca->cnt_failed++; return; } #ifdef SCTP_MBUF_LOGGING if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) { @@ -6798,45 +6835,49 @@ sctp_sendall_iterator(struct sctp_inpcb SCTP_TCB_LOCK_ASSERT(stcb); if (stcb->asoc.alternate) { net = stcb->asoc.alternate; } else { net = stcb->asoc.primary_destination; } if (ca->sndrcv.sinfo_flags & SCTP_ABORT) { /* Abort this assoc with m as the user defined reason */ - if (m) { - struct sctp_paramhdr *ph; - + if (m != NULL) { SCTP_BUF_PREPEND(m, sizeof(struct sctp_paramhdr), M_NOWAIT); - if (m) { - ph = mtod(m, struct sctp_paramhdr *); - ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT); - ph->param_length = htons(sizeof(struct sctp_paramhdr) + ca->sndlen); - } - /* We add one here to keep the assoc from - * dis-appearing on us. - */ - atomic_add_int(&stcb->asoc.refcnt, 1); - sctp_abort_an_association(inp, stcb, m, SCTP_SO_NOT_LOCKED); - /* sctp_abort_an_association calls sctp_free_asoc() - * free association will NOT free it since we - * incremented the refcnt .. we do this to prevent - * it being freed and things getting tricky since - * we could end up (from free_asoc) calling inpcb_free - * which would get a recursive lock call to the - * iterator lock.. But as a consequence of that the - * stcb will return to us un-locked.. since free_asoc - * returns with either no TCB or the TCB unlocked, we - * must relock.. to unlock in the iterator timer :-0 - */ - SCTP_TCB_LOCK(stcb); - atomic_add_int(&stcb->asoc.refcnt, -1); - goto no_chunk_output; - } + } else { + m = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr), + 0, M_NOWAIT, 1, MT_DATA); + SCTP_BUF_LEN(m) = sizeof(struct sctp_paramhdr); + } + if (m != NULL) { + struct sctp_paramhdr *ph; + + ph = mtod(m, struct sctp_paramhdr *); + ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT); + ph->param_length = htons(sizeof(struct sctp_paramhdr) + ca->sndlen); + } + /* We add one here to keep the assoc from + * dis-appearing on us. + */ + atomic_add_int(&stcb->asoc.refcnt, 1); + sctp_abort_an_association(inp, stcb, m, SCTP_SO_NOT_LOCKED); + /* sctp_abort_an_association calls sctp_free_asoc() + * free association will NOT free it since we + * incremented the refcnt .. we do this to prevent + * it being freed and things getting tricky since + * we could end up (from free_asoc) calling inpcb_free + * which would get a recursive lock call to the + * iterator lock.. But as a consequence of that the + * stcb will return to us un-locked.. since free_asoc + * returns with either no TCB or the TCB unlocked, we + * must relock.. to unlock in the iterator timer :-0 + */ + SCTP_TCB_LOCK(stcb); + atomic_add_int(&stcb->asoc.refcnt, -1); + goto no_chunk_output; } else { if (m) { ret = sctp_msg_append(stcb, net, m, &ca->sndrcv, 1); } asoc = &stcb->asoc; if (ca->sndrcv.sinfo_flags & SCTP_EOF) { /* shutdown this assoc */ @@ -6909,18 +6950,17 @@ sctp_sendall_iterator(struct sctp_inpcb } } un_sent = ((stcb->asoc.total_output_queue_size - stcb->asoc.total_flight) + (stcb->asoc.stream_queue_cnt * sizeof(struct sctp_data_chunk))); if ((sctp_is_feature_off(inp, SCTP_PCB_FLAGS_NODELAY)) && (stcb->asoc.total_flight > 0) && - (un_sent < (int)(stcb->asoc.smallest_mtu - SCTP_MIN_OVERHEAD)) - ) { + (un_sent < (int)(stcb->asoc.smallest_mtu - SCTP_MIN_OVERHEAD))) { do_chunk_output = 0; } if (do_chunk_output) sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_USR_SEND, SCTP_SO_NOT_LOCKED); else if (added_control) { int num_out = 0, reason = 0, now_filled = 0; struct timeval now; int frag_point; @@ -7052,23 +7092,20 @@ sctp_sendall(struct sctp_inpcb *inp, str SCTP_FREE(ca, SCTP_M_COPYAL); SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_OUTPUT, ENOMEM); return (ENOMEM); } } else { /* Gather the length of the send */ struct mbuf *mat; - mat = m; ca->sndlen = 0; - while (m) { - ca->sndlen += SCTP_BUF_LEN(m); - m = SCTP_BUF_NEXT(m); - } - ca->m = mat; + for (mat = m; mat; mat = SCTP_BUF_NEXT(mat)) { + ca->sndlen += SCTP_BUF_LEN(mat); + } } ret = sctp_initiate_iterator(NULL, sctp_sendall_iterator, NULL, SCTP_PCB_ANY_FLAGS, SCTP_PCB_ANY_FEATURES, SCTP_ASOC_ANY_STATE, (void *)ca, 0, sctp_sendall_completes, inp, 1); if (ret) { SCTP_PRINTF("Failed to initiate iterator for sendall\n"); @@ -7260,18 +7297,18 @@ sctp_clean_up_ctl(struct sctp_tcb *stcb, } } } } static int sctp_can_we_split_this(struct sctp_tcb *stcb, - uint32_t length, - uint32_t goal_mtu, uint32_t frag_point, int eeor_on) + uint32_t length, + uint32_t goal_mtu, uint32_t frag_point, int eeor_on) { /* Make a decision on if I should split a * msg into multiple parts. This is only asked of * incomplete messages. */ if (eeor_on) { /* If we are doing EEOR we need to always send * it if its the entire thing, since it might @@ -7320,42 +7357,42 @@ sctp_can_we_split_this(struct sctp_tcb * } /* Nope, can't split */ return (0); } static uint32_t sctp_move_to_outqueue(struct sctp_tcb *stcb, - struct sctp_stream_out *strq, - uint32_t goal_mtu, - uint32_t frag_point, - int *locked, - int *giveup, - int eeor_mode, - int *bail, - int so_locked + struct sctp_stream_out *strq, + uint32_t goal_mtu, + uint32_t frag_point, + int *locked, + int *giveup, + int eeor_mode, + int *bail, + int so_locked #if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING) - SCTP_UNUSED -#endif -) + SCTP_UNUSED +#endif + ) { /* Move from the stream to the send_queue keeping track of the total */ struct sctp_association *asoc; struct sctp_stream_queue_pending *sp; struct sctp_tmit_chunk *chk; struct sctp_data_chunk *dchkh; uint32_t to_move, length; uint8_t rcv_flags = 0; uint8_t some_taken; uint8_t send_lock_up = 0; SCTP_TCB_LOCK_ASSERT(stcb); asoc = &stcb->asoc; - one_more_time: +one_more_time: /*sa_ignore FREED_MEMORY*/ sp = TAILQ_FIRST(&strq->outqueue); if (sp == NULL) { *locked = 0; if (send_lock_up == 0) { SCTP_TCB_SEND_LOCK(stcb); send_lock_up = 1; } @@ -7380,21 +7417,21 @@ sctp_move_to_outqueue(struct sctp_tcb *s if (sp->sender_all_done) { /* We are doing differed cleanup. Last * time through when we took all the data * the sender_all_done was not set. */ if ((sp->put_last_out == 0) && (sp->discard_rest == 0)) { SCTP_PRINTF("Gak, put out entire msg with NO end!-1\n"); SCTP_PRINTF("sender_done:%d len:%d msg_comp:%d put_last_out:%d send_lock:%d\n", - sp->sender_all_done, - sp->length, - sp->msg_is_complete, - sp->put_last_out, - send_lock_up); + sp->sender_all_done, + sp->length, + sp->msg_is_complete, + sp->put_last_out, + send_lock_up); } if ((TAILQ_NEXT(sp, next) == NULL) && (send_lock_up == 0)) { SCTP_TCB_SEND_LOCK(stcb); send_lock_up = 1; } atomic_subtract_int(&asoc->stream_queue_cnt, 1); TAILQ_REMOVE(&strq->outqueue, sp, next); stcb->asoc.ss_functions.sctp_ss_remove_from_stream(stcb, asoc, strq, sp, send_lock_up); @@ -7457,17 +7494,17 @@ sctp_move_to_outqueue(struct sctp_tcb *s to_move = 0; goto out_of; } } some_taken = sp->some_taken; if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) { sp->msg_is_complete = 1; } - re_look: +re_look: length = sp->length; if (sp->msg_is_complete) { /* The message is complete */ to_move = min(length, frag_point); if (to_move == length) { /* All of it fits in the MTU */ if (sp->some_taken) { rcv_flags |= SCTP_DATA_LAST_FRAG; @@ -7556,17 +7593,17 @@ sctp_move_to_outqueue(struct sctp_tcb *s goto dont_do_it; } chk->data = sp->data; chk->last_mbuf = sp->tail_mbuf; /* register the stealing */ sp->data = sp->tail_mbuf = NULL; } else { struct mbuf *m; - dont_do_it: + dont_do_it: chk->data = SCTP_M_COPYM(sp->data, 0, to_move, M_NOWAIT); chk->last_mbuf = NULL; if (chk->data == NULL) { sp->some_taken = some_taken; sctp_free_a_chunk(stcb, chk, so_locked); *bail = 1; to_move = 0; goto out_of; @@ -7774,23 +7811,18 @@ sctp_move_to_outqueue(struct sctp_tcb *s chk->pad_inplace = 1; } if ((lm = SCTP_BUF_NEXT(chk->last_mbuf)) != NULL) { /* pad added an mbuf */ chk->last_mbuf = lm; } chk->send_size += pads; } - /* We only re-set the policy if it is on */ - if (sp->pr_sctp_on) { - sctp_set_prsctp_policy(sp); + if (PR_SCTP_ENABLED(chk->flags)) { asoc->pr_sctp_cnt++; - chk->pr_sctp_on = 1; - } else { - chk->pr_sctp_on = 0; } if (sp->msg_is_complete && (sp->length == 0) && (sp->sender_all_done)) { /* All done pull and kill the message */ atomic_subtract_int(&asoc->stream_queue_cnt, 1); if (sp->put_last_out == 0) { SCTP_PRINTF("Gak, put out entire msg with NO end!-2\n"); SCTP_PRINTF("sender_done:%d len:%d msg_comp:%d put_last_out:%d send_lock:%d\n", sp->sender_all_done, @@ -7821,17 +7853,17 @@ sctp_move_to_outqueue(struct sctp_tcb *s } else { /* more to go, we are locked */ *locked = 1; } asoc->chunks_on_out_queue++; strq->chunks_on_queues++; TAILQ_INSERT_TAIL(&asoc->send_queue, chk, sctp_next); asoc->send_queue_cnt++; - out_of: +out_of: if (send_lock_up) { SCTP_TCB_SEND_UNLOCK(stcb); } return (to_move); } static void @@ -7975,17 +8007,17 @@ sctp_med_chunk_output(struct sctp_inpcb int *reason_code, int control_only, int from_where, struct timeval *now, int *now_filled, int frag_point, int so_locked #if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING) SCTP_UNUSED #endif ) { - /* + /** * Ok this is the generic chunk service queue. we must do the * following: - Service the stream queue that is next, moving any * message (note I must get a complete message i.e. FIRST/MIDDLE and * LAST to the out queue in one pass) and assigning TSN's - Check to * see if the cwnd/rwnd allows any output, if so we go ahead and * fomulate and send the low level chunks. Making sure to combine * any control in the control chunk queue also. */ @@ -9326,17 +9358,16 @@ sctp_send_heartbeat_ack(struct sctp_tcb void sctp_send_cookie_ack(struct sctp_tcb *stcb) { /* formulate and queue a cookie-ack back to sender */ struct mbuf *cookie_ack; struct sctp_chunkhdr *hdr; struct sctp_tmit_chunk *chk; - cookie_ack = NULL; SCTP_TCB_LOCK_ASSERT(stcb); cookie_ack = sctp_get_mbuf_for_msg(sizeof(struct sctp_chunkhdr), 0, M_NOWAIT, 1, MT_HEADER); if (cookie_ack == NULL) { /* no mbuf's */ return; } SCTP_BUF_RESV_UF(cookie_ack, SCTP_MIN_OVERHEAD); @@ -11078,16 +11109,17 @@ sctp_send_abort_tcb(struct sctp_tcb *stc #endif ) { struct mbuf *m_abort, *m, *m_last; struct mbuf *m_out, *m_end = NULL; struct sctp_abort_chunk *abort; struct sctp_auth_chunk *auth = NULL; struct sctp_nets *net; + uint32_t vtag; uint32_t auth_offset = 0; uint16_t cause_len, chunk_len, padding_len; #if defined(__APPLE__) if (so_locked) { sctp_lock_assert(SCTP_INP_SO(stcb->sctp_ep)); } else { sctp_unlock_assert(SCTP_INP_SO(stcb->sctp_ep)); @@ -11140,29 +11172,36 @@ sctp_send_abort_tcb(struct sctp_tcb *stc if (stcb->asoc.alternate) { net = stcb->asoc.alternate; } else { net = stcb->asoc.primary_destination; } /* Fill in the ABORT chunk header. */ abort = mtod(m_abort, struct sctp_abort_chunk *); abort->ch.chunk_type = SCTP_ABORT_ASSOCIATION; - abort->ch.chunk_flags = 0; + if (stcb->asoc.peer_vtag == 0) { + /* This happens iff the assoc is in COOKIE-WAIT state. */ + vtag = stcb->asoc.my_vtag; + abort->ch.chunk_flags = SCTP_HAD_NO_TCB; + } else { + vtag = stcb->asoc.peer_vtag; + abort->ch.chunk_flags = 0; + } abort->ch.chunk_length = htons(chunk_len); /* Add padding, if necessary. */ if (padding_len > 0) { if ((m_last == NULL) || sctp_add_pad_tombuf(m_last, padding_len)) { sctp_m_freem(m_out); return; } } (void)sctp_lowlevel_chunk_output(stcb->sctp_ep, stcb, net, (struct sockaddr *)&net->ro._l_addr, m_out, auth_offset, auth, stcb->asoc.authinfo.active_keyid, 1, 0, 0, - stcb->sctp_ep->sctp_lport, stcb->rport, htonl(stcb->asoc.peer_vtag), + stcb->sctp_ep->sctp_lport, stcb->rport, htonl(vtag), stcb->asoc.primary_destination->port, NULL, #if defined(__FreeBSD__) 0, 0, #endif so_locked); SCTP_STAT_INCR_COUNTER64(sctps_outcontrolchunks); } @@ -11227,17 +11266,20 @@ sctp_send_resp_msg(struct sockaddr *src, pakhandle_type o_pak; #else struct mbuf *o_pak; #endif struct mbuf *mout; struct sctphdr *shout; struct sctp_chunkhdr *ch; struct udphdr *udp; - int len, cause_len, padding_len, ret; + int len, cause_len, padding_len; +#if defined(INET) || defined(INET6) + int ret; +#endif #ifdef INET #if defined(__APPLE__) || defined(__Panda__) sctp_route_t ro; #endif struct sockaddr_in *src_sin, *dst_sin; struct ip *ip; #endif #ifdef INET6 @@ -11503,16 +11545,17 @@ sctp_send_resp_msg(struct sockaddr *src, sctp_packet_log(o_pak); } #endif #if defined(__APPLE__) || defined(__Panda__) SCTP_IP_OUTPUT(ret, o_pak, &ro, NULL, vrf_id); /* Free the route if we got one back */ if (ro.ro_rt) { RTFREE(ro.ro_rt); + ro.ro_rt = NULL; } #else SCTP_IP_OUTPUT(ret, o_pak, NULL, NULL, vrf_id); #endif break; #endif #ifdef INET6 case AF_INET6: @@ -11559,27 +11602,31 @@ sctp_send_resp_msg(struct sockaddr *src, #endif #if defined(__Userspace__) case AF_CONN: { char *buffer; struct sockaddr_conn *sconn; sconn = (struct sockaddr_conn *)src; +#if defined(SCTP_WITH_NO_CSUM) + SCTP_STAT_INCR(sctps_sendnocrc); +#else shout->checksum = sctp_calculate_cksum(mout, 0); SCTP_STAT_INCR(sctps_sendswcrc); +#endif #ifdef SCTP_PACKET_LOGGING if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LAST_PACKET_TRACING) { sctp_packet_log(mout); } #endif /* Don't alloc/free for each packet */ if ((buffer = malloc(len)) != NULL) { m_copydata(mout, 0, len, buffer); - ret = SCTP_BASE_VAR(conn_output)(sconn->sconn_addr, buffer, len, 0, 0); + SCTP_BASE_VAR(conn_output)(sconn->sconn_addr, buffer, len, 0, 0); free(buffer); } sctp_m_freem(mout); break; } #endif default: SCTPDBG(SCTP_DEBUG_OUTPUT1, "Unknown protocol (TSNH) type %d\n",
--- a/netwerk/sctp/src/netinet/sctp_pcb.c +++ b/netwerk/sctp/src/netinet/sctp_pcb.c @@ -27,17 +27,17 @@ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_pcb.c 246687 2013-02-11 21:02:49Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp_pcb.c 258765 2013-11-30 12:51:19Z tuexen $"); #endif #include <netinet/sctp_os.h> #ifdef __FreeBSD__ #include <sys/proc.h> #endif #include <netinet/sctp_var.h> #include <netinet/sctp_sysctl.h> @@ -63,40 +63,34 @@ #endif #endif #if defined(__FreeBSD__) #include <sys/sched.h> #include <sys/smp.h> #include <sys/unistd.h> #endif #if defined(__Userspace__) -#if !defined(__Userspace_os_Windows) -#if defined(ANDROID) -#include <unistd.h> -#include <ifaddrs-android-ext.h> -#else -#include <sys/unistd.h> -#endif -#endif #include <user_socketvar.h> #endif #if defined(__APPLE__) #define APPLE_FILE_NO 4 #endif #if defined(__FreeBSD__) && __FreeBSD_version >= 801000 VNET_DEFINE(struct sctp_base_info, system_base_info); #else struct sctp_base_info system_base_info; #endif #if defined(__Userspace__) +#if defined(INET) || defined(INET6) struct ifaddrs *g_interfaces; #endif +#endif /* FIX: we don't handle multiple link local scopes */ /* "scopeless" replacement IN6_ARE_ADDR_EQUAL */ #ifdef INET6 int SCTP6_ARE_ADDR_EQUAL(struct sockaddr_in6 *a, struct sockaddr_in6 *b) { #ifdef SCTP_EMBEDDED_V6_SCOPE #if defined(__APPLE__) @@ -921,31 +915,40 @@ sctp_del_addr_from_vrf(uint32_t vrf_id, } return; } static int sctp_does_stcb_own_this_addr(struct sctp_tcb *stcb, struct sockaddr *to) { - int loopback_scope, ipv4_local_scope, local_scope, site_scope; - int ipv4_addr_legal, ipv6_addr_legal; + int loopback_scope; +#if defined(INET) + int ipv4_local_scope, ipv4_addr_legal; +#endif +#if defined(INET6) + int local_scope, site_scope, ipv6_addr_legal; +#endif #if defined(__Userspace__) int conn_addr_legal; #endif struct sctp_vrf *vrf; struct sctp_ifn *sctp_ifn; struct sctp_ifa *sctp_ifa; loopback_scope = stcb->asoc.scope.loopback_scope; +#if defined(INET) ipv4_local_scope = stcb->asoc.scope.ipv4_local_scope; + ipv4_addr_legal = stcb->asoc.scope.ipv4_addr_legal; +#endif +#if defined(INET6) local_scope = stcb->asoc.scope.local_scope; site_scope = stcb->asoc.scope.site_scope; - ipv4_addr_legal = stcb->asoc.scope.ipv4_addr_legal; ipv6_addr_legal = stcb->asoc.scope.ipv6_addr_legal; +#endif #if defined(__Userspace__) conn_addr_legal = stcb->asoc.scope.conn_addr_legal; #endif SCTP_IPI_ADDR_RLOCK(); vrf = sctp_find_vrf(stcb->asoc.vrf_id); if (vrf == NULL) { /* no vrf, no addresses */ @@ -963,17 +966,19 @@ sctp_does_stcb_own_this_addr(struct sctp if (sctp_is_addr_restricted(stcb, sctp_ifa) && (!sctp_is_addr_pending(stcb, sctp_ifa))) { /* We allow pending addresses, where we * have sent an asconf-add to be considered * valid. */ continue; } - + if (sctp_ifa->address.sa.sa_family != to->sa_family) { + continue; + } switch (sctp_ifa->address.sa.sa_family) { #ifdef INET case AF_INET: if (ipv4_addr_legal) { struct sockaddr_in *sin, *rsin; sin = &sctp_ifa->address.sin; rsin = (struct sockaddr_in *)to; @@ -2313,18 +2318,21 @@ sctp_findassociation_addr_sa(struct sock * address will be used to lookup the TCB and see if one exits. */ static struct sctp_tcb * sctp_findassociation_special_addr(struct mbuf *m, int offset, struct sctphdr *sh, struct sctp_inpcb **inp_p, struct sctp_nets **netp, struct sockaddr *dst) { struct sctp_paramhdr *phdr, parm_buf; +#if defined(INET) || defined(INET6) struct sctp_tcb *stcb; - uint32_t ptype, plen; + uint16_t ptype; +#endif + uint16_t plen; #ifdef INET struct sockaddr_in sin4; #endif #ifdef INET6 struct sockaddr_in6 sin6; #endif #ifdef INET @@ -2339,23 +2347,24 @@ sctp_findassociation_special_addr(struct memset(&sin6, 0, sizeof(sin6)); #ifdef HAVE_SIN6_LEN sin6.sin6_len = sizeof(sin6); #endif sin6.sin6_family = AF_INET6; sin6.sin6_port = sh->src_port; #endif - stcb = NULL; offset += sizeof(struct sctp_init_chunk); phdr = sctp_get_next_param(m, offset, &parm_buf, sizeof(parm_buf)); while (phdr != NULL) { /* now we must see if we want the parameter */ +#if defined(INET) || defined(INET6) ptype = ntohs(phdr->param_type); +#endif plen = ntohs(phdr->param_length); if (plen == 0) { break; } #ifdef INET if (ptype == SCTP_IPV4_ADDRESS && plen == sizeof(struct sctp_ipv4addr_param)) { /* Get the rest of the address */ @@ -2529,37 +2538,37 @@ sctp_findassociation_addr(struct mbuf *m { int find_tcp_pool; struct sctp_tcb *stcb; struct sctp_inpcb *inp; if (sh->v_tag) { /* we only go down this path if vtag is non-zero */ stcb = sctp_findassoc_by_vtag(src, dst, ntohl(sh->v_tag), - inp_p, netp, sh->src_port, sh->dest_port, 0, vrf_id, 0); + inp_p, netp, sh->src_port, sh->dest_port, 0, vrf_id, 0); if (stcb) { return (stcb); } } find_tcp_pool = 0; if ((ch->chunk_type != SCTP_INITIATION) && (ch->chunk_type != SCTP_INITIATION_ACK) && (ch->chunk_type != SCTP_COOKIE_ACK) && (ch->chunk_type != SCTP_COOKIE_ECHO)) { /* Other chunk types go to the tcp pool. */ find_tcp_pool = 1; } if (inp_p) { stcb = sctp_findassociation_addr_sa(src, dst, inp_p, netp, - find_tcp_pool, vrf_id); + find_tcp_pool, vrf_id); inp = *inp_p; } else { stcb = sctp_findassociation_addr_sa(src, dst, &inp, netp, - find_tcp_pool, vrf_id); + find_tcp_pool, vrf_id); } SCTPDBG(SCTP_DEBUG_PCB1, "stcb:%p inp:%p\n", (void *)stcb, (void *)inp); if (stcb == NULL && inp) { /* Found a EP but not this address */ if ((ch->chunk_type == SCTP_INITIATION) || (ch->chunk_type == SCTP_INITIATION_ACK)) { /*- * special hook, we do NOT return linp or an @@ -2735,18 +2744,23 @@ sctp_inpcb_alloc(struct socket *so, uint #if defined(__APPLE__) inp->ip_inp.inp.inp_state = INPCB_STATE_INUSE; #endif /* setup socket pointers */ inp->sctp_socket = so; inp->ip_inp.inp.inp_socket = so; #ifdef INET6 #if !defined(__Userspace__) && !defined(__Windows__) - if (MODULE_GLOBAL(ip6_auto_flowlabel)) { - inp->ip_inp.inp.inp_flags |= IN6P_AUTOFLOWLABEL; + if (INP_SOCKAF(so) == AF_INET6) { + if (MODULE_GLOBAL(ip6_auto_flowlabel)) { + inp->ip_inp.inp.inp_flags |= IN6P_AUTOFLOWLABEL; + } + if (MODULE_GLOBAL(ip6_v6only)) { + inp->ip_inp.inp.inp_flags |= IN6P_IPV6_V6ONLY; + } } #endif #endif inp->sctp_associd_counter = 1; 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); @@ -2858,47 +2872,54 @@ sctp_inpcb_alloc(struct socket *so, uint } inp->m_vrf_ids[0] = vrf_id; inp->num_vrfs = 1; #endif inp->def_vrf_id = vrf_id; #if defined(__APPLE__) #if defined(APPLE_LEOPARD) || defined(APPLE_SNOWLEOPARD) - inp->ip_inp.inp.inpcb_mtx = lck_mtx_alloc_init(SCTP_BASE_INFO(mtx_grp), SCTP_BASE_INFO(mtx_attr)); + inp->ip_inp.inp.inpcb_mtx = lck_mtx_alloc_init(SCTP_BASE_INFO(sctbinfo).mtx_grp, SCTP_BASE_INFO(sctbinfo).mtx_attr); if (inp->ip_inp.inp.inpcb_mtx == NULL) { SCTP_PRINTF("in_pcballoc: can't alloc mutex! so=%p\n", (void *)so); #ifdef SCTP_MVRF SCTP_FREE(inp->m_vrf_ids, SCTP_M_MVRF); #endif SCTP_HASH_FREE(inp->sctp_tcbhash, inp->sctp_hashmark); so->so_pcb = NULL; SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_ep), inp); - SCTP_UNLOCK_EXC(SCTP_BASE_INFO(ipi_ep_mtx)); + SCTP_UNLOCK_EXC(SCTP_BASE_INFO(sctbinfo).ipi_lock); SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, ENOMEM); return (ENOMEM); } +#elif defined(APPLE_LION) || defined(APPLE_MOUNTAINLION) + lck_mtx_init(&inp->ip_inp.inp.inpcb_mtx, SCTP_BASE_INFO(sctbinfo).mtx_grp, SCTP_BASE_INFO(sctbinfo).mtx_attr); #else - lck_mtx_init(&inp->ip_inp.inp.inpcb_mtx, SCTP_BASE_INFO(mtx_grp), SCTP_BASE_INFO(mtx_attr)); + lck_mtx_init(&inp->ip_inp.inp.inpcb_mtx, SCTP_BASE_INFO(sctbinfo).ipi_lock_grp, SCTP_BASE_INFO(sctbinfo).ipi_lock_attr); #endif #endif SCTP_INP_INFO_WLOCK(); SCTP_INP_LOCK_INIT(inp); #if defined(__FreeBSD__) INP_LOCK_INIT(&inp->ip_inp.inp, "inp", "sctpinp"); #endif SCTP_INP_READ_INIT(inp); SCTP_ASOC_CREATE_LOCK_INIT(inp); /* lock the new ep */ SCTP_INP_WLOCK(inp); /* add it to the info area */ LIST_INSERT_HEAD(&SCTP_BASE_INFO(listhead), inp, sctp_list); #if defined(__APPLE__) - LIST_INSERT_HEAD(&SCTP_BASE_INFO(inplisthead), &inp->ip_inp.inp, inp_list); + inp->ip_inp.inp.inp_pcbinfo = &SCTP_BASE_INFO(sctbinfo); +#if defined(APPLE_LEOPARD) || defined(APPLE_SNOWLEOPARD) || defined(APPLE_LION) || defined(APPLE_MOUNTAINLION) + LIST_INSERT_HEAD(SCTP_BASE_INFO(sctbinfo).listhead, &inp->ip_inp.inp, inp_list); +#else + LIST_INSERT_HEAD(SCTP_BASE_INFO(sctbinfo).ipi_listhead, &inp->ip_inp.inp, inp_list); +#endif #endif SCTP_INP_INFO_WUNLOCK(); TAILQ_INIT(&inp->read_queue); LIST_INIT(&inp->sctp_addr_list); LIST_INIT(&inp->sctp_asoc_list); @@ -2922,30 +2943,28 @@ sctp_inpcb_alloc(struct socket *so, uint m->sctp_timeoutticks[SCTP_TIMER_MAXSHUTDOWN] = SEC_TO_TICKS(SCTP_BASE_SYSCTL(sctp_shutdown_guard_time_default)); m->sctp_timeoutticks[SCTP_TIMER_SIGNATURE] = SEC_TO_TICKS(SCTP_BASE_SYSCTL(sctp_secret_lifetime_default)); /* all max/min max are in ms */ m->sctp_maxrto = SCTP_BASE_SYSCTL(sctp_rto_max_default); m->sctp_minrto = SCTP_BASE_SYSCTL(sctp_rto_min_default); m->initial_rto = SCTP_BASE_SYSCTL(sctp_rto_initial_default); m->initial_init_rto_max = SCTP_BASE_SYSCTL(sctp_init_rto_max_default); m->sctp_sack_freq = SCTP_BASE_SYSCTL(sctp_sack_freq_default); - - m->max_open_streams_intome = MAX_SCTP_STREAMS; - m->max_init_times = SCTP_BASE_SYSCTL(sctp_init_rtx_max_default); m->max_send_times = SCTP_BASE_SYSCTL(sctp_assoc_rtx_max_default); m->def_net_failure = SCTP_BASE_SYSCTL(sctp_path_rtx_max_default); m->def_net_pf_threshold = SCTP_BASE_SYSCTL(sctp_path_pf_threshold); m->sctp_sws_sender = SCTP_SWS_SENDER_DEF; m->sctp_sws_receiver = SCTP_SWS_RECEIVER_DEF; m->max_burst = SCTP_BASE_SYSCTL(sctp_max_burst_default); m->fr_max_burst = SCTP_BASE_SYSCTL(sctp_fr_max_burst_default); m->sctp_default_cc_module = SCTP_BASE_SYSCTL(sctp_default_cc_module); m->sctp_default_ss_module = SCTP_BASE_SYSCTL(sctp_default_ss_module); + m->max_open_streams_intome = SCTP_BASE_SYSCTL(sctp_nr_incoming_streams_default); /* number of streams to pre-open on a association */ m->pre_open_stream_count = SCTP_BASE_SYSCTL(sctp_nr_outgoing_streams_default); /* Add adaptation cookie */ m->adaptation_layer_indicator = 0; m->adaptation_layer_indicator_provided = 0; /* seed random number generator */ @@ -3134,31 +3153,35 @@ sctp_inpcb_bind(struct socket *so, struc #else sctp_inpcb_bind(struct socket *so, struct sockaddr *addr, struct sctp_ifa *sctp_ifap, struct proc *p) #endif { /* bind a ep to a socket address */ struct sctppcbhead *head; struct sctp_inpcb *inp, *inp_tmp; +#if defined(INET) || (defined(INET6) && defined(__APPLE__)) || defined(__FreeBSD__) || defined(__APPLE__) struct inpcb *ip_inp; +#endif int port_reuse_active = 0; int bindall; #ifdef SCTP_MVRF int i; #endif uint16_t lport; int error; uint32_t vrf_id; lport = 0; error = 0; bindall = 1; inp = (struct sctp_inpcb *)so->so_pcb; +#if defined(INET) || (defined(INET6) && defined(__APPLE__)) || defined(__FreeBSD__) || defined(__APPLE__) ip_inp = (struct inpcb *)so->so_pcb; +#endif #ifdef SCTP_DEBUG if (addr) { SCTPDBG(SCTP_DEBUG_PCB1, "Bind called port: %d\n", ntohs(((struct sockaddr_in *)addr)->sin_port)); SCTPDBG(SCTP_DEBUG_PCB1, "Addr: "); SCTPDBG_ADDR(SCTP_DEBUG_PCB1, addr); } #endif @@ -4377,17 +4400,17 @@ sctp_add_remote_addr(struct sctp_tcb *st memset(&sin->sin_zero, 0, sizeof(sin->sin_zero)); /* assure len is set */ #ifdef HAVE_SIN_LEN sin->sin_len = sizeof(struct sockaddr_in); #endif if (set_scope) { #ifdef SCTP_DONT_DO_PRIVADDR_SCOPE - stcb->ipv4_local_scope = 1; + stcb->asoc.scope.ipv4_local_scope = 1; #else if (IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) { stcb->asoc.scope.ipv4_local_scope = 1; } #endif /* SCTP_DONT_DO_PRIVADDR_SCOPE */ } else { /* Validate the address is in scope */ if ((IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) && @@ -4583,16 +4606,17 @@ sctp_add_remote_addr(struct sctp_tcb *st #ifndef SCOPEDROUTING sin6->sin6_scope_id = 0; #endif } #endif /* SCTP_EMBEDDED_V6_SCOPE */ #endif SCTP_RTALLOC((sctp_route_t *)&net->ro, stcb->asoc.vrf_id); +#if !defined(__Userspace__) if (SCTP_ROUTE_HAS_VALID_IFN(&net->ro)) { /* Get source address */ net->ro._s_addr = sctp_source_address_selection(stcb->sctp_ep, stcb, (sctp_route_t *)&net->ro, net, 0, stcb->asoc.vrf_id); @@ -4612,16 +4636,17 @@ sctp_add_remote_addr(struct sctp_tcb *st /* we take the route mtu over the interface, since * the route may be leading out the loopback, or * a different interface. */ net->mtu = rmtu; } } } +#endif if (net->mtu == 0) { switch (newaddr->sa_family) { #ifdef INET case AF_INET: net->mtu = SCTP_DEFAULT_MTU; break; #endif #ifdef INET6 @@ -5051,16 +5076,17 @@ sctp_aloc_assoc(struct sctp_inpcb *inp, SCTP_FREE(asoc->mapping_array, SCTP_M_MAP); asoc->mapping_array = NULL; } if (asoc->nr_mapping_array) { SCTP_FREE(asoc->nr_mapping_array, SCTP_M_MAP); asoc->nr_mapping_array = NULL; } SCTP_DECR_ASOC_COUNT(); + SCTP_TCB_UNLOCK(stcb); SCTP_TCB_LOCK_DESTROY(stcb); SCTP_TCB_SEND_LOCK_DESTROY(stcb); LIST_REMOVE(stcb, sctp_tcbasocidhash); SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_asoc), stcb); SCTP_INP_WUNLOCK(inp); SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, ENOBUFS); *error = ENOBUFS; return (NULL); @@ -5186,59 +5212,55 @@ void sctp_delete_from_timewait(uint32_t tag, uint16_t lport, uint16_t rport) { struct sctpvtaghead *chain; struct sctp_tagblock *twait_block; int found = 0; int i; chain = &SCTP_BASE_INFO(vtag_timewait)[(tag % SCTP_STACK_VTAG_HASH_SIZE)]; - if (!LIST_EMPTY(chain)) { - LIST_FOREACH(twait_block, chain, sctp_nxt_tagblock) { - for (i = 0; i < SCTP_NUMBER_IN_VTAG_BLOCK; i++) { - if ((twait_block->vtag_block[i].v_tag == tag) && - (twait_block->vtag_block[i].lport == lport) && - (twait_block->vtag_block[i].rport == rport)) { - twait_block->vtag_block[i].tv_sec_at_expire = 0; - twait_block->vtag_block[i].v_tag = 0; - twait_block->vtag_block[i].lport = 0; - twait_block->vtag_block[i].rport = 0; - found = 1; - break; - } - } - if (found) + LIST_FOREACH(twait_block, chain, sctp_nxt_tagblock) { + for (i = 0; i < SCTP_NUMBER_IN_VTAG_BLOCK; i++) { + if ((twait_block->vtag_block[i].v_tag == tag) && + (twait_block->vtag_block[i].lport == lport) && + (twait_block->vtag_block[i].rport == rport)) { + twait_block->vtag_block[i].tv_sec_at_expire = 0; + twait_block->vtag_block[i].v_tag = 0; + twait_block->vtag_block[i].lport = 0; + twait_block->vtag_block[i].rport = 0; + found = 1; break; - } + } + } + if (found) + break; } } int sctp_is_in_timewait(uint32_t tag, uint16_t lport, uint16_t rport) { struct sctpvtaghead *chain; struct sctp_tagblock *twait_block; int found = 0; int i; SCTP_INP_INFO_WLOCK(); chain = &SCTP_BASE_INFO(vtag_timewait)[(tag % SCTP_STACK_VTAG_HASH_SIZE)]; - if (!LIST_EMPTY(chain)) { - LIST_FOREACH(twait_block, chain, sctp_nxt_tagblock) { - for (i = 0; i < SCTP_NUMBER_IN_VTAG_BLOCK; i++) { - if ((twait_block->vtag_block[i].v_tag == tag) && - (twait_block->vtag_block[i].lport == lport) && - (twait_block->vtag_block[i].rport == rport)) { - found = 1; - break; - } - } - if (found) + LIST_FOREACH(twait_block, chain, sctp_nxt_tagblock) { + for (i = 0; i < SCTP_NUMBER_IN_VTAG_BLOCK; i++) { + if ((twait_block->vtag_block[i].v_tag == tag) && + (twait_block->vtag_block[i].lport == lport) && + (twait_block->vtag_block[i].rport == rport)) { + found = 1; break; - } + } + } + if (found) + break; } SCTP_INP_INFO_WUNLOCK(); return (found); } void sctp_add_vtag_to_timewait(uint32_t tag, uint32_t time, uint16_t lport, uint16_t rport) @@ -5250,52 +5272,50 @@ sctp_add_vtag_to_timewait(uint32_t tag, if (time == 0) { /* Its disabled */ return; } (void)SCTP_GETTIME_TIMEVAL(&now); chain = &SCTP_BASE_INFO(vtag_timewait)[(tag % SCTP_STACK_VTAG_HASH_SIZE)]; set = 0; - if (!LIST_EMPTY(chain)) { + LIST_FOREACH(twait_block, chain, sctp_nxt_tagblock) { /* Block(s) present, lets find space, and expire on the fly */ - LIST_FOREACH(twait_block, chain, sctp_nxt_tagblock) { - for (i = 0; i < SCTP_NUMBER_IN_VTAG_BLOCK; i++) { - if ((twait_block->vtag_block[i].v_tag == 0) && - !set) { - twait_block->vtag_block[i].tv_sec_at_expire = - now.tv_sec + time; + for (i = 0; i < SCTP_NUMBER_IN_VTAG_BLOCK; i++) { + if ((twait_block->vtag_block[i].v_tag == 0) && + !set) { + twait_block->vtag_block[i].tv_sec_at_expire = + now.tv_sec + time; + twait_block->vtag_block[i].v_tag = tag; + twait_block->vtag_block[i].lport = lport; + twait_block->vtag_block[i].rport = rport; + set = 1; + } else if ((twait_block->vtag_block[i].v_tag) && + ((long)twait_block->vtag_block[i].tv_sec_at_expire < now.tv_sec)) { + /* Audit expires this guy */ + twait_block->vtag_block[i].tv_sec_at_expire = 0; + twait_block->vtag_block[i].v_tag = 0; + twait_block->vtag_block[i].lport = 0; + twait_block->vtag_block[i].rport = 0; + if (set == 0) { + /* Reuse it for my new tag */ + twait_block->vtag_block[i].tv_sec_at_expire = now.tv_sec + time; twait_block->vtag_block[i].v_tag = tag; twait_block->vtag_block[i].lport = lport; twait_block->vtag_block[i].rport = rport; set = 1; - } else if ((twait_block->vtag_block[i].v_tag) && - ((long)twait_block->vtag_block[i].tv_sec_at_expire < now.tv_sec)) { - /* Audit expires this guy */ - twait_block->vtag_block[i].tv_sec_at_expire = 0; - twait_block->vtag_block[i].v_tag = 0; - twait_block->vtag_block[i].lport = 0; - twait_block->vtag_block[i].rport = 0; - if (set == 0) { - /* Reuse it for my new tag */ - twait_block->vtag_block[i].tv_sec_at_expire = now.tv_sec + time; - twait_block->vtag_block[i].v_tag = tag; - twait_block->vtag_block[i].lport = lport; - twait_block->vtag_block[i].rport = rport; - set = 1; - } } } - if (set) { - /* - * We only do up to the block where we can - * place our tag for audits - */ - break; - } + } + if (set) { + /* + * We only do up to the block where we can + * place our tag for audits + */ + break; } } /* Need to add a new block to chain */ if (!set) { SCTP_MALLOC(twait_block, struct sctp_tagblock *, sizeof(struct sctp_tagblock), SCTP_M_TIMW); if (twait_block == NULL) { #ifdef INVARIANTS @@ -5871,16 +5891,17 @@ sctp_free_assoc(struct sctp_inpcb *inp, LIST_REMOVE(shared_key, next); sctp_free_sharedkey(shared_key); /*sa_ignore FREED_MEMORY*/ } /* Insert new items here :> */ /* Get rid of LOCK */ + SCTP_TCB_UNLOCK(stcb); SCTP_TCB_LOCK_DESTROY(stcb); SCTP_TCB_SEND_LOCK_DESTROY(stcb); if (from_inpcbfree == SCTP_NORMAL_PROC) { SCTP_INP_INFO_WUNLOCK(); SCTP_INP_RLOCK(inp); } #if defined(__APPLE__) /* TEMP CODE */ stcb->freed_from_where = from_location; @@ -6596,16 +6617,35 @@ sctp_pcb_init() bzero(&SCTP_BASE_STATS, sizeof(struct sctpstat)); SCTP_BASE_STAT(sctps_discontinuitytime).tv_sec = (uint32_t)tv.tv_sec; SCTP_BASE_STAT(sctps_discontinuitytime).tv_usec = (uint32_t)tv.tv_usec; #endif /* init the empty list of (All) Endpoints */ LIST_INIT(&SCTP_BASE_INFO(listhead)); #if defined(__APPLE__) LIST_INIT(&SCTP_BASE_INFO(inplisthead)); +#if defined(APPLE_LEOPARD) || defined(APPLE_SNOWLEOPARD) || defined(APPLE_LION) || defined(APPLE_MOUNTAINLION) + SCTP_BASE_INFO(sctbinfo).listhead = &SCTP_BASE_INFO(inplisthead); + SCTP_BASE_INFO(sctbinfo).mtx_grp_attr = lck_grp_attr_alloc_init(); + lck_grp_attr_setdefault(SCTP_BASE_INFO(sctbinfo).mtx_grp_attr); + SCTP_BASE_INFO(sctbinfo).mtx_grp = lck_grp_alloc_init("sctppcb", SCTP_BASE_INFO(sctbinfo).mtx_grp_attr); + SCTP_BASE_INFO(sctbinfo).mtx_attr = lck_attr_alloc_init(); + lck_attr_setdefault(SCTP_BASE_INFO(sctbinfo).mtx_attr); +#else + SCTP_BASE_INFO(sctbinfo).ipi_listhead = &SCTP_BASE_INFO(inplisthead); + SCTP_BASE_INFO(sctbinfo).ipi_lock_grp_attr = lck_grp_attr_alloc_init(); + lck_grp_attr_setdefault(SCTP_BASE_INFO(sctbinfo).ipi_lock_grp_attr); + SCTP_BASE_INFO(sctbinfo).ipi_lock_grp = lck_grp_alloc_init("sctppcb", SCTP_BASE_INFO(sctbinfo).ipi_lock_grp_attr); + SCTP_BASE_INFO(sctbinfo).ipi_lock_attr = lck_attr_alloc_init(); + lck_attr_setdefault(SCTP_BASE_INFO(sctbinfo).ipi_lock_attr); +#endif +#if !defined(APPLE_LEOPARD) && !defined(APPLE_SNOWLEOPARD) && !defined(APPLE_LION) && !defined(APPLE_MOUNTAINLION) + SCTP_BASE_INFO(sctbinfo).ipi_gc = sctp_gc; + in_pcbinfo_attach(&SCTP_BASE_INFO(sctbinfo)); +#endif #endif /* init the hash table of endpoints */ #if defined(__FreeBSD__) #if defined(__FreeBSD_cc_version) && __FreeBSD_cc_version >= 440000 TUNABLE_INT_FETCH("net.inet.sctp.tcbhashsize", &SCTP_BASE_SYSCTL(sctp_hashtblsize)); TUNABLE_INT_FETCH("net.inet.sctp.pcbhashsize", &SCTP_BASE_SYSCTL(sctp_pcbtblsize)); @@ -6669,27 +6709,16 @@ sctp_pcb_init() (sctp_max_number_of_assoc * SCTP_BASE_SYSCTL(sctp_chunkscale))); SCTP_ZONE_INIT(SCTP_BASE_INFO(ipi_zone_asconf_ack), "sctp_asconf_ack", sizeof(struct sctp_asconf_ack), (sctp_max_number_of_assoc * SCTP_BASE_SYSCTL(sctp_chunkscale))); /* Master Lock INIT for info structure */ -#if defined(__APPLE__) - /* allocate the lock group attribute for SCTP PCB mutexes */ - SCTP_BASE_INFO(mtx_grp_attr) = lck_grp_attr_alloc_init(); - lck_grp_attr_setdefault(SCTP_BASE_INFO(mtx_grp_attr)); - /* allocate the lock group for SCTP PCB mutexes */ - SCTP_BASE_INFO(mtx_grp) = lck_grp_alloc_init("sctppcb", - SCTP_BASE_INFO(mtx_grp_attr)); - /* allocate the lock attribute for SCTP PCB mutexes */ - SCTP_BASE_INFO(mtx_attr) = lck_attr_alloc_init(); - lck_attr_setdefault(SCTP_BASE_INFO(mtx_attr)); -#endif /* __APPLE__ */ SCTP_INP_INFO_LOCK_INIT(); SCTP_STATLOG_INIT_LOCK(); SCTP_IPI_COUNT_INIT(); SCTP_IPI_ADDR_INIT(); #ifdef SCTP_PACKET_LOGGING SCTP_IP_PKTLOG_INIT(); #endif @@ -6717,17 +6746,16 @@ sctp_pcb_init() SCTP_BASE_INFO(ipi_free_chunks) = 0; SCTP_OS_TIMER_INIT(&SCTP_BASE_INFO(addr_wq_timer.timer)); /* Init the TIMEWAIT list */ for (i = 0; i < SCTP_STACK_VTAG_HASH_SIZE; i++) { LIST_INIT(&SCTP_BASE_INFO(vtag_timewait)[i]); } - #if defined(SCTP_PROCESS_LEVEL_LOCKS) #if defined(__Userspace_os_Windows) InitializeConditionVariable(&sctp_it_ctl.iterator_wakeup); #else (void)pthread_cond_init(&sctp_it_ctl.iterator_wakeup, NULL); #endif #endif sctp_startup_iterator(); @@ -6772,79 +6800,101 @@ sctp_pcb_finish(void) struct sctp_vrflist *vrf_bucket; struct sctp_vrf *vrf, *nvrf; struct sctp_ifn *ifn, *nifn; struct sctp_ifa *ifa, *nifa; struct sctpvtaghead *chain; struct sctp_tagblock *twait_block, *prev_twait_block; struct sctp_laddr *wi, *nwi; int i; - -#if defined(__FreeBSD__) - /* Free BSD the it thread never exits - * but we do clean up. The only way - * freebsd reaches here if we have VRF's - * but we still add the ifdef to make it - * compile on old versions. - */ - { - struct sctp_iterator *it, *nit; - - SCTP_IPI_ITERATOR_WQ_LOCK(); - TAILQ_FOREACH_SAFE(it, &sctp_it_ctl.iteratorhead, sctp_nxt_itr, nit) { - if (it->vn != curvnet) { - continue; - } - TAILQ_REMOVE(&sctp_it_ctl.iteratorhead, it, sctp_nxt_itr); - if (it->function_atend != NULL) { - (*it->function_atend) (it->pointer, it->val); - } - SCTP_FREE(it,SCTP_M_ITER); - } - SCTP_IPI_ITERATOR_WQ_UNLOCK(); - SCTP_ITERATOR_LOCK(); - if ((sctp_it_ctl.cur_it) && - (sctp_it_ctl.cur_it->vn == curvnet)) { - sctp_it_ctl.iterator_flags |= SCTP_ITERATOR_STOP_CUR_IT; - } - SCTP_ITERATOR_UNLOCK(); - } -#else + struct sctp_iterator *it, *nit; + +#if !defined(__FreeBSD__) /* Notify the iterator to exit. */ SCTP_IPI_ITERATOR_WQ_LOCK(); sctp_it_ctl.iterator_flags |= SCTP_ITERATOR_MUST_EXIT; sctp_wakeup_iterator(); SCTP_IPI_ITERATOR_WQ_UNLOCK(); #endif #if defined(__APPLE__) +#if !defined(APPLE_LEOPARD) && !defined(APPLE_SNOWLEOPARD) && !defined(APPLE_LION) && !defined(APPLE_MOUNTAINLION) + in_pcbinfo_detach(&SCTP_BASE_INFO(sctbinfo)); +#endif SCTP_IPI_ITERATOR_WQ_LOCK(); do { msleep(&sctp_it_ctl.iterator_flags, sctp_it_ctl.ipi_iterator_wq_mtx, 0, "waiting_for_work", 0); } while ((sctp_it_ctl.iterator_flags & SCTP_ITERATOR_EXITED) == 0); thread_deallocate(sctp_it_ctl.thread_proc); SCTP_IPI_ITERATOR_WQ_UNLOCK(); - SCTP_IPI_ITERATOR_WQ_DESTROY(); - SCTP_ITERATOR_LOCK_DESTROY(); #endif #if defined(__Windows__) if (sctp_it_ctl.iterator_thread_obj != NULL) { NTSTATUS status = STATUS_SUCCESS; KeSetEvent(&sctp_it_ctl.iterator_wakeup[1], IO_NO_INCREMENT, FALSE); status = KeWaitForSingleObject(sctp_it_ctl.iterator_thread_obj, Executive, KernelMode, FALSE, NULL); ObDereferenceObject(sctp_it_ctl.iterator_thread_obj); } #endif - +#if defined(__Userspace__) + if (sctp_it_ctl.thread_proc) { +#if defined(__Userspace_os_Windows) + WaitForSingleObject(sctp_it_ctl.thread_proc, INFINITE); + CloseHandle(sctp_it_ctl.thread_proc); + sctp_it_ctl.thread_proc = NULL; +#else + pthread_join(sctp_it_ctl.thread_proc, NULL); + sctp_it_ctl.thread_proc = 0; +#endif + } +#endif +#if defined(SCTP_PROCESS_LEVEL_LOCKS) +#if defined(__Userspace_os_Windows) + DeleteConditionVariable(&sctp_it_ctl.iterator_wakeup); +#else + pthread_cond_destroy(&sctp_it_ctl.iterator_wakeup); +#endif +#endif + /* In FreeBSD the iterator thread never exits + * but we do clean up. + * The only way FreeBSD reaches here is if we have VRF's + * but we still add the ifdef to make it compile on old versions. + */ + SCTP_IPI_ITERATOR_WQ_LOCK(); + TAILQ_FOREACH_SAFE(it, &sctp_it_ctl.iteratorhead, sctp_nxt_itr, nit) { +#if defined(__FreeBSD__) && __FreeBSD_version >= 801000 + if (it->vn != curvnet) { + continue; + } +#endif + TAILQ_REMOVE(&sctp_it_ctl.iteratorhead, it, sctp_nxt_itr); + if (it->function_atend != NULL) { + (*it->function_atend) (it->pointer, it->val); + } + SCTP_FREE(it,SCTP_M_ITER); + } + SCTP_IPI_ITERATOR_WQ_UNLOCK(); +#if defined(__FreeBSD__) && __FreeBSD_version >= 801000 + SCTP_ITERATOR_LOCK(); + if ((sctp_it_ctl.cur_it) && + (sctp_it_ctl.cur_it->vn == curvnet)) { + sctp_it_ctl.iterator_flags |= SCTP_ITERATOR_STOP_CUR_IT; + } + SCTP_ITERATOR_UNLOCK(); +#endif +#if !defined(__FreeBSD__) + SCTP_IPI_ITERATOR_WQ_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(); SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_laddr), wi); } SCTP_WQ_ADDR_UNLOCK(); @@ -6872,18 +6922,20 @@ sctp_pcb_finish(void) LIST_REMOVE(vrf, next_vrf); SCTP_FREE(vrf, SCTP_M_VRF); } /* free the vrf hashes */ SCTP_HASH_FREE(SCTP_BASE_INFO(sctp_vrfhash), SCTP_BASE_INFO(hashvrfmark)); SCTP_HASH_FREE(SCTP_BASE_INFO(vrf_ifn_hash), SCTP_BASE_INFO(vrf_ifn_hashmark)); #if defined(__Userspace__) && !defined(__Userspace_os_Windows) /* free memory allocated by getifaddrs call */ +#if defined(INET) || defined(INET6) freeifaddrs(g_interfaces); #endif +#endif /* free the TIMEWAIT list elements malloc'd in the function * sctp_add_vtag_to_timewait()... */ for (i = 0; i < SCTP_STACK_VTAG_HASH_SIZE; i++) { chain = &SCTP_BASE_INFO(vtag_timewait)[i]; if (!LIST_EMPTY(chain)) { prev_twait_block = NULL; @@ -6904,26 +6956,30 @@ sctp_pcb_finish(void) #ifdef SCTP_PACKET_LOGGING SCTP_IP_PKTLOG_DESTROY(); #endif SCTP_IPI_ADDR_DESTROY(); #if defined(__APPLE__) SCTP_IPI_COUNT_DESTROY(); #endif SCTP_STATLOG_DESTROY(); -#if !defined(__Userspace__) SCTP_INP_INFO_LOCK_DESTROY(); -#endif SCTP_WQ_ADDR_DESTROY(); #if defined(__APPLE__) - lck_grp_attr_free(SCTP_BASE_INFO(mtx_grp_attr)); - lck_grp_free(SCTP_BASE_INFO(mtx_grp)); - lck_attr_free(SCTP_BASE_INFO(mtx_attr)); +#if defined(APPLE_LEOPARD) || defined(APPLE_SNOWLEOPARD) || defined(APPLE_LION) || defined(APPLE_MOUNTAINLION) + lck_grp_attr_free(SCTP_BASE_INFO(sctbinfo).mtx_grp_attr); + lck_grp_free(SCTP_BASE_INFO(sctbinfo).mtx_grp); + lck_attr_free(SCTP_BASE_INFO(sctbinfo).mtx_attr); +#else + lck_grp_attr_free(SCTP_BASE_INFO(sctbinfo).ipi_lock_grp_attr); + lck_grp_free(SCTP_BASE_INFO(sctbinfo).ipi_lock_grp); + lck_attr_free(SCTP_BASE_INFO(sctbinfo).ipi_lock_attr); +#endif #endif #if defined(__Userspace__) SCTP_TIMERQ_LOCK_DESTROY(); SCTP_ZONE_DESTROY(zone_mbuf); SCTP_ZONE_DESTROY(zone_clust); SCTP_ZONE_DESTROY(zone_ext_refcnt); #endif #if defined(__Windows__) || defined(__FreeBSD__) || defined(__Userspace__) @@ -7651,40 +7707,38 @@ sctp_is_vtag_good(uint32_t tag, uint16_t SCTP_INP_INFO_RUNLOCK(); return (0); } } skip_vtag_check: chain = &SCTP_BASE_INFO(vtag_timewait)[(tag % SCTP_STACK_VTAG_HASH_SIZE)]; /* Now what about timed wait ? */ - if (!LIST_EMPTY(chain)) { + LIST_FOREACH(twait_block, chain, sctp_nxt_tagblock) { /* * Block(s) are present, lets see if we have this tag in the * list */ - LIST_FOREACH(twait_block, chain, sctp_nxt_tagblock) { - for (i = 0; i < SCTP_NUMBER_IN_VTAG_BLOCK; i++) { - if (twait_block->vtag_block[i].v_tag == 0) { - /* not used */ - continue; - } else if ((long)twait_block->vtag_block[i].tv_sec_at_expire < - now->tv_sec) { - /* Audit expires this guy */ - twait_block->vtag_block[i].tv_sec_at_expire = 0; - twait_block->vtag_block[i].v_tag = 0; - twait_block->vtag_block[i].lport = 0; - twait_block->vtag_block[i].rport = 0; - } else if ((twait_block->vtag_block[i].v_tag == tag) && - (twait_block->vtag_block[i].lport == lport) && - (twait_block->vtag_block[i].rport == rport)) { - /* Bad tag, sorry :< */ - SCTP_INP_INFO_RUNLOCK(); - return (0); - } + for (i = 0; i < SCTP_NUMBER_IN_VTAG_BLOCK; i++) { + if (twait_block->vtag_block[i].v_tag == 0) { + /* not used */ + continue; + } else if ((long)twait_block->vtag_block[i].tv_sec_at_expire < + now->tv_sec) { + /* Audit expires this guy */ + twait_block->vtag_block[i].tv_sec_at_expire = 0; + twait_block->vtag_block[i].v_tag = 0; + twait_block->vtag_block[i].lport = 0; + twait_block->vtag_block[i].rport = 0; + } else if ((twait_block->vtag_block[i].v_tag == tag) && + (twait_block->vtag_block[i].lport == lport) && + (twait_block->vtag_block[i].rport == rport)) { + /* Bad tag, sorry :< */ + SCTP_INP_INFO_RUNLOCK(); + return (0); } } } SCTP_INP_INFO_RUNLOCK(); return (1); } static void
--- a/netwerk/sctp/src/netinet/sctp_pcb.h +++ b/netwerk/sctp/src/netinet/sctp_pcb.h @@ -27,17 +27,17 @@ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_pcb.h 246687 2013-02-11 21:02:49Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp_pcb.h 254248 2013-08-12 13:52:15Z tuexen $"); #endif #ifndef _NETINET_SCTP_PCB_H_ #define _NETINET_SCTP_PCB_H_ #include <netinet/sctp_os.h> #include <netinet/sctp.h> #include <netinet/sctp_constants.h> @@ -184,16 +184,17 @@ struct sctp_epinfo { struct sctp_ifnlist *vrf_ifn_hash; u_long vrf_ifn_hashmark; struct sctppcbhead listhead; struct sctpladdr addr_wq; #if defined(__APPLE__) struct inpcbhead inplisthead; + struct inpcbinfo sctbinfo; #endif /* ep zone info */ sctp_zone_t ipi_zone_ep; sctp_zone_t ipi_zone_asoc; sctp_zone_t ipi_zone_laddr; sctp_zone_t ipi_zone_net; sctp_zone_t ipi_zone_chunk; sctp_zone_t ipi_zone_readq; @@ -218,30 +219,22 @@ struct sctp_epinfo { #elif defined(SCTP_PROCESS_LEVEL_LOCKS) userland_mutex_t ipi_ep_mtx; userland_mutex_t ipi_addr_mtx; userland_mutex_t ipi_count_mtx; userland_mutex_t ipi_pktlog_mtx; userland_mutex_t wq_addr_mtx; #elif defined(__APPLE__) #ifdef _KERN_LOCKS_H_ - lck_grp_attr_t *mtx_grp_attr; - lck_grp_t *mtx_grp; - lck_attr_t *mtx_attr; - lck_rw_t *ipi_ep_mtx; lck_mtx_t *ipi_addr_mtx; lck_mtx_t *ipi_count_mtx; lck_mtx_t *ipi_pktlog_mtx; lck_mtx_t *logging_mtx; lck_mtx_t *wq_addr_mtx; #else - void *mtx_grp_attr; - void *mtx_grp; - void *mtx_attr; - void *ipi_ep_mtx; void *ipi_count_mtx; void *logging_mtx; #endif /* _KERN_LOCKS_H_ */ #elif defined(__Windows__) struct rwlock ipi_ep_lock; struct rwlock ipi_addr_lock; struct spinlock ipi_pktlog_mtx; struct rwlock wq_addr_mtx; @@ -464,18 +457,18 @@ struct sctp_inpcb { /* list of addrs in use by the EP, NULL if bound-all */ struct sctpladdr sctp_addr_list; /* used for source address selection rotation when we are subset bound */ struct sctp_laddr *next_addr_touse; /* back pointer to our socket */ struct socket *sctp_socket; + uint64_t sctp_features; /* Feature flags */ uint32_t sctp_flags; /* INP state flag set */ - uint32_t sctp_features; /* Feature flags */ uint32_t sctp_mobility_features; /* Mobility Feature flags */ struct sctp_pcb sctp_ep;/* SCTP ep data */ /* head of the hash of all associations */ struct sctpasochead *sctp_tcbhash; u_long sctp_hashmark; /* head of the list of all associations */ struct sctpasochead sctp_asoc_list; #ifdef SCTP_TRACK_FREED_ASOCS
--- a/netwerk/sctp/src/netinet/sctp_process_lock.h +++ b/netwerk/sctp/src/netinet/sctp_process_lock.h @@ -121,16 +121,18 @@ #define SCTP_WQ_ADDR_LOCK() \ EnterCriticalSection(&SCTP_BASE_INFO(wq_addr_mtx)) #define SCTP_WQ_ADDR_UNLOCK() \ LeaveCriticalSection(&SCTP_BASE_INFO(wq_addr_mtx)) #define SCTP_INP_INFO_LOCK_INIT() \ InitializeCriticalSection(&SCTP_BASE_INFO(ipi_ep_mtx)) +#define SCTP_INP_INFO_LOCK_DESTROY() \ + DeleteCriticalSection(&SCTP_BASE_INFO(ipi_ep_mtx)) #define SCTP_INP_INFO_RLOCK() \ EnterCriticalSection(&SCTP_BASE_INFO(ipi_ep_mtx)) #define SCTP_INP_INFO_TRYLOCK() \ TryEnterCriticalSection(&SCTP_BASE_INFO(ipi_ep_mtx)) #define SCTP_INP_INFO_WLOCK() \ EnterCriticalSection(&SCTP_BASE_INFO(ipi_ep_mtx)) #define SCTP_INP_INFO_RUNLOCK() \ LeaveCriticalSection(&SCTP_BASE_INFO(ipi_ep_mtx)) @@ -270,16 +272,18 @@ #define SCTP_WQ_ADDR_LOCK() \ (void)pthread_mutex_lock(&SCTP_BASE_INFO(wq_addr_mtx)) #define SCTP_WQ_ADDR_UNLOCK() \ (void)pthread_mutex_unlock(&SCTP_BASE_INFO(wq_addr_mtx)) #define SCTP_INP_INFO_LOCK_INIT() \ (void)pthread_mutex_init(&SCTP_BASE_INFO(ipi_ep_mtx), NULL) +#define SCTP_INP_INFO_LOCK_DESTROY() \ + (void)pthread_mutex_destroy(&SCTP_BASE_INFO(ipi_ep_mtx)) #define SCTP_INP_INFO_RLOCK() \ (void)pthread_mutex_lock(&SCTP_BASE_INFO(ipi_ep_mtx)) #define SCTP_INP_INFO_TRYLOCK() \ (!(pthread_mutex_trylock(&SCTP_BASE_INFO(ipi_ep_mtx)))) #define SCTP_INP_INFO_WLOCK() \ (void)pthread_mutex_lock(&SCTP_BASE_INFO(ipi_ep_mtx)) #define SCTP_INP_INFO_RUNLOCK() \ (void)pthread_mutex_unlock(&SCTP_BASE_INFO(ipi_ep_mtx))
--- a/netwerk/sctp/src/netinet/sctp_sha1.c +++ b/netwerk/sctp/src/netinet/sctp_sha1.c @@ -1,12 +1,13 @@ /*- * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved. * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved. - * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved. + * Copyright (c) 2008-2013, by Michael Tuexen. All rights reserved. + * Copyright (c) 2013, by Lally Singh. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * a) Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * b) Redistributions in binary form must reproduce the above copyright @@ -25,36 +26,94 @@ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ -#ifdef __FreeBSD__ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); +#include <netinet/sctp_sha1.h> + +#if defined(SCTP_USE_NSS_SHA1) +/* A SHA-1 Digest is 160 bits, or 20 bytes */ +#define SHA_DIGEST_LENGTH (20) + +void +sctp_sha1_init(struct sctp_sha1_context *ctx) +{ + ctx->pk11_ctx = PK11_CreateDigestContext(SEC_OID_SHA1); + PK11_DigestBegin(ctx->pk11_ctx); +} + +void +sctp_sha1_update(struct sctp_sha1_context *ctx, const unsigned char *ptr, unsigned int siz) +{ + PK11_DigestOp(ctx->pk11_ctx, ptr, siz); +} + +void +sctp_sha1_final(unsigned char *digest, struct sctp_sha1_context *ctx) +{ + unsigned int output_len = 0; + + PK11_DigestFinal(ctx->pk11_ctx, digest, &output_len, SHA_DIGEST_LENGTH); + PK11_DestroyContext(ctx->pk11_ctx, PR_TRUE); +} + +#elif defined(SCTP_USE_OPENSSL_SHA1) + +void +sctp_sha1_init(struct sctp_sha1_context *ctx) +{ + SHA1_Init(&ctx->sha_ctx); +} + +void +sctp_sha1_update(struct sctp_sha1_context *ctx, const unsigned char *ptr, unsigned int siz) +{ + SHA1_Update(&ctx->sha_ctx, ptr, (unsigned long)siz); +} + +void +sctp_sha1_final(unsigned char *digest, struct sctp_sha1_context *ctx) +{ + SHA1_Final(digest, &ctx->sha_ctx); +} + +#else + +#include <string.h> +#if defined(__Userspace_os_Windows) +#include <winsock2.h> +#elif !defined(__Windows__) +#include <arpa/inet.h> #endif -#include <netinet/sctp_sha1.h> -#if !defined(__Userspace_os_Windows) -#include <sys/param.h> -#if !defined(__Windows__) -#include <arpa/inet.h> -#endif -#else -#include <winsock2.h> -#endif -#if !defined(__Userspace__) -#include <sys/systm.h> -#endif -#include <string.h> +#define F1(B,C,D) (((B & C) | ((~B) & D))) /* 0 <= t <= 19 */ +#define F2(B,C,D) (B ^ C ^ D) /* 20 <= t <= 39 */ +#define F3(B,C,D) ((B & C) | (B & D) | (C & D)) /* 40 <= t <= 59 */ +#define F4(B,C,D) (B ^ C ^ D) /* 600 <= t <= 79 */ + +/* circular shift */ +#define CSHIFT(A,B) ((B << A) | (B >> (32-A))) + +#define K1 0x5a827999 /* 0 <= t <= 19 */ +#define K2 0x6ed9eba1 /* 20 <= t <= 39 */ +#define K3 0x8f1bbcdc /* 40 <= t <= 59 */ +#define K4 0xca62c1d6 /* 60 <= t <= 79 */ + +#define H0INIT 0x67452301 +#define H1INIT 0xefcdab89 +#define H2INIT 0x98badcfe +#define H3INIT 0x10325476 +#define H4INIT 0xc3d2e1f0 + void -SHA1_Init(struct sha1_context *ctx) +sctp_sha1_init(struct sctp_sha1_context *ctx) { /* Init the SHA-1 context structure */ ctx->A = 0; ctx->B = 0; ctx->C = 0; ctx->D = 0; ctx->E = 0; ctx->H0 = H0INIT; @@ -64,17 +123,17 @@ SHA1_Init(struct sha1_context *ctx) ctx->H4 = H4INIT; ctx->TEMP = 0; memset(ctx->words, 0, sizeof(ctx->words)); ctx->how_many_in_block = 0; ctx->running_total = 0; } static void -sha1_process_a_block(struct sha1_context *ctx, unsigned int *block) +sctp_sha1_process_a_block(struct sctp_sha1_context *ctx, unsigned int *block) { int i; /* init the W0-W15 to the block of words being hashed. */ /* step a) */ for (i = 0; i < 16; i++) { ctx->words[i] = ntohl(block[i]); } @@ -128,49 +187,48 @@ sha1_process_a_block(struct sha1_context /* step e) */ ctx->H0 = (ctx->H0) + (ctx->A); ctx->H1 = (ctx->H1) + (ctx->B); ctx->H2 = (ctx->H2) + (ctx->C); ctx->H3 = (ctx->H3) + (ctx->D); ctx->H4 = (ctx->H4) + (ctx->E); } - void -SHA1_Update(struct sha1_context *ctx, const unsigned char *ptr, int siz) +sctp_sha1_update(struct sctp_sha1_context *ctx, const unsigned char *ptr, unsigned int siz) { - int number_left, left_to_fill; + unsigned int number_left, left_to_fill; number_left = siz; while (number_left > 0) { left_to_fill = sizeof(ctx->sha_block) - ctx->how_many_in_block; if (left_to_fill > number_left) { /* can only partially fill up this one */ memcpy(&ctx->sha_block[ctx->how_many_in_block], ptr, number_left); ctx->how_many_in_block += number_left; ctx->running_total += number_left; number_left = 0; break; } else { /* block is now full, process it */ memcpy(&ctx->sha_block[ctx->how_many_in_block], ptr, left_to_fill); - sha1_process_a_block(ctx, + sctp_sha1_process_a_block(ctx, (unsigned int *)ctx->sha_block); number_left -= left_to_fill; ctx->running_total += left_to_fill; ctx->how_many_in_block = 0; ptr = (const unsigned char *)(ptr + left_to_fill); } } } void -SHA1_Final(unsigned char *digest, struct sha1_context *ctx) +sctp_sha1_final(unsigned char *digest, struct sctp_sha1_context *ctx) { /* * if any left in block fill with padding and process. Then transfer * the digest to the pointer. At the last block some special rules * need to apply. We must add a 1 bit following the message, then we * pad with 0's. The total size is encoded as a 64 bit number at the * end. Now if the last buffer has more than 55 octets in it we * cannot fit the 64 bit number + 10000000 pad on the end and must @@ -186,46 +244,46 @@ SHA1_Final(unsigned char *digest, struct /* * special case, we need to process two blocks here. One for * the current stuff plus possibly the pad. The other for * the size. */ left_to_fill = sizeof(ctx->sha_block) - ctx->how_many_in_block; if (left_to_fill == 0) { /* Should not really happen but I am paranoid */ - sha1_process_a_block(ctx, + sctp_sha1_process_a_block(ctx, (unsigned int *)ctx->sha_block); /* init last block, a bit different than the rest */ ctx->sha_block[0] = '\x80'; for (i = 1; i < sizeof(ctx->sha_block); i++) { ctx->sha_block[i] = 0x0; } } else if (left_to_fill == 1) { ctx->sha_block[ctx->how_many_in_block] = '\x80'; - sha1_process_a_block(ctx, + sctp_sha1_process_a_block(ctx, (unsigned int *)ctx->sha_block); /* init last block */ memset(ctx->sha_block, 0, sizeof(ctx->sha_block)); } else { ctx->sha_block[ctx->how_many_in_block] = '\x80'; for (i = (ctx->how_many_in_block + 1); i < sizeof(ctx->sha_block); i++) { ctx->sha_block[i] = 0x0; } - sha1_process_a_block(ctx, + sctp_sha1_process_a_block(ctx, (unsigned int *)ctx->sha_block); /* init last block */ memset(ctx->sha_block, 0, sizeof(ctx->sha_block)); } /* This is in bits so multiply by 8 */ ctx->running_total *= 8; ptr = (unsigned int *)&ctx->sha_block[60]; *ptr = htonl(ctx->running_total); - sha1_process_a_block(ctx, (unsigned int *)ctx->sha_block); + sctp_sha1_process_a_block(ctx, (unsigned int *)ctx->sha_block); } else { /* * easy case, we just pad this message to size - end with 0 * add the magic 0x80 to the next word and then put the * network byte order size in the last spot and process the * block. */ ctx->sha_block[ctx->how_many_in_block] = '\x80'; @@ -233,17 +291,17 @@ SHA1_Final(unsigned char *digest, struct i < sizeof(ctx->sha_block); i++) { ctx->sha_block[i] = 0x0; } /* get last int spot */ ctx->running_total *= 8; ptr = (unsigned int *)&ctx->sha_block[60]; *ptr = htonl(ctx->running_total); - sha1_process_a_block(ctx, (unsigned int *)ctx->sha_block); + sctp_sha1_process_a_block(ctx, (unsigned int *)ctx->sha_block); } /* transfer the digest back to the user */ digest[3] = (ctx->H0 & 0xff); digest[2] = ((ctx->H0 >> 8) & 0xff); digest[1] = ((ctx->H0 >> 16) & 0xff); digest[0] = ((ctx->H0 >> 24) & 0xff); digest[7] = (ctx->H1 & 0xff); @@ -261,8 +319,10 @@ SHA1_Final(unsigned char *digest, struct digest[13] = ((ctx->H3 >> 16) & 0xff); digest[12] = ((ctx->H3 >> 24) & 0xff); digest[19] = (ctx->H4 & 0xff); digest[18] = ((ctx->H4 >> 8) & 0xff); digest[17] = ((ctx->H4 >> 16) & 0xff); digest[16] = ((ctx->H4 >> 24) & 0xff); } + +#endif
--- a/netwerk/sctp/src/netinet/sctp_sha1.h +++ b/netwerk/sctp/src/netinet/sctp_sha1.h @@ -31,22 +31,41 @@ */ #ifdef __FreeBSD__ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); #endif -#ifndef __SCTP_SLA1_h__ -#define __SCTP_SLA1_h__ +#ifndef __NETINET_SCTP_SHA1_H__ +#define __NETINET_SCTP_SHA1_H__ #include <sys/types.h> +#if defined(SCTP_USE_NSS_SHA1) +#if defined(__Userspace_os_Darwin) +/* The NSS sources require __APPLE__ to be defined. + * XXX: Remove this ugly hack once the platform defines have been cleaned up. + */ +#define __APPLE__ +#endif +#include <pk11pub.h> +#if defined(__Userspace_os_Darwin) +#undef __APPLE__ +#endif +#elif defined(SCTP_USE_OPENSSL_SHA1) +#include <openssl/sha.h> +#endif -struct sha1_context { +struct sctp_sha1_context { +#if defined(SCTP_USE_NSS_SHA1) + struct PK11Context *pk11_ctx; +#elif defined(SCTP_USE_OPENSSL_SHA1) + SHA_CTX sha_ctx; +#else unsigned int A; unsigned int B; unsigned int C; unsigned int D; unsigned int E; unsigned int H0; unsigned int H1; unsigned int H2; @@ -54,45 +73,25 @@ struct sha1_context { unsigned int H4; unsigned int words[80]; unsigned int TEMP; /* block I am collecting to process */ char sha_block[64]; /* collected so far */ int how_many_in_block; unsigned int running_total; +#endif }; -typedef struct sha1_context SHA1_CTX; - -#define F1(B,C,D) (((B & C) | ((~B) & D))) /* 0 <= t <= 19 */ -#define F2(B,C,D) (B ^ C ^ D) /* 20 <= t <= 39 */ -#define F3(B,C,D) ((B & C) | (B & D) | (C & D)) /* 40 <= t <= 59 */ -#define F4(B,C,D) (B ^ C ^ D) /* 600 <= t <= 79 */ - -/* circular shift */ -#define CSHIFT(A,B) ((B << A) | (B >> (32-A))) - -#define K1 0x5a827999 /* 0 <= t <= 19 */ -#define K2 0x6ed9eba1 /* 20 <= t <= 39 */ -#define K3 0x8f1bbcdc /* 40 <= t <= 59 */ -#define K4 0xca62c1d6 /* 60 <= t <= 79 */ - -#define H0INIT 0x67452301 -#define H1INIT 0xefcdab89 -#define H2INIT 0x98badcfe -#define H3INIT 0x10325476 -#define H4INIT 0xc3d2e1f0 - #if (defined(__APPLE__) && defined(KERNEL)) #ifndef _KERNEL #define _KERNEL #endif #endif #if defined(_KERNEL) || defined(__Userspace__) -void SHA1_Init(struct sha1_context *); -void SHA1_Update(struct sha1_context *, const unsigned char *, int); -void SHA1_Final(unsigned char *, struct sha1_context *); +void sctp_sha1_init(struct sctp_sha1_context *); +void sctp_sha1_update(struct sctp_sha1_context *, const unsigned char *, unsigned int); +void sctp_sha1_final(unsigned char *, struct sctp_sha1_context *); -#endif /* _KERNEL */ #endif +#endif
--- a/netwerk/sctp/src/netinet/sctp_structs.h +++ b/netwerk/sctp/src/netinet/sctp_structs.h @@ -27,17 +27,17 @@ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_structs.h 246595 2013-02-09 17:26:14Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp_structs.h 255190 2013-09-03 19:31:59Z tuexen $"); #endif #ifndef _NETINET_SCTP_STRUCTS_H_ #define _NETINET_SCTP_STRUCTS_H_ #include <netinet/sctp_os.h> #include <netinet/sctp_header.h> #include <netinet/sctp_auth.h> @@ -231,16 +231,19 @@ struct sctp_net_route { void *ro_lle; #endif #if __FreeBSD_version >= 900000 void *ro_ia; int ro_flags; #endif #endif #if defined(__APPLE__) +#if !defined(APPLE_LEOPARD) && !defined(APPLE_SNOWLEOPARD) && !defined(APPLE_LION) && !defined(APPLE_MOUNTAINLION) + struct ifaddr *ro_srcia; +#endif #if !defined(APPLE_LEOPARD) uint32_t ro_flags; #endif #endif union sctp_sockstore _l_addr; /* remote peer addr */ struct sctp_ifa *_s_addr; /* our selected src addr */ }; @@ -488,17 +491,16 @@ struct sctp_tmit_chunk { uint16_t book_size; uint16_t mbcnt; uint16_t auth_keyid; uint8_t holds_key_ref; /* flag if auth keyid refcount is held */ uint8_t pad_inplace; uint8_t do_rtt; uint8_t book_size_scale; uint8_t no_fr_allowed; - uint8_t pr_sctp_on; uint8_t copy_by_ref; uint8_t window_probe; }; /* * The first part of this structure MUST be the entire sinfo structure. Maybe * I should have made it a sub structure... we can circle back later and do * that if we want. @@ -563,17 +565,16 @@ struct sctp_stream_queue_pending { uint32_t context; uint16_t sinfo_flags; uint16_t stream; uint16_t act_flags; uint16_t auth_keyid; uint8_t holds_key_ref; uint8_t msg_is_complete; uint8_t some_taken; - uint8_t pr_sctp_on; uint8_t sender_all_done; uint8_t put_last_out; uint8_t discard_rest; }; /* * this struct contains info that is used to track inbound stream data and * help with ordering. @@ -1247,17 +1248,17 @@ 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; - uint32_t sctp_features; + uint64_t sctp_features; uint16_t port; /* remote UDP encapsulation port */ /* * The mapping array is used to track out of order sequences above * last_acked_seq. 0 indicates packet missing 1 indicates packet * rec'd. We slide it up every time we raise last_acked_seq and 0 * trailing locactions out. If I get a TSN above the array * mappingArraySz, I discard the datagram and let retransmit happen. */
--- a/netwerk/sctp/src/netinet/sctp_sysctl.c +++ b/netwerk/sctp/src/netinet/sctp_sysctl.c @@ -27,17 +27,17 @@ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_sysctl.c 246595 2013-02-09 17:26:14Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp_sysctl.c 254672 2013-08-22 20:29:57Z tuexen $"); #endif #include <netinet/sctp_os.h> #include <netinet/sctp.h> #include <netinet/sctp_constants.h> #include <netinet/sctp_sysctl.h> #include <netinet/sctp_pcb.h> #include <netinet/sctputil.h> @@ -88,16 +88,17 @@ sctp_init_sysctls() SCTP_BASE_SYSCTL(sctp_rto_initial_default) = SCTPCTL_RTO_INITIAL_DEFAULT; SCTP_BASE_SYSCTL(sctp_init_rto_max_default) = SCTPCTL_INIT_RTO_MAX_DEFAULT; SCTP_BASE_SYSCTL(sctp_valid_cookie_life_default) = SCTPCTL_VALID_COOKIE_LIFE_DEFAULT; SCTP_BASE_SYSCTL(sctp_init_rtx_max_default) = SCTPCTL_INIT_RTX_MAX_DEFAULT; SCTP_BASE_SYSCTL(sctp_assoc_rtx_max_default) = SCTPCTL_ASSOC_RTX_MAX_DEFAULT; SCTP_BASE_SYSCTL(sctp_path_rtx_max_default) = SCTPCTL_PATH_RTX_MAX_DEFAULT; SCTP_BASE_SYSCTL(sctp_path_pf_threshold) = SCTPCTL_PATH_PF_THRESHOLD_DEFAULT; SCTP_BASE_SYSCTL(sctp_add_more_threshold) = SCTPCTL_ADD_MORE_ON_OUTPUT_DEFAULT; + SCTP_BASE_SYSCTL(sctp_nr_incoming_streams_default) = SCTPCTL_INCOMING_STREAMS_DEFAULT; SCTP_BASE_SYSCTL(sctp_nr_outgoing_streams_default) = SCTPCTL_OUTGOING_STREAMS_DEFAULT; SCTP_BASE_SYSCTL(sctp_cmt_on_off) = SCTPCTL_CMT_ON_OFF_DEFAULT; /* EY */ SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) = SCTPCTL_NR_SACK_ON_OFF_DEFAULT; SCTP_BASE_SYSCTL(sctp_cmt_use_dac) = SCTPCTL_CMT_USE_DAC_DEFAULT; SCTP_BASE_SYSCTL(sctp_use_cwnd_based_maxburst) = SCTPCTL_CWND_MAXBURST_DEFAULT; SCTP_BASE_SYSCTL(sctp_asconf_auth_nochk) = SCTPCTL_ASCONF_AUTH_NOCHK_DEFAULT; SCTP_BASE_SYSCTL(sctp_auth_disable) = SCTPCTL_AUTH_DISABLE_DEFAULT; @@ -486,17 +487,21 @@ sctp_assoclist(SYSCTL_HANDLER_ARGS) SCTP_INP_RLOCK(inp); if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) { /* if its allgone it is being freed - skip it */ goto skip; } xinpcb.last = 0; xinpcb.local_port = ntohs(inp->sctp_lport); xinpcb.flags = inp->sctp_flags; +#if defined(__FreeBSD__) && __FreeBSD_version < 1000048 + xinpcb.features = (uint32_t)inp->sctp_features; +#else xinpcb.features = inp->sctp_features; +#endif xinpcb.total_sends = inp->total_sends; xinpcb.total_recvs = inp->total_recvs; xinpcb.total_nospaces = inp->total_nospaces; xinpcb.fragmentation_point = inp->sctp_frag_point; so = inp->sctp_socket; if ((so == NULL) || (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) { xinpcb.qlen = 0; @@ -783,16 +788,17 @@ sysctl_sctp_check(SYSCTL_HANDLER_ARGS) RANGECHK(SCTP_BASE_SYSCTL(sctp_rto_initial_default), SCTPCTL_RTO_INITIAL_MIN, SCTPCTL_RTO_INITIAL_MAX); RANGECHK(SCTP_BASE_SYSCTL(sctp_init_rto_max_default), SCTPCTL_INIT_RTO_MAX_MIN, SCTPCTL_INIT_RTO_MAX_MAX); RANGECHK(SCTP_BASE_SYSCTL(sctp_valid_cookie_life_default), SCTPCTL_VALID_COOKIE_LIFE_MIN, SCTPCTL_VALID_COOKIE_LIFE_MAX); RANGECHK(SCTP_BASE_SYSCTL(sctp_init_rtx_max_default), SCTPCTL_INIT_RTX_MAX_MIN, SCTPCTL_INIT_RTX_MAX_MAX); RANGECHK(SCTP_BASE_SYSCTL(sctp_assoc_rtx_max_default), SCTPCTL_ASSOC_RTX_MAX_MIN, SCTPCTL_ASSOC_RTX_MAX_MAX); RANGECHK(SCTP_BASE_SYSCTL(sctp_path_rtx_max_default), SCTPCTL_PATH_RTX_MAX_MIN, SCTPCTL_PATH_RTX_MAX_MAX); RANGECHK(SCTP_BASE_SYSCTL(sctp_path_pf_threshold), SCTPCTL_PATH_PF_THRESHOLD_MIN, SCTPCTL_PATH_PF_THRESHOLD_MAX); RANGECHK(SCTP_BASE_SYSCTL(sctp_add_more_threshold), SCTPCTL_ADD_MORE_ON_OUTPUT_MIN, SCTPCTL_ADD_MORE_ON_OUTPUT_MAX); + RANGECHK(SCTP_BASE_SYSCTL(sctp_nr_incoming_streams_default), SCTPCTL_INCOMING_STREAMS_MIN, SCTPCTL_INCOMING_STREAMS_MAX); RANGECHK(SCTP_BASE_SYSCTL(sctp_nr_outgoing_streams_default), SCTPCTL_OUTGOING_STREAMS_MIN, SCTPCTL_OUTGOING_STREAMS_MAX); RANGECHK(SCTP_BASE_SYSCTL(sctp_cmt_on_off), SCTPCTL_CMT_ON_OFF_MIN, SCTPCTL_CMT_ON_OFF_MAX); /* EY */ RANGECHK(SCTP_BASE_SYSCTL(sctp_nr_sack_on_off), SCTPCTL_NR_SACK_ON_OFF_MIN, SCTPCTL_NR_SACK_ON_OFF_MAX); RANGECHK(SCTP_BASE_SYSCTL(sctp_cmt_use_dac), SCTPCTL_CMT_USE_DAC_MIN, SCTPCTL_CMT_USE_DAC_MAX); RANGECHK(SCTP_BASE_SYSCTL(sctp_use_cwnd_based_maxburst), SCTPCTL_CWND_MAXBURST_MIN, SCTPCTL_CWND_MAXBURST_MAX); RANGECHK(SCTP_BASE_SYSCTL(sctp_asconf_auth_nochk), SCTPCTL_ASCONF_AUTH_NOCHK_MIN, SCTPCTL_ASCONF_AUTH_NOCHK_MAX); RANGECHK(SCTP_BASE_SYSCTL(sctp_auth_disable), SCTPCTL_AUTH_DISABLE_MIN, SCTPCTL_AUTH_DISABLE_MAX); @@ -1175,16 +1181,20 @@ SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUT SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, path_pf_threshold, CTLTYPE_UINT|CTLFLAG_RW, &SCTP_BASE_SYSCTL(sctp_path_pf_threshold), 0, sysctl_sctp_check, "IU", SCTPCTL_PATH_PF_THRESHOLD_DESC); SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, add_more_on_output, CTLTYPE_UINT|CTLFLAG_RW, &SCTP_BASE_SYSCTL(sctp_add_more_threshold), 0, sysctl_sctp_check, "IU", SCTPCTL_ADD_MORE_ON_OUTPUT_DESC); +SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, incoming_streams, CTLTYPE_UINT|CTLFLAG_RW, + &SCTP_BASE_SYSCTL(sctp_nr_incoming_streams_default), 0, sysctl_sctp_check, "IU", + SCTPCTL_INCOMING_STREAMS_DESC); + SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, outgoing_streams, CTLTYPE_UINT|CTLFLAG_RW, &SCTP_BASE_SYSCTL(sctp_nr_outgoing_streams_default), 0, sysctl_sctp_check, "IU", SCTPCTL_OUTGOING_STREAMS_DESC); SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, cmt_on_off, CTLTYPE_UINT|CTLFLAG_RW, &SCTP_BASE_SYSCTL(sctp_cmt_on_off), 0, sysctl_sctp_check, "IU", SCTPCTL_CMT_ON_OFF_DESC); @@ -1510,16 +1520,20 @@ void sysctl_setup_sctp(void) sysctl_add_oid(&sysctl_oid_top, "path_pf_threshold", CTLTYPE_INT|CTLFLAG_RW, &SCTP_BASE_SYSCTL(sctp_path_pf_threshold), 0, sysctl_sctp_check, SCTPCTL_PATH_PF_THRESHOLD_DESC); sysctl_add_oid(&sysctl_oid_top, "add_more_on_output", CTLTYPE_INT|CTLFLAG_RW, &SCTP_BASE_SYSCTL(sctp_add_more_threshold), 0, sysctl_sctp_check, SCTPCTL_ADD_MORE_ON_OUTPUT_DESC); + sysctl_add_oid(&sysctl_oid_top, "incoming_streams", CTLTYPE_INT|CTLFLAG_RW, + &SCTP_BASE_SYSCTL(sctp_nr_incoming_streams_default), 0, sysctl_sctp_check, + SCTPCTL_INCOMING_STREAMS_DESC); + sysctl_add_oid(&sysctl_oid_top, "outgoing_streams", CTLTYPE_INT|CTLFLAG_RW, &SCTP_BASE_SYSCTL(sctp_nr_outgoing_streams_default), 0, sysctl_sctp_check, SCTPCTL_OUTGOING_STREAMS_DESC); sysctl_add_oid(&sysctl_oid_top, "cmt_on_off", CTLTYPE_INT|CTLFLAG_RW, &SCTP_BASE_SYSCTL(sctp_cmt_on_off), 0, sysctl_sctp_check, SCTPCTL_CMT_ON_OFF_DESC);
--- a/netwerk/sctp/src/netinet/sctp_sysctl.h +++ b/netwerk/sctp/src/netinet/sctp_sysctl.h @@ -27,17 +27,17 @@ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_sysctl.h 237565 2012-06-25 17:15:09Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp_sysctl.h 252779 2013-07-05 10:08:49Z tuexen $"); #endif #ifndef _NETINET_SCTP_SYSCTL_H_ #define _NETINET_SCTP_SYSCTL_H_ #include <netinet/sctp_os.h> #include <netinet/sctp_constants.h> @@ -74,16 +74,17 @@ struct sctp_sysctl { uint32_t sctp_rto_initial_default; uint32_t sctp_init_rto_max_default; uint32_t sctp_valid_cookie_life_default; uint32_t sctp_init_rtx_max_default; uint32_t sctp_assoc_rtx_max_default; uint32_t sctp_path_rtx_max_default; uint32_t sctp_path_pf_threshold; uint32_t sctp_add_more_threshold; + uint32_t sctp_nr_incoming_streams_default; 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; @@ -334,16 +335,22 @@ struct sctp_sysctl { #define SCTPCTL_PATH_PF_THRESHOLD_DEFAULT SCTPCTL_PATH_PF_THRESHOLD_MAX /* add_more_on_output: When space-wise is it worthwhile to try to add more to a socket send buffer */ #define SCTPCTL_ADD_MORE_ON_OUTPUT_DESC "When space-wise is it worthwhile to try to add more to a socket send buffer" #define SCTPCTL_ADD_MORE_ON_OUTPUT_MIN 0 #define SCTPCTL_ADD_MORE_ON_OUTPUT_MAX 0xFFFFFFFF #define SCTPCTL_ADD_MORE_ON_OUTPUT_DEFAULT SCTP_DEFAULT_ADD_MORE +/* incoming_streams: Default number of incoming streams */ +#define SCTPCTL_INCOMING_STREAMS_DESC "Default number of incoming streams" +#define SCTPCTL_INCOMING_STREAMS_MIN 1 +#define SCTPCTL_INCOMING_STREAMS_MAX 65535 +#define SCTPCTL_INCOMING_STREAMS_DEFAULT SCTP_ISTREAM_INITIAL + /* outgoing_streams: Default number of outgoing streams */ #define SCTPCTL_OUTGOING_STREAMS_DESC "Default number of outgoing streams" #define SCTPCTL_OUTGOING_STREAMS_MIN 1 #define SCTPCTL_OUTGOING_STREAMS_MAX 65535 #define SCTPCTL_OUTGOING_STREAMS_DEFAULT SCTP_OSTREAM_INITIAL /* cmt_on_off: CMT on/off flag */ #define SCTPCTL_CMT_ON_OFF_DESC "CMT settings"
--- a/netwerk/sctp/src/netinet/sctp_timer.c +++ b/netwerk/sctp/src/netinet/sctp_timer.c @@ -27,17 +27,17 @@ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_timer.c 246588 2013-02-09 08:27:08Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp_timer.c 257359 2013-10-29 20:04:50Z tuexen $"); #endif #define _IP_VHL #include <netinet/sctp_os.h> #include <netinet/sctp_pcb.h> #ifdef INET6 #if defined(__Userspace_os_FreeBSD) #include <netinet6/sctp6_var.h> @@ -437,17 +437,17 @@ sctp_recover_sent_list(struct sctp_tcb * SCTP_PRINTF("Found chk:%p tsn:%x <= last_acked_seq:%x\n", (void *)chk, chk->rec.data.TSN_seq, asoc->last_acked_seq); if (chk->sent != SCTP_DATAGRAM_NR_ACKED) { if (asoc->strmout[chk->rec.data.stream_number].chunks_on_queues > 0) { asoc->strmout[chk->rec.data.stream_number].chunks_on_queues--; } } TAILQ_REMOVE(&asoc->sent_queue, chk, sctp_next); - if (chk->pr_sctp_on) { + if (PR_SCTP_ENABLED(chk->flags)) { if (asoc->pr_sctp_cnt != 0) asoc->pr_sctp_cnt--; } if (chk->data) { /*sa_ignore NO_NULL_CHK*/ sctp_free_bufspace(stcb, asoc, chk, 1); sctp_m_freem(chk->data); chk->data = NULL; @@ -546,17 +546,17 @@ sctp_mark_all_for_resend(struct sctp_tcb num_mk = cnt_mk = 0; tsnfirst = tsnlast = 0; #ifndef INVARIANTS start_again: #endif TAILQ_FOREACH_SAFE(chk, &stcb->asoc.sent_queue, sctp_next, nchk) { if (SCTP_TSN_GE(stcb->asoc.last_acked_seq, chk->rec.data.TSN_seq)) { /* Strange case our list got out of order? */ - SCTP_PRINTF("Our list is out of order? last_acked:%x chk:%x", + SCTP_PRINTF("Our list is out of order? last_acked:%x chk:%x\n", (unsigned int)stcb->asoc.last_acked_seq, (unsigned int)chk->rec.data.TSN_seq); recovery_cnt++; #ifdef INVARIANTS panic("last acked >= chk on sent-Q"); #else SCTP_PRINTF("Recover attempts a restart cnt:%d\n", recovery_cnt); sctp_recover_sent_list(stcb); if (recovery_cnt < 10) {
--- a/netwerk/sctp/src/netinet/sctp_timer.h +++ b/netwerk/sctp/src/netinet/sctp_timer.h @@ -91,14 +91,17 @@ void sctp_autoclose_timer(struct sctp_inpcb *, struct sctp_tcb *, struct sctp_nets *net); void sctp_audit_retranmission_queue(struct sctp_association *); void sctp_iterator_timer(struct sctp_iterator *it); #if defined(__APPLE__) -void sctp_slowtimo(); - +#if defined(APPLE_LEOPARD) || defined(APPLE_SNOWLEOPARD) || defined(APPLE_LION) || defined(APPLE_MOUNTAINLION) +void sctp_slowtimo(void); +#else +void sctp_gc(struct inpcbinfo *); +#endif #endif #endif #endif
--- a/netwerk/sctp/src/netinet/sctp_uio.h +++ b/netwerk/sctp/src/netinet/sctp_uio.h @@ -27,17 +27,17 @@ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_uio.h 242327 2012-10-29 20:47:32Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp_uio.h 255160 2013-09-02 22:48:41Z tuexen $"); #endif #ifndef _NETINET_SCTP_UIO_H_ #define _NETINET_SCTP_UIO_H_ #if (defined(__APPLE__) && defined(KERNEL)) #ifndef _KERNEL #define _KERNEL @@ -686,20 +686,16 @@ struct sctp_hmacalgo { uint32_t shmac_number_of_idents; uint16_t shmac_idents[]; }; /* AUTH hmac_id */ #define SCTP_AUTH_HMAC_ID_RSVD 0x0000 #define SCTP_AUTH_HMAC_ID_SHA1 0x0001 /* default, mandatory */ #define SCTP_AUTH_HMAC_ID_SHA256 0x0003 -#define SCTP_AUTH_HMAC_ID_SHA224 0x0004 -#define SCTP_AUTH_HMAC_ID_SHA384 0x0005 -#define SCTP_AUTH_HMAC_ID_SHA512 0x0006 - /* SCTP_AUTH_ACTIVE_KEY / SCTP_AUTH_DELETE_KEY */ struct sctp_authkeyid { sctp_assoc_t scact_assoc_id; uint16_t scact_keynumber; }; /* SCTP_PEER_AUTH_CHUNKS / SCTP_LOCAL_AUTH_CHUNKS */ @@ -1169,28 +1165,36 @@ union sctp_sockstore { #endif #endif /***********************************/ struct xsctp_inpcb { uint32_t last; uint32_t flags; +#if defined(__FreeBSD__) && __FreeBSD_version < 1000048 uint32_t features; +#else + uint64_t features; +#endif uint32_t total_sends; uint32_t total_recvs; uint32_t total_nospaces; uint32_t fragmentation_point; uint16_t local_port; uint16_t qlen; uint16_t maxqlen; #if defined(__Windows__) uint16_t padding; #endif +#if defined(__FreeBSD__) && __FreeBSD_version < 1000048 uint32_t extra_padding[32]; /* future */ +#else + uint32_t extra_padding[31]; /* future */ +#endif }; struct xsctp_tcb { union sctp_sockstore primary_addr; /* sctpAssocEntry 5/6 */ uint32_t last; uint32_t heartbeat_interval; /* sctpAssocEntry 7 */ uint32_t state; /* sctpAssocEntry 8 */ uint32_t in_streams; /* sctpAssocEntry 9 */ @@ -1323,17 +1327,17 @@ sctp_sorecvmsg(struct socket *so, #endif /* * API system calls */ #if !(defined(_KERNEL)) && !(defined(__Userspace__)) __BEGIN_DECLS -#if defined(__FreeBSD__) && __FreeBSD_version < 1000000 +#if defined(__FreeBSD__) && __FreeBSD_version < 902000 int sctp_peeloff __P((int, sctp_assoc_t)); int sctp_bindx __P((int, struct sockaddr *, int, int)); int sctp_connectx __P((int, const struct sockaddr *, int, sctp_assoc_t *)); int sctp_getaddrlen __P((sa_family_t)); int sctp_getpaddrs __P((int, sctp_assoc_t, struct sockaddr **)); void sctp_freepaddrs __P((struct sockaddr *)); int sctp_getladdrs __P((int, sctp_assoc_t, struct sockaddr **)); void sctp_freeladdrs __P((struct sockaddr *));
--- a/netwerk/sctp/src/netinet/sctp_userspace.c +++ b/netwerk/sctp/src/netinet/sctp_userspace.c @@ -92,27 +92,31 @@ getwintimeofday(struct timeval *tv) ftime(&tb); tv->tv_sec = tb.time; tv->tv_usec = tb.millitm * 1000; } int Win_getifaddrs(struct ifaddrs** interfaces) { +#if defined(INET) || defined(INET6) DWORD Err, AdapterAddrsSize; int count; PIP_ADAPTER_ADDRESSES pAdapterAddrs, pAdapt; struct ifaddrs *ifa; +#endif #if defined(INET) struct sockaddr_in *addr; #endif #if defined(INET6) struct sockaddr_in6 *addr6; #endif +#if defined(INET) || defined(INET6) count = 0; +#endif #if defined(INET) AdapterAddrsSize = 0; if ((Err = GetAdaptersAddresses(AF_INET, 0, NULL, NULL, &AdapterAddrsSize)) != 0) { if ((Err != ERROR_BUFFER_OVERFLOW) && (Err != ERROR_INSUFFICIENT_BUFFER)) { SCTPDBG(SCTP_DEBUG_USR, "GetAdaptersV4Addresses() sizing failed with error code %d and AdapterAddrsSize = %d\n", Err, AdapterAddrsSize); return (-1); } }
--- a/netwerk/sctp/src/netinet/sctp_usrreq.c +++ b/netwerk/sctp/src/netinet/sctp_usrreq.c @@ -27,17 +27,17 @@ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_usrreq.c 246687 2013-02-11 21:02:49Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp_usrreq.c 259943 2013-12-27 13:07:00Z tuexen $"); #endif #include <netinet/sctp_os.h> #ifdef __FreeBSD__ #include <sys/proc.h> #endif #include <netinet/sctp_pcb.h> #include <netinet/sctp_header.h> @@ -71,34 +71,42 @@ extern struct sctp_cc_functions sctp_cc_functions[]; extern struct sctp_ss_functions sctp_ss_functions[]; void #if defined(__Userspace__) sctp_init(uint16_t port, int (*conn_output)(void *addr, void *buffer, size_t length, uint8_t tos, uint8_t set_df), void (*debug_printf)(const char *format, ...)) +#elif defined(__APPLE__) && (!defined(APPLE_LEOPARD) && !defined(APPLE_SNOWLEOPARD) &&!defined(APPLE_LION) && !defined(APPLE_MOUNTAINLION)) +sctp_init(struct protosw *pp SCTP_UNUSED, struct domain *dp SCTP_UNUSED) #else sctp_init(void) #endif { #if !defined(__Panda__) && !defined(__Userspace__) u_long sb_max_adj; #endif +#if defined(__Userspace__) #if defined(__Userspace_os_Windows) +#if defined(INET) || defined(INET6) WSADATA wsaData; - int Ret; - - if ((Ret = WSAStartup(MAKEWORD(2,2), &wsaData))!=0) { + + if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) { SCTP_PRINTF("WSAStartup failed\n"); exit (-1); } +#endif InitializeConditionVariable(&accept_cond); InitializeCriticalSection(&accept_mtx); +#else + pthread_cond_init(&accept_cond, NULL); + pthread_mutex_init(&accept_mtx, NULL); +#endif #endif /* Initialize and modify the sysctled variables */ sctp_init_sysctls(); #if defined(__Userspace__) #if defined(__Userspace_os_Windows) srand((unsigned int)time(NULL)); #else srandom(getpid()); /* so inp->sctp_ep.random_numbers are truly random... */ @@ -166,25 +174,25 @@ sctp_init(void) #if defined(SCTP_PACKET_LOGGING) SCTP_BASE_VAR(packet_log_writers) = 0; SCTP_BASE_VAR(packet_log_end) = 0; bzero(&SCTP_BASE_VAR(packet_log_buffer), SCTP_PACKET_LOG_SIZE); #endif #if defined(__APPLE__) SCTP_BASE_VAR(sctp_main_timer_ticks) = 0; sctp_start_main_timer(); - sctp_address_monitor_start(); - sctp_over_udp_start(); + timeout(sctp_delayed_startup, NULL, 1); #endif } void sctp_finish(void) { #if defined(__APPLE__) + untimeout(sctp_delayed_startup, NULL); sctp_over_udp_stop(); sctp_address_monitor_stop(); sctp_stop_main_timer(); #endif #if defined(__Userspace__) #if defined(INET) || defined(INET6) recv_thread_destroy(); #endif @@ -194,54 +202,71 @@ sctp_finish(void) pthread_join(SCTP_BASE_VAR(recvthreadroute), NULL); } #endif #endif #ifdef INET if (SCTP_BASE_VAR(userspace_rawsctp) != -1) { #if defined(__Userspace_os_Windows) WaitForSingleObject(SCTP_BASE_VAR(recvthreadraw), INFINITE); + CloseHandle(SCTP_BASE_VAR(recvthreadraw)); #else pthread_join(SCTP_BASE_VAR(recvthreadraw), NULL); #endif } if (SCTP_BASE_VAR(userspace_udpsctp) != -1) { #if defined(__Userspace_os_Windows) WaitForSingleObject(SCTP_BASE_VAR(recvthreadudp), INFINITE); + CloseHandle(SCTP_BASE_VAR(recvthreadudp)); #else pthread_join(SCTP_BASE_VAR(recvthreadudp), NULL); #endif } #endif #ifdef INET6 if (SCTP_BASE_VAR(userspace_rawsctp6) != -1) { #if defined(__Userspace_os_Windows) WaitForSingleObject(SCTP_BASE_VAR(recvthreadraw6), INFINITE); + CloseHandle(SCTP_BASE_VAR(recvthreadraw6)); #else pthread_join(SCTP_BASE_VAR(recvthreadraw6), NULL); #endif } if (SCTP_BASE_VAR(userspace_udpsctp6) != -1) { #if defined(__Userspace_os_Windows) WaitForSingleObject(SCTP_BASE_VAR(recvthreadudp6), INFINITE); + CloseHandle(SCTP_BASE_VAR(recvthreadudp6)); #else pthread_join(SCTP_BASE_VAR(recvthreadudp6), NULL); #endif } #endif SCTP_BASE_VAR(timer_thread_should_exit) = 1; #if defined(__Userspace_os_Windows) WaitForSingleObject(SCTP_BASE_VAR(timer_thread), INFINITE); + CloseHandle(SCTP_BASE_VAR(timer_thread)); #else pthread_join(SCTP_BASE_VAR(timer_thread), NULL); #endif #endif sctp_pcb_finish(); +#if defined(__Userspace__) +#if defined(__Userspace_os_Windows) + DeleteConditionVariable(&accept_cond); + DeleteCriticalSection(&accept_mtx); +#else + pthread_cond_destroy(&accept_cond); + pthread_mutex_destroy(&accept_mtx); +#endif +#endif #if defined(__Windows__) sctp_finish_sysctls(); +#if defined(INET) || defined(INET6) + WSACleanup(); +#endif #endif } void sctp_pathmtu_adjustment(struct sctp_tcb *stcb, uint16_t nxtsz) { @@ -407,18 +432,20 @@ sctp_notify(struct sctp_inpcb *inp, } if ((icmph->icmp_code == ICMP_UNREACH_NET) || (icmph->icmp_code == ICMP_UNREACH_HOST) || (icmph->icmp_code == ICMP_UNREACH_NET_UNKNOWN) || (icmph->icmp_code == ICMP_UNREACH_HOST_UNKNOWN) || (icmph->icmp_code == ICMP_UNREACH_ISOLATED) || (icmph->icmp_code == ICMP_UNREACH_NET_PROHIB) || (icmph->icmp_code == ICMP_UNREACH_HOST_PROHIB) || -#ifdef __Panda__ +#if defined(__Panda__) (icmph->icmp_code == ICMP_UNREACH_ADMIN)) { +#elif defined(__Userspace_os_NetBSD) + (icmph->icmp_code == ICMP_UNREACH_ADMIN_PROHIBIT)) { #else (icmph->icmp_code == ICMP_UNREACH_FILTER_PROHIB)) { #endif /* * Hmm reachablity problems we must examine closely. If its * not reachable, we may have lost a network. Or if there is * NO protocol at the other end named SCTP. well we consider @@ -1157,21 +1184,21 @@ sctp_disconnect(struct socket *so) if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) { /* We are about to be freed, out of here */ SCTP_TCB_UNLOCK(stcb); SCTP_INP_RUNLOCK(inp); return (0); } #if defined(__Userspace__) if (((so->so_options & SCTP_SO_LINGER) && - (so->so_linger == 0)) || + (so->so_linger == 0)) || (so->so_rcv.sb_cc > 0)) { #else if (((so->so_options & SO_LINGER) && - (so->so_linger == 0)) || + (so->so_linger == 0)) || (so->so_rcv.sb_cc > 0)) { #endif if (SCTP_GET_STATE(asoc) != SCTP_STATE_COOKIE_WAIT) { /* Left with Data unread */ struct mbuf *err; err = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr), 0, M_NOWAIT, 1, MT_DATA); @@ -1553,68 +1580,93 @@ static size_t sctp_fill_up_addresses_vrf(struct sctp_inpcb *inp, struct sctp_tcb *stcb, size_t limit, struct sockaddr_storage *sas, uint32_t vrf_id) { struct sctp_ifn *sctp_ifn; struct sctp_ifa *sctp_ifa; - int loopback_scope, ipv4_local_scope, local_scope, site_scope; size_t actual; - int ipv4_addr_legal, ipv6_addr_legal; + int loopback_scope; +#if defined(INET) + int ipv4_local_scope, ipv4_addr_legal; +#endif +#if defined(INET6) + int local_scope, site_scope, ipv6_addr_legal; +#endif #if defined(__Userspace__) int conn_addr_legal; #endif struct sctp_vrf *vrf; actual = 0; if (limit <= 0) return (actual); if (stcb) { /* Turn on all the appropriate scope */ loopback_scope = stcb->asoc.scope.loopback_scope; +#if defined(INET) ipv4_local_scope = stcb->asoc.scope.ipv4_local_scope; + ipv4_addr_legal = stcb->asoc.scope.ipv4_addr_legal; +#endif +#if defined(INET6) local_scope = stcb->asoc.scope.local_scope; site_scope = stcb->asoc.scope.site_scope; - ipv4_addr_legal = stcb->asoc.scope.ipv4_addr_legal; ipv6_addr_legal = stcb->asoc.scope.ipv6_addr_legal; +#endif #if defined(__Userspace__) conn_addr_legal = stcb->asoc.scope.conn_addr_legal; #endif } else { /* Use generic values for endpoints. */ loopback_scope = 1; +#if defined(INET) ipv4_local_scope = 1; +#endif +#if defined(INET6) local_scope = 1; site_scope = 1; +#endif if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) { +#if defined(INET6) ipv6_addr_legal = 1; +#endif +#if defined(INET) if (SCTP_IPV6_V6ONLY(inp)) { ipv4_addr_legal = 0; } else { ipv4_addr_legal = 1; } +#endif #if defined(__Userspace__) conn_addr_legal = 0; #endif } else { +#if defined(INET6) ipv6_addr_legal = 0; +#endif #if defined(__Userspace__) if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_CONN) { conn_addr_legal = 1; +#if defined(INET) ipv4_addr_legal = 0; +#endif } else { conn_addr_legal = 0; +#if defined(INET) ipv4_addr_legal = 1; +#endif } #else +#if defined(INET) ipv4_addr_legal = 1; #endif +#endif } } vrf = sctp_find_vrf(vrf_id); if (vrf == NULL) { return (0); } if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) { LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) { @@ -3386,17 +3438,17 @@ sctp_getopt(struct socket *so, int optna { struct sctp_setprim *ssp; SCTP_CHECK_AND_CAST(ssp, optval, struct sctp_setprim, *optsize); SCTP_FIND_STCB(inp, stcb, ssp->ssp_assoc_id); if (stcb) { /* simply copy out the sockaddr_storage... */ - int len; + size_t len; len = *optsize; #ifdef HAVE_SA_LEN if (len > stcb->asoc.primary_destination->ro._l_addr.sa.sa_len) len = stcb->asoc.primary_destination->ro._l_addr.sa.sa_len; #else if (stcb->asoc.primary_destination->ro._l_addr.sa.sa_family == AF_INET && len > sizeof(struct sockaddr_in)) @@ -3949,17 +4001,17 @@ sctp_getopt(struct socket *so, int optna encaps->sue_port = inp->sctp_ep.port; SCTP_INP_RUNLOCK(inp); } else { SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); error = EINVAL; } } if (error == 0) { - *optsize = sizeof(struct sctp_paddrparams); + *optsize = sizeof(struct sctp_udpencaps); } break; } case SCTP_ENABLE_STREAM_RESET: { struct sctp_assoc_value *av; SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize); @@ -4721,17 +4773,16 @@ sctp_setopt(struct socket *so, int optna break; } case SCTP_HMAC_IDENT: { struct sctp_hmacalgo *shmac; sctp_hmaclist_t *hmaclist; uint16_t hmacid; uint32_t i; - size_t found; SCTP_CHECK_AND_CAST(shmac, optval, struct sctp_hmacalgo, optsize); if (optsize < sizeof(struct sctp_hmacalgo) + shmac->shmac_number_of_idents * sizeof(uint16_t)) { SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); error = EINVAL; break; } @@ -4746,24 +4797,24 @@ sctp_setopt(struct socket *so, int optna if (sctp_auth_add_hmacid(hmaclist, hmacid)) { /* invalid HMACs were found */; SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); error = EINVAL; sctp_free_hmaclist(hmaclist); goto sctp_set_hmac_done; } } - found = 0; for (i = 0; i < hmaclist->num_algo; i++) { if (hmaclist->hmac[i] == SCTP_AUTH_HMAC_ID_SHA1) { /* already in list */ - found = 1; - } - } - if (!found) { + break; + } + } + if (i == hmaclist->num_algo) { + /* not found in list */ sctp_free_hmaclist(hmaclist); SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); error = EINVAL; break; } /* set it on the endpoint */ SCTP_INP_WLOCK(inp); if (inp->sctp_ep.local_hmacs) @@ -5587,21 +5638,19 @@ sctp_setopt(struct socket *so, int optna sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net); } if ((paddrp->spp_flags & SPP_PMTUD_DISABLE) && (paddrp->spp_pathmtu >= SCTP_SMALLEST_PMTU)) { if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) { sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net, SCTP_FROM_SCTP_USRREQ+SCTP_LOC_10); } net->dest_state |= SCTP_ADDR_NO_PMTUD; - if (paddrp->spp_pathmtu > SCTP_DEFAULT_MINSEGMENT) { - net->mtu = paddrp->spp_pathmtu + ovh; - if (net->mtu < stcb->asoc.smallest_mtu) { - sctp_pathmtu_adjustment(stcb, net->mtu); - } + net->mtu = paddrp->spp_pathmtu + ovh; + if (net->mtu < stcb->asoc.smallest_mtu) { + sctp_pathmtu_adjustment(stcb, net->mtu); } } if (paddrp->spp_flags & SPP_PMTUD_ENABLE) { if (!SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) { sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net); } net->dest_state &= ~SCTP_ADDR_NO_PMTUD; } @@ -5712,21 +5761,19 @@ sctp_setopt(struct socket *so, int optna } if ((paddrp->spp_flags & SPP_PMTUD_DISABLE) && (paddrp->spp_pathmtu >= SCTP_SMALLEST_PMTU)) { TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) { sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net, SCTP_FROM_SCTP_USRREQ+SCTP_LOC_10); } net->dest_state |= SCTP_ADDR_NO_PMTUD; - if (paddrp->spp_pathmtu > SCTP_DEFAULT_MINSEGMENT) { - net->mtu = paddrp->spp_pathmtu + ovh; - if (net->mtu < stcb->asoc.smallest_mtu) { - sctp_pathmtu_adjustment(stcb, net->mtu); - } + net->mtu = paddrp->spp_pathmtu + ovh; + if (net->mtu < stcb->asoc.smallest_mtu) { + sctp_pathmtu_adjustment(stcb, net->mtu); } } sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_DO_NOT_PMTUD); } if (paddrp->spp_flags & SPP_PMTUD_ENABLE) { TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { if (!SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) { sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net); @@ -7749,17 +7796,17 @@ sctp_peeraddr(struct socket *so, struct #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__) (*addr) = (struct sockaddr *)sin; #endif return (0); } #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__) struct pr_usrreqs sctp_usrreqs = { -#if __FreeBSD_version >= 600000 +#if defined(__FreeBSD__) .pru_abort = sctp_abort, .pru_accept = sctp_accept, .pru_attach = sctp_attach, .pru_bind = sctp_bind, .pru_connect = sctp_connect, .pru_control = in_control, #if __FreeBSD_version >= 690000 .pru_close = sctp_close, @@ -7773,55 +7820,61 @@ struct pr_usrreqs sctp_usrreqs = { .pru_disconnect = sctp_disconnect, .pru_listen = sctp_listen, .pru_peeraddr = sctp_peeraddr, .pru_send = sctp_sendm, .pru_shutdown = sctp_shutdown, .pru_sockaddr = sctp_ingetaddr, .pru_sosend = sctp_sosend, .pru_soreceive = sctp_soreceive -#else +#elif defined(__APPLE__) + .pru_abort = sctp_abort, + .pru_accept = sctp_accept, + .pru_attach = sctp_attach, + .pru_bind = sctp_bind, + .pru_connect = sctp_connect, + .pru_connect2 = pru_connect2_notsupp, + .pru_control = in_control, + .pru_detach = sctp_detach, + .pru_disconnect = sctp_disconnect, + .pru_listen = sctp_listen, + .pru_peeraddr = sctp_peeraddr, + .pru_rcvd = NULL, + .pru_rcvoob = pru_rcvoob_notsupp, + .pru_send = sctp_sendm, + .pru_sense = pru_sense_null, + .pru_shutdown = sctp_shutdown, + .pru_sockaddr = sctp_ingetaddr, + .pru_sosend = sctp_sosend, + .pru_soreceive = sctp_soreceive, + .pru_sopoll = sopoll +#elif defined(__Windows__) sctp_abort, sctp_accept, sctp_attach, sctp_bind, sctp_connect, pru_connect2_notsupp, -#if defined(__Windows__) NULL, NULL, -#else - in_control, - sctp_detach, -#endif sctp_disconnect, sctp_listen, sctp_peeraddr, NULL, pru_rcvoob_notsupp, -#if defined(__Windows__) NULL, -#else - sctp_sendm, -#endif pru_sense_null, sctp_shutdown, -#if defined(__Windows__) sctp_flush, -#endif sctp_ingetaddr, sctp_sosend, sctp_soreceive, -#if defined(__Windows__) sopoll_generic, NULL, sctp_close -#else - sopoll -#endif #endif }; #elif !defined(__Panda__) && !defined(__Userspace__) int sctp_usrreq(so, req, m, nam, control) struct socket *so; int req; struct mbuf *m, *nam, *control;
--- a/netwerk/sctp/src/netinet/sctp_var.h +++ b/netwerk/sctp/src/netinet/sctp_var.h @@ -394,17 +394,17 @@ struct sctphdr; #if (defined(__FreeBSD__) && __FreeBSD_version > 690000) || defined(__Windows__) || defined(__Userspace__) void sctp_close(struct socket *so); #else int sctp_detach(struct socket *so); #endif int sctp_disconnect(struct socket *so); #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__) -#if defined(__FreeBSD__) && __FreeBSD_version < 1000000 +#if defined(__FreeBSD__) && __FreeBSD_version < 902000 void sctp_ctlinput __P((int, struct sockaddr *, void *)); int sctp_ctloutput __P((struct socket *, struct sockopt *)); #ifdef INET void sctp_input_with_port __P((struct mbuf *, int, uint16_t)); void sctp_input __P((struct mbuf *, int)); #endif void sctp_pathmtu_adjustment __P((struct sctp_tcb *, uint16_t)); #else @@ -422,37 +422,37 @@ void sctp_input(pakhandle_type i_pak); #elif defined(__Userspace__) void sctp_pathmtu_adjustment(struct sctp_tcb *, uint16_t); #else void sctp_input(struct mbuf *,...); #endif void *sctp_ctlinput(int, struct sockaddr *, void *); int sctp_ctloutput(int, struct socket *, int, int, struct mbuf **); #endif -#if defined(__FreeBSD__) && __FreeBSD_version < 1000000 +#if defined(__FreeBSD__) && __FreeBSD_version < 902000 void sctp_drain __P((void)); #else void sctp_drain(void); #endif #if defined(__Userspace__) void sctp_init(uint16_t, int (*)(void *addr, void *buffer, size_t length, uint8_t tos, uint8_t set_df), void (*)(const char *, ...)); -#else -#if defined(__FreeBSD__) && __FreeBSD_version < 1000000 +#elif defined(__FreeBSD__) && __FreeBSD_version < 902000 void sctp_init __P((void)); +#elif defined(__APPLE__) && (!defined(APPLE_LEOPARD) && !defined(APPLE_SNOWLEOPARD) &&!defined(APPLE_LION) && !defined(APPLE_MOUNTAINLION)) +void sctp_init(struct protosw *pp, struct domain *dp); #else void sctp_init(void); #endif -#endif void sctp_finish(void); #if defined(__FreeBSD__) || defined(__Windows__) || defined(__Userspace__) int sctp_flush(struct socket *, int); #endif -#if defined(__FreeBSD__) && __FreeBSD_version < 1000000 +#if defined(__FreeBSD__) && __FreeBSD_version < 902000 int sctp_shutdown __P((struct socket *)); void sctp_notify __P((struct sctp_inpcb *, struct ip *ip, struct sctphdr *, struct sockaddr *, struct sctp_tcb *, struct sctp_nets *)); #else int sctp_shutdown(struct socket *); void sctp_notify(struct sctp_inpcb *, struct ip *ip, struct sctphdr *, struct sockaddr *, struct sctp_tcb *,
--- a/netwerk/sctp/src/netinet/sctputil.c +++ b/netwerk/sctp/src/netinet/sctputil.c @@ -27,17 +27,17 @@ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctputil.c 247412 2013-02-27 19:51:47Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctputil.c 259943 2013-12-27 13:07:00Z tuexen $"); #endif #include <netinet/sctp_os.h> #include <netinet/sctp_pcb.h> #include <netinet/sctputil.h> #include <netinet/sctp_var.h> #include <netinet/sctp_sysctl.h> #ifdef INET6 @@ -2716,17 +2716,17 @@ sctp_notify_assoc_change(uint16_t state, unsigned int i; #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) struct socket *so; #endif if (sctp_stcb_is_feature_on(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVASSOCEVNT)) { notif_len = sizeof(struct sctp_assoc_change); if (abort != NULL) { - abort_len = htons(abort->ch.chunk_length); + abort_len = ntohs(abort->ch.chunk_length); } else { abort_len = 0; } if ((state == SCTP_COMM_UP) || (state == SCTP_RESTART)) { notif_len += SCTP_ASSOC_SUPPORTS_MAX; } else if ((state == SCTP_COMM_LOST) || (state == SCTP_CANT_STR_ASSOC)) { notif_len += abort_len; } @@ -2751,17 +2751,17 @@ sctp_notify_assoc_change(uint16_t state, sac->sac_inbound_streams = stcb->asoc.streamincnt; sac->sac_assoc_id = sctp_get_associd(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) { sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_PR; } - if (stcb->asoc.peer_supports_auth) { + if (stcb->asoc.peer_supports_auth) { sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_AUTH; } if (stcb->asoc.peer_supports_asconf) { sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_ASCONF; } sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_MULTIBUF; if (stcb->asoc.peer_supports_strreset) { sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_RE_CONFIG; @@ -2769,27 +2769,27 @@ sctp_notify_assoc_change(uint16_t state, sac->sac_length += i; } else if ((state == SCTP_COMM_LOST) || (state == SCTP_CANT_STR_ASSOC)) { memcpy(sac->sac_info, abort, abort_len); sac->sac_length += abort_len; } } SCTP_BUF_LEN(m_notify) = sac->sac_length; control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination, - 0, 0, stcb->asoc.context, 0, 0, 0, - m_notify); + 0, 0, stcb->asoc.context, 0, 0, 0, + m_notify); if (control != NULL) { control->length = SCTP_BUF_LEN(m_notify); /* not that we need this */ control->tail_mbuf = m_notify; control->spec_flags = M_NOTIFICATION; sctp_add_to_readq(stcb->sctp_ep, stcb, - control, - &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, - so_locked); + control, + &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, + so_locked); } else { sctp_m_freem(m_notify); } } /* * For 1-to-1 style sockets, we send up and error when an ABORT * comes in. */ @@ -2802,18 +2802,24 @@ set_error: if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_WAIT) { SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ECONNREFUSED); stcb->sctp_socket->so_error = ECONNREFUSED; } else { SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ECONNRESET); stcb->sctp_socket->so_error = ECONNRESET; } } else { - SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ECONNABORTED); - stcb->sctp_socket->so_error = ECONNABORTED; + if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_WAIT) || + (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_ECHOED)) { + SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ETIMEDOUT); + stcb->sctp_socket->so_error = ETIMEDOUT; + } else { + SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ECONNABORTED); + stcb->sctp_socket->so_error = ECONNABORTED; + } } } /* Wake ANY sleepers */ #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) so = SCTP_INP_SO(stcb->sctp_ep); if (!so_locked) { atomic_add_int(&stcb->asoc.refcnt, 1); SCTP_TCB_UNLOCK(stcb); @@ -2924,20 +2930,20 @@ sctp_notify_peer_addr_change(struct sctp sctp_m_freem(m_notify); return; } control->length = SCTP_BUF_LEN(m_notify); control->spec_flags = M_NOTIFICATION; /* not that we need this */ control->tail_mbuf = m_notify; sctp_add_to_readq(stcb->sctp_ep, stcb, - control, - &stcb->sctp_socket->so_rcv, 1, - SCTP_READ_LOCK_NOT_HELD, - SCTP_SO_NOT_LOCKED); + control, + &stcb->sctp_socket->so_rcv, 1, + SCTP_READ_LOCK_NOT_HELD, + SCTP_SO_NOT_LOCKED); } static void sctp_notify_send_failed(struct sctp_tcb *stcb, uint8_t sent, uint32_t error, struct sctp_tmit_chunk *chk, int so_locked #if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING) SCTP_UNUSED @@ -3606,17 +3612,17 @@ sctp_notify_remote_error(struct sctp_tcb struct sctp_queued_to_read *control; size_t notif_len, chunk_len; if ((stcb == NULL) || sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVPEERERR)) { return; } if (chunk != NULL) { - chunk_len = htons(chunk->ch.chunk_length); + chunk_len = ntohs(chunk->ch.chunk_length); } else { chunk_len = 0; } notif_len = sizeof(struct sctp_remote_error) + chunk_len; m_notify = sctp_get_mbuf_for_msg(notif_len, 0, M_NOWAIT, 1, MT_DATA); if (m_notify == NULL) { /* Retry with smaller value. */ notif_len = sizeof(struct sctp_remote_error); @@ -3679,18 +3685,18 @@ sctp_ulp_notify(uint32_t notification, s } #if defined(__APPLE__) if (so_locked) { sctp_lock_assert(SCTP_INP_SO(stcb->sctp_ep)); } else { sctp_unlock_assert(SCTP_INP_SO(stcb->sctp_ep)); } #endif - if (stcb && ((stcb->asoc.state & SCTP_STATE_COOKIE_WAIT) || - (stcb->asoc.state & SCTP_STATE_COOKIE_ECHOED))) { + if ((stcb->asoc.state & SCTP_STATE_COOKIE_WAIT) || + (stcb->asoc.state & SCTP_STATE_COOKIE_ECHOED)) { if ((notification == SCTP_NOTIFY_INTERFACE_DOWN) || (notification == SCTP_NOTIFY_INTERFACE_UP) || (notification == SCTP_NOTIFY_INTERFACE_CONFIRMED)) { /* Don't report these in front states */ return; } } switch (notification) { @@ -3699,17 +3705,17 @@ sctp_ulp_notify(uint32_t notification, s sctp_notify_assoc_change(SCTP_COMM_UP, stcb, error, NULL, 0, so_locked); stcb->asoc.assoc_up_sent = 1; } if (stcb->asoc.adaptation_needed && (stcb->asoc.adaptation_sent == 0)) { sctp_notify_adaptation_layer(stcb); } if (stcb->asoc.peer_supports_auth == 0) { sctp_ulp_notify(SCTP_NOTIFY_NO_PEER_AUTH, stcb, 0, - NULL, so_locked); + NULL, so_locked); } break; case SCTP_NOTIFY_ASSOC_DOWN: sctp_notify_assoc_change(SCTP_SHUTDOWN_COMP, stcb, error, NULL, 0, so_locked); #if defined(__Userspace__) if (stcb->sctp_ep->recv_callback) { if (stcb->sctp_socket) { union sctp_sockstore addr; @@ -3750,108 +3756,108 @@ sctp_ulp_notify(uint32_t notification, s net = (struct sctp_nets *)data; sctp_notify_peer_addr_change(stcb, SCTP_ADDR_CONFIRMED, (struct sockaddr *)&net->ro._l_addr, error); break; } case SCTP_NOTIFY_SPECIAL_SP_FAIL: sctp_notify_send_failed2(stcb, error, - (struct sctp_stream_queue_pending *)data, so_locked); + (struct sctp_stream_queue_pending *)data, so_locked); break; case SCTP_NOTIFY_SENT_DG_FAIL: sctp_notify_send_failed(stcb, 1, error, (struct sctp_tmit_chunk *)data, so_locked); break; case SCTP_NOTIFY_UNSENT_DG_FAIL: sctp_notify_send_failed(stcb, 0, error, - (struct sctp_tmit_chunk *)data, so_locked); + (struct sctp_tmit_chunk *)data, so_locked); break; case SCTP_NOTIFY_PARTIAL_DELVIERY_INDICATION: { uint32_t val; val = *((uint32_t *)data); sctp_notify_partial_delivery_indication(stcb, error, val, so_locked); break; } case SCTP_NOTIFY_ASSOC_LOC_ABORTED: - if ((stcb) && (((stcb->asoc.state & SCTP_STATE_MASK) == SCTP_STATE_COOKIE_WAIT) || - ((stcb->asoc.state & SCTP_STATE_MASK) == SCTP_STATE_COOKIE_ECHOED))) { + if (((stcb->asoc.state & SCTP_STATE_MASK) == SCTP_STATE_COOKIE_WAIT) || + ((stcb->asoc.state & SCTP_STATE_MASK) == SCTP_STATE_COOKIE_ECHOED)) { sctp_notify_assoc_change(SCTP_CANT_STR_ASSOC, stcb, error, data, 0, so_locked); } else { sctp_notify_assoc_change(SCTP_COMM_LOST, stcb, error, data, 0, so_locked); } break; case SCTP_NOTIFY_ASSOC_REM_ABORTED: - if ((stcb) && (((stcb->asoc.state & SCTP_STATE_MASK) == SCTP_STATE_COOKIE_WAIT) || - ((stcb->asoc.state & SCTP_STATE_MASK) == SCTP_STATE_COOKIE_ECHOED))) { + if (((stcb->asoc.state & SCTP_STATE_MASK) == SCTP_STATE_COOKIE_WAIT) || + ((stcb->asoc.state & SCTP_STATE_MASK) == SCTP_STATE_COOKIE_ECHOED)) { sctp_notify_assoc_change(SCTP_CANT_STR_ASSOC, stcb, error, data, 1, so_locked); } else { sctp_notify_assoc_change(SCTP_COMM_LOST, stcb, error, data, 1, so_locked); } 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) { sctp_ulp_notify(SCTP_NOTIFY_NO_PEER_AUTH, stcb, 0, - NULL, so_locked); + NULL, so_locked); } break; case SCTP_NOTIFY_STR_RESET_SEND: sctp_notify_stream_reset(stcb, error, ((uint16_t *) data), SCTP_STREAM_RESET_OUTGOING_SSN); break; case SCTP_NOTIFY_STR_RESET_RECV: sctp_notify_stream_reset(stcb, error, ((uint16_t *) data), SCTP_STREAM_RESET_INCOMING); break; case SCTP_NOTIFY_STR_RESET_FAILED_OUT: sctp_notify_stream_reset(stcb, error, ((uint16_t *) data), - (SCTP_STREAM_RESET_OUTGOING_SSN|SCTP_STREAM_RESET_FAILED)); + (SCTP_STREAM_RESET_OUTGOING_SSN|SCTP_STREAM_RESET_FAILED)); break; case SCTP_NOTIFY_STR_RESET_DENIED_OUT: sctp_notify_stream_reset(stcb, error, ((uint16_t *) data), (SCTP_STREAM_RESET_OUTGOING_SSN|SCTP_STREAM_RESET_DENIED)); break; case SCTP_NOTIFY_STR_RESET_FAILED_IN: sctp_notify_stream_reset(stcb, error, ((uint16_t *) data), - (SCTP_STREAM_RESET_INCOMING|SCTP_STREAM_RESET_FAILED)); + (SCTP_STREAM_RESET_INCOMING|SCTP_STREAM_RESET_FAILED)); break; case SCTP_NOTIFY_STR_RESET_DENIED_IN: sctp_notify_stream_reset(stcb, error, ((uint16_t *) data), (SCTP_STREAM_RESET_INCOMING|SCTP_STREAM_RESET_DENIED)); break; case SCTP_NOTIFY_ASCONF_ADD_IP: sctp_notify_peer_addr_change(stcb, SCTP_ADDR_ADDED, data, error); break; case SCTP_NOTIFY_ASCONF_DELETE_IP: sctp_notify_peer_addr_change(stcb, SCTP_ADDR_REMOVED, data, - error); + error); break; case SCTP_NOTIFY_ASCONF_SET_PRIMARY: sctp_notify_peer_addr_change(stcb, SCTP_ADDR_MADE_PRIM, data, - error); + error); break; case SCTP_NOTIFY_PEER_SHUTDOWN: sctp_notify_shutdown_event(stcb); break; case SCTP_NOTIFY_AUTH_NEW_KEY: sctp_notify_authentication(stcb, SCTP_AUTH_NEW_KEY, error, - (uint16_t)(uintptr_t)data, - so_locked); + (uint16_t)(uintptr_t)data, + so_locked); break; case SCTP_NOTIFY_AUTH_FREE_KEY: sctp_notify_authentication(stcb, SCTP_AUTH_FREE_KEY, error, - (uint16_t)(uintptr_t)data, - so_locked); + (uint16_t)(uintptr_t)data, + so_locked); break; case SCTP_NOTIFY_NO_PEER_AUTH: sctp_notify_authentication(stcb, SCTP_AUTH_NO_AUTH, error, - (uint16_t)(uintptr_t)data, - so_locked); + (uint16_t)(uintptr_t)data, + so_locked); break; case SCTP_NOTIFY_SENDER_DRY: sctp_notify_sender_dry_event(stcb, so_locked); break; case SCTP_NOTIFY_REMOTE_ERROR: sctp_notify_remote_error(stcb, error, data); break; default: @@ -4150,17 +4156,17 @@ sctp_abort_an_association(struct sctp_in sctp_lock_assert(SCTP_INP_SO(inp)); } else { sctp_unlock_assert(SCTP_INP_SO(inp)); } #endif if (stcb == NULL) { /* Got to have a TCB */ if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) { - if (LIST_FIRST(&inp->sctp_asoc_list) == NULL) { + if (LIST_EMPTY(&inp->sctp_asoc_list)) { #if defined(__APPLE__) if (!so_locked) { SCTP_SOCKET_LOCK(so, 1); } #endif sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT, SCTP_CALLED_DIRECTLY_NOCMPSET); #if defined(__APPLE__) @@ -4217,17 +4223,17 @@ sctp_handle_ootb(struct mbuf *m, int iph { struct sctp_chunkhdr *ch, chunk_buf; unsigned int chk_length; int contains_init_chunk; SCTP_STAT_INCR_COUNTER32(sctps_outoftheblue); /* Generate a TO address for future reference */ if (inp && (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) { - if (LIST_FIRST(&inp->sctp_asoc_list) == NULL) { + if (LIST_EMPTY(&inp->sctp_asoc_list)) { #if defined(__APPLE__) SCTP_SOCKET_LOCK(SCTP_INP_SO(inp), 1); #endif sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT, SCTP_CALLED_DIRECTLY_NOCMPSET); #if defined(__APPLE__) SCTP_SOCKET_UNLOCK(SCTP_INP_SO(inp), 1); #endif @@ -4732,17 +4738,17 @@ sctp_add_to_readq(struct sctp_inpcb *inp if (inp_read_lock_held == 0) SCTP_INP_READ_UNLOCK(inp); if (control->end_added == 1) { struct socket *so; struct mbuf *m; char *buffer; struct sctp_rcvinfo rcv; union sctp_sockstore addr; - int flags = 0; + int flags; if ((buffer = malloc(control->length)) == NULL) { return; } so = stcb->sctp_socket; for (m = control->data; m; m = SCTP_BUF_NEXT(m)) { sctp_sbfree(control, control->stcb, &so->so_rcv, m); } @@ -4765,34 +4771,32 @@ sctp_add_to_readq(struct sctp_inpcb *inp addr.sin = control->whoFrom->ro._l_addr.sin; break; #endif #ifdef INET6 case AF_INET6: addr.sin6 = control->whoFrom->ro._l_addr.sin6; break; #endif -#if defined(__Userspace__) case AF_CONN: addr.sconn = control->whoFrom->ro._l_addr.sconn; break; -#endif default: addr.sa = control->whoFrom->ro._l_addr.sa; break; } + flags = MSG_EOR; if (control->spec_flags & M_NOTIFICATION) { flags |= MSG_NOTIFICATION; } - if (control->spec_flags & M_EOR) { - flags |= MSG_EOR; - } inp->recv_callback(so, addr, buffer, control->length, rcv, flags, inp->ulp_info); SCTP_TCB_LOCK(stcb); atomic_subtract_int(&stcb->asoc.refcnt, 1); + sctp_free_remote_addr(control->whoFrom); + control->whoFrom = NULL; sctp_m_freem(control->data); control->data = NULL; control->length = 0; sctp_free_a_readq(stcb, control); } return; } #endif @@ -4945,34 +4949,42 @@ sctp_append_to_readq(struct sctp_inpcb * control->do_not_ref_stcb = 1; } /* * When we are appending in partial delivery, the cum-ack is used * for the actual pd-api highest tsn on this mbuf. The true cum-ack * is populated in the outbound sinfo structure from the true cumack * if the association exists... */ + control->sinfo_tsn = control->sinfo_cumtsn = ctls_cumack; #if defined(__Userspace__) if (inp->recv_callback) { - if (control->end_added == 1) { + uint32_t pd_point, length; + + length = control->length; + if (stcb != NULL && stcb->sctp_socket != NULL) { + pd_point = min(SCTP_SB_LIMIT_RCV(stcb->sctp_socket) >> SCTP_PARTIAL_DELIVERY_SHIFT, + stcb->sctp_ep->partial_delivery_point); + } else { + pd_point = inp->partial_delivery_point; + } + if ((control->end_added == 1) || (length >= pd_point)) { struct socket *so; char *buffer; struct sctp_rcvinfo rcv; union sctp_sockstore addr; - int flags = 0; + int flags; if ((buffer = malloc(control->length)) == NULL) { return (-1); } - so = inp->sctp_socket; + so = stcb->sctp_socket; for (m = control->data; m; m = SCTP_BUF_NEXT(m)) { sctp_sbfree(control, control->stcb, &so->so_rcv, m); } - atomic_add_int(&stcb->asoc.refcnt, 1); - SCTP_TCB_UNLOCK(stcb); m_copydata(control->data, 0, control->length, buffer); memset(&rcv, 0, sizeof(struct sctp_rcvinfo)); rcv.rcv_sid = control->sinfo_stream; rcv.rcv_ssn = control->sinfo_ssn; rcv.rcv_flags = control->sinfo_flags; rcv.rcv_ppid = control->sinfo_ppid; rcv.rcv_tsn = control->sinfo_tsn; rcv.rcv_cumtsn = control->sinfo_cumtsn; @@ -4985,45 +4997,52 @@ sctp_append_to_readq(struct sctp_inpcb * addr.sin = control->whoFrom->ro._l_addr.sin; break; #endif #ifdef INET6 case AF_INET6: addr.sin6 = control->whoFrom->ro._l_addr.sin6; break; #endif -#if defined(__Userspace__) case AF_CONN: addr.sconn = control->whoFrom->ro._l_addr.sconn; break; -#endif default: addr.sa = control->whoFrom->ro._l_addr.sa; break; } + flags = 0; + if (control->end_added == 1) { + flags |= MSG_EOR; + } if (control->spec_flags & M_NOTIFICATION) { flags |= MSG_NOTIFICATION; } - if (control->spec_flags & M_EOR) { - flags |= MSG_EOR; + sctp_m_freem(control->data); + control->data = NULL; + control->tail_mbuf = NULL; + control->length = 0; + if (control->end_added) { + sctp_free_remote_addr(control->whoFrom); + control->whoFrom = NULL; + sctp_free_a_readq(stcb, control); + } else { + control->some_taken = 1; } - inp->recv_callback(so, addr, buffer, control->length, rcv, flags, inp->ulp_info); + atomic_add_int(&stcb->asoc.refcnt, 1); + SCTP_TCB_UNLOCK(stcb); + inp->recv_callback(so, addr, buffer, length, rcv, flags, inp->ulp_info); SCTP_TCB_LOCK(stcb); atomic_subtract_int(&stcb->asoc.refcnt, 1); - sctp_m_freem(control->data); - control->data = NULL; - control->length = 0; - sctp_free_a_readq(stcb, control); } if (inp) SCTP_INP_READ_UNLOCK(inp); return (0); } #endif - control->sinfo_tsn = control->sinfo_cumtsn = ctls_cumack; if (inp) { SCTP_INP_READ_UNLOCK(inp); } if (inp && inp->sctp_socket) { if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_ZERO_COPY_ACTIVE)) { SCTP_ZERO_COPY_EVENT(inp, inp->sctp_socket); } else { #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) @@ -5267,17 +5286,16 @@ sctp_release_pr_sctp_chunk(struct sctp_t chk->whoTo = stcb->asoc.primary_destination; atomic_add_int(&chk->whoTo->ref_count, 1); #if defined(__FreeBSD__) || defined(__Panda__) chk->rec.data.TSN_seq = atomic_fetchadd_int(&stcb->asoc.sending_seq, 1); #else chk->rec.data.TSN_seq = stcb->asoc.sending_seq++; #endif stcb->asoc.pr_sctp_cnt++; - chk->pr_sctp_on = 1; TAILQ_INSERT_TAIL(&stcb->asoc.sent_queue, chk, sctp_next); stcb->asoc.sent_queue_cnt++; stcb->asoc.pr_sctp_cnt++; } else { chk->rec.data.rcv_flags |= SCTP_DATA_LAST_FRAG; } strq->next_sequence_send++; oh_well: @@ -5426,20 +5444,20 @@ sctp_get_ifa_hash_val(struct sockaddr *a hash_of_addr = (hash_of_addr ^ (hash_of_addr >> 16)); return (hash_of_addr); } #endif #if defined(__Userspace__) case AF_CONN: { struct sockaddr_conn *sconn; - uint64_t temp; + uintptr_t temp; sconn = (struct sockaddr_conn *)addr; - temp = (uint64_t)sconn->sconn_addr; + temp = (uintptr_t)sconn->sconn_addr; return ((uint32_t)(temp ^ (temp >> 16))); } #endif default: break; } return (0); } @@ -5699,17 +5717,17 @@ sctp_sorecvmsg(struct socket *so, SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTPUTIL, EFAULT); return (EFAULT); } rwnd_req = (SCTP_SB_LIMIT_RCV(so) >> SCTP_RWND_HIWAT_SHIFT); /* Must be at least a MTU's worth */ if (rwnd_req < SCTP_MIN_RWND) rwnd_req = SCTP_MIN_RWND; in_eeor_mode = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXPLICIT_EOR); - if (SCTP_BASE_SYSCTL(sctp_logging_level) &SCTP_RECV_RWND_LOGGING_ENABLE) { + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_RECV_RWND_LOGGING_ENABLE) { #if defined(__APPLE__) #if defined(APPLE_LEOPARD) sctp_misc_ints(SCTP_SORECV_ENTER, rwnd_req, in_eeor_mode, so->so_rcv.sb_cc, uio->uio_resid); #else sctp_misc_ints(SCTP_SORECV_ENTER, rwnd_req, in_eeor_mode, so->so_rcv.sb_cc, uio_resid(uio)); #endif @@ -6454,18 +6472,18 @@ sctp_sorecvmsg(struct socket *so, #if defined(APPLE_LEOPARD) if ((uio->uio_resid == 0) || #else if ((uio_resid(uio) == 0) || #endif #else if ((uio->uio_resid == 0) || #endif - ((in_eeor_mode) && (copied_so_far >= max(so->so_rcv.sb_lowat, 1))) - ) { + ((in_eeor_mode) && + (copied_so_far >= (uint32_t)max(so->so_rcv.sb_lowat, 1)))) { goto release; } /* * If I hit here the receiver wants more and this message is * NOT done (pd-api). So two questions. Can we block? if not * we are done. Did the user NOT set MSG_WAITALL? */ if (block_allowed == 0) { @@ -6975,17 +6993,17 @@ sctp_hashinit_flags(int elements, struct /*cannot use MALLOC here because it has to be declared or defined using MALLOC_DECLARE or MALLOC_DEFINE first. */ if (flags & HASH_WAITOK) hashtbl = malloc((u_long)hashsize * sizeof(*hashtbl)); else if (flags & HASH_NOWAIT) hashtbl = malloc((u_long)hashsize * sizeof(*hashtbl)); else { #ifdef INVARIANTS - SCTP_PRINTF("flag incorrect in hashinit_flags"); + SCTP_PRINTF("flag incorrect in hashinit_flags.\n"); #endif return (NULL); } /* no memory? */ if (hashtbl == NULL) return (NULL); @@ -6999,17 +7017,17 @@ sctp_hashinit_flags(int elements, struct void sctp_hashdestroy(void *vhashtbl, struct malloc_type *type, u_long hashmask) { LIST_HEAD(generic, generic) *hashtbl, *hp; hashtbl = vhashtbl; for (hp = hashtbl; hp <= &hashtbl[hashmask]; hp++) if (!LIST_EMPTY(hp)) { - SCTP_PRINTF("hashdestroy: hash not empty"); + SCTP_PRINTF("hashdestroy: hash not empty.\n"); return; } FREE(hashtbl, type); } void sctp_hashfreedestroy(void *vhashtbl, struct malloc_type *type, u_long hashmask) @@ -7461,33 +7479,42 @@ sctp_bindx_delete_address(struct sctp_in /* * returns the valid local address count for an assoc, taking into account * all scoping rules */ int sctp_local_addr_count(struct sctp_tcb *stcb) { - int loopback_scope, ipv4_local_scope, local_scope, site_scope; - int ipv4_addr_legal, ipv6_addr_legal; + int loopback_scope; +#if defined(INET) + int ipv4_local_scope, ipv4_addr_legal; +#endif +#if defined (INET6) + int local_scope, site_scope, ipv6_addr_legal; +#endif #if defined(__Userspace__) int conn_addr_legal; #endif struct sctp_vrf *vrf; struct sctp_ifn *sctp_ifn; struct sctp_ifa *sctp_ifa; int count = 0; /* Turn on all the appropriate scopes */ loopback_scope = stcb->asoc.scope.loopback_scope; +#if defined(INET) ipv4_local_scope = stcb->asoc.scope.ipv4_local_scope; + ipv4_addr_legal = stcb->asoc.scope.ipv4_addr_legal; +#endif +#if defined(INET6) local_scope = stcb->asoc.scope.local_scope; site_scope = stcb->asoc.scope.site_scope; - ipv4_addr_legal = stcb->asoc.scope.ipv4_addr_legal; ipv6_addr_legal = stcb->asoc.scope.ipv6_addr_legal; +#endif #if defined(__Userspace__) conn_addr_legal = stcb->asoc.scope.conn_addr_legal; #endif SCTP_IPI_ADDR_RLOCK(); vrf = sctp_find_vrf(stcb->asoc.vrf_id); if (vrf == NULL) { /* no vrf, no addresses */ SCTP_IPI_ADDR_RUNLOCK();
--- a/netwerk/sctp/src/netinet6/sctp6_usrreq.c +++ b/netwerk/sctp/src/netinet6/sctp6_usrreq.c @@ -27,17 +27,17 @@ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet6/sctp6_usrreq.c 243186 2012-11-17 20:04:04Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet6/sctp6_usrreq.c 257555 2013-11-02 20:12:19Z tuexen $"); #endif #include <netinet/sctp_os.h> #ifdef INET6 #ifdef __FreeBSD__ #include <sys/proc.h> #endif #include <netinet/sctp_pcb.h> @@ -173,17 +173,23 @@ sctp6_input(struct mbuf **i_pak, int *of } #endif #ifdef SCTP_PACKET_LOGGING if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LAST_PACKET_TRACING) { sctp_packet_log(m); } #endif #if defined(__FreeBSD__) -#if __FreeBSD_version >= 800000 +#if __FreeBSD_version > 1000049 + SCTPDBG(SCTP_DEBUG_CRCOFFLOAD, + "sctp6_input(): Packet of length %d received on %s with csum_flags 0x%b.\n", + m->m_pkthdr.len, + if_name(m->m_pkthdr.rcvif), + (int)m->m_pkthdr.csum_flags, CSUM_BITS); +#elif __FreeBSD_version >= 800000 SCTPDBG(SCTP_DEBUG_CRCOFFLOAD, "sctp6_input(): Packet of length %d received on %s with csum_flags 0x%x.\n", m->m_pkthdr.len, if_name(m->m_pkthdr.rcvif), m->m_pkthdr.csum_flags); #else SCTPDBG(SCTP_DEBUG_CRCOFFLOAD, "sctp6_input(): Packet of length %d received on %s with csum_flags 0x%x.\n", @@ -452,18 +458,20 @@ sctp6_notify(struct sctp_inpcb *inp, } if ((icmph->icmp6_code == ICMP_UNREACH_NET) || (icmph->icmp6_code == ICMP_UNREACH_HOST) || (icmph->icmp6_code == ICMP_UNREACH_NET_UNKNOWN) || (icmph->icmp6_code == ICMP_UNREACH_HOST_UNKNOWN) || (icmph->icmp6_code == ICMP_UNREACH_ISOLATED) || (icmph->icmp6_code == ICMP_UNREACH_NET_PROHIB) || (icmph->icmp6_code == ICMP_UNREACH_HOST_PROHIB) || -#ifdef __Panda__ +#if defined(__Panda__) (icmph->icmp6_code == ICMP_UNREACH_ADMIN)) { +#elif defined(__Userspace_os_NetBSD) + (icmph->icmp6_code == ICMP_UNREACH_ADMIN_PROHIBIT)) { #else (icmph->icmp6_code == ICMP_UNREACH_FILTER_PROHIB)) { #endif /* * Hmm reachablity problems we must examine closely. If its * not reachable, we may have lost a network. Or if there is * NO protocol at the other end named SCTP. well we consider @@ -1085,28 +1093,21 @@ sctp6_send(struct socket *so, int flags, return (EINVAL); } if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL); return (EINVAL); } } if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { - if (!MODULE_GLOBAL(ip6_v6only)) { - struct sockaddr_in sin; + struct sockaddr_in sin; - /* convert v4-mapped into v4 addr and send */ - in6_sin6_2_sin(&sin, sin6); - return (sctp_sendm(so, flags, m, (struct sockaddr *)&sin, - control, p)); - } else { - /* mapped addresses aren't enabled */ - SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL); - return (EINVAL); - } + /* convert v4-mapped into v4 addr and send */ + in6_sin6_2_sin(&sin, sin6); + return (sctp_sendm(so, flags, m, (struct sockaddr *)&sin, control, p)); } #endif /* INET */ connected_type: /* now what about control */ if (control) { if (inp->control) { SCTP_PRINTF("huh? control set?\n"); SCTP_RELEASE_PKT(inp->control); @@ -1174,24 +1175,26 @@ sctp6_connect(struct socket *so, struct static int sctp6_connect(struct socket *so, struct mbuf *nam, struct proc *p) { struct sockaddr *addr = mtod(nam, struct sockaddr *); #endif uint32_t vrf_id; int error = 0; struct sctp_inpcb *inp; - struct in6pcb *inp6; struct sctp_tcb *stcb; #ifdef INET + struct in6pcb *inp6; struct sockaddr_in6 *sin6; struct sockaddr_storage ss; #endif +#ifdef INET inp6 = (struct in6pcb *)so->so_pcb; +#endif inp = (struct sctp_inpcb *)so->so_pcb; if (inp == NULL) { SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ECONNRESET); return (ECONNRESET); /* I made the same as TCP since we are * not setup? */ } if (addr == NULL) { SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL); @@ -1264,27 +1267,19 @@ sctp6_connect(struct socket *so, struct if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { SCTP_INP_RUNLOCK(inp); SCTP_ASOC_CREATE_UNLOCK(inp); SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL); return (EINVAL); } } if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { - if (!MODULE_GLOBAL(ip6_v6only)) { - /* convert v4-mapped into v4 addr */ - in6_sin6_2_sin((struct sockaddr_in *)&ss, sin6); - addr = (struct sockaddr *)&ss; - } else { - /* mapped addresses aren't enabled */ - SCTP_INP_RUNLOCK(inp); - SCTP_ASOC_CREATE_UNLOCK(inp); - SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL); - return (EINVAL); - } + /* convert v4-mapped into v4 addr */ + in6_sin6_2_sin((struct sockaddr_in *)&ss, sin6); + addr = (struct sockaddr *)&ss; } #endif /* INET */ /* Now do we connect? */ if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) { stcb = LIST_FIRST(&inp->sctp_asoc_list); if (stcb) { SCTP_TCB_UNLOCK(stcb); } @@ -1685,17 +1680,17 @@ sctp6_getpeeraddr(struct socket *so, str #if defined(__Panda__) *namelen = nam->sa_len; #endif return (error); } #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__) struct pr_usrreqs sctp6_usrreqs = { -#if __FreeBSD_version >= 600000 +#if defined(__FreeBSD__) .pru_abort = sctp6_abort, .pru_accept = sctp_accept, .pru_attach = sctp6_attach, .pru_bind = sctp6_bind, .pru_connect = sctp6_connect, .pru_control = in6_control, #if __FreeBSD_version >= 690000 .pru_close = sctp6_close, @@ -1709,56 +1704,62 @@ struct pr_usrreqs sctp6_usrreqs = { .pru_disconnect = sctp6_disconnect, .pru_listen = sctp_listen, .pru_peeraddr = sctp6_getpeeraddr, .pru_send = sctp6_send, .pru_shutdown = sctp_shutdown, .pru_sockaddr = sctp6_in6getaddr, .pru_sosend = sctp_sosend, .pru_soreceive = sctp_soreceive -#else +#elif defined(__APPLE__) + .pru_abort = sctp6_abort, + .pru_accept = sctp_accept, + .pru_attach = sctp6_attach, + .pru_bind = sctp6_bind, + .pru_connect = sctp6_connect, + .pru_connect2 = pru_connect2_notsupp, + .pru_control = in6_control, + .pru_detach = sctp6_detach, + .pru_disconnect = sctp6_disconnect, + .pru_listen = sctp_listen, + .pru_peeraddr = sctp6_getpeeraddr, + .pru_rcvd = NULL, + .pru_rcvoob = pru_rcvoob_notsupp, + .pru_send = sctp6_send, + .pru_sense = pru_sense_null, + .pru_shutdown = sctp_shutdown, + .pru_sockaddr = sctp6_in6getaddr, + .pru_sosend = sctp_sosend, + .pru_soreceive = sctp_soreceive, + .pru_sopoll = sopoll +#elif defined(__Windows__) sctp6_abort, sctp_accept, sctp6_attach, sctp6_bind, sctp6_connect, pru_connect2_notsupp, -#if defined(__Windows__) NULL, NULL, -#else - in6_control, - sctp6_detach, -#endif sctp6_disconnect, sctp_listen, sctp6_getpeeraddr, NULL, pru_rcvoob_notsupp, -#if defined(__Windows__) NULL, -#else - sctp6_send, -#endif pru_sense_null, sctp_shutdown, -#if defined(__Windows__) sctp_flush, -#endif sctp6_in6getaddr, sctp_sosend, sctp_soreceive, -#if !defined(__Windows__) - sopoll -#else sopoll_generic, NULL, sctp6_close #endif -#endif }; #elif !defined(__Panda__) && !defined(__Userspace__) int sctp6_usrreq(so, req, m, nam, control, p) struct socket *so; int req; struct mbuf *m, *nam, *control;
--- a/netwerk/sctp/src/netinet6/sctp6_var.h +++ b/netwerk/sctp/src/netinet6/sctp6_var.h @@ -50,24 +50,24 @@ extern struct pr_usrreqs sctp6_usrreqs; int sctp6_usrreq(struct socket *, int, struct mbuf *, struct mbuf *, struct mbuf *); #endif #if defined(__APPLE__) int sctp6_input(struct mbuf **, int *); int sctp6_input_with_port(struct mbuf **, int *, uint16_t); #elif defined(__Panda__) int sctp6_input (pakhandle_type *); -#elif defined(__FreeBSD__) && __FreeBSD_version < 1000000 +#elif defined(__FreeBSD__) && __FreeBSD_version < 902000 int sctp6_input __P((struct mbuf **, int *, int)); int sctp6_input_with_port __P((struct mbuf **, int *, uint16_t)); #else int sctp6_input(struct mbuf **, int *, int); int sctp6_input_with_port(struct mbuf **, int *, uint16_t); #endif -#if defined(__FreeBSD__) && __FreeBSD_version < 1000000 +#if defined(__FreeBSD__) && __FreeBSD_version < 902000 int sctp6_output __P((struct sctp_inpcb *, struct mbuf *, struct sockaddr *, struct mbuf *, struct proc *)); void sctp6_ctlinput __P((int, struct sockaddr *, void *)); #else int sctp6_output(struct sctp_inpcb *, struct mbuf *, struct sockaddr *, struct mbuf *, struct proc *); void sctp6_ctlinput(int, struct sockaddr *, void *);
--- a/netwerk/sctp/src/user_environment.c +++ b/netwerk/sctp/src/user_environment.c @@ -28,21 +28,16 @@ * SUCH DAMAGE. */ /* __Userspace__ */ #include <stdlib.h> #if !defined (__Userspace_os_Windows) #include <stdint.h> -#if !defined(__Userspace_os_FreeBSD) -#if !defined(ANDROID) -#include <sys/sysctl.h> -#endif -#endif #include <netinet/sctp_os_userspace.h> #endif #include <user_environment.h> #include <sys/types.h> /* #include <sys/param.h> defines MIN */ #if !defined(MIN) #define MIN(arg1,arg2) ((arg1) < (arg2) ? (arg1) : (arg2)) #endif
--- a/netwerk/sctp/src/user_inpcb.h +++ b/netwerk/sctp/src/user_inpcb.h @@ -30,38 +30,30 @@ * $FreeBSD: src/sys/netinet/in_pcb.h,v 1.100.2.1 2007/12/07 05:46:08 kmacy Exp $ */ #ifndef _USER_INPCB_H_ #define _USER_INPCB_H_ #include <user_route.h> /* was <net/route.h> */ -#if defined(ANDROID) -#include <arpa/inet.h> -#include <netinet/in.h> -/* missing defines in Android bionic libc/NDK */ -typedef uint16_t in_port_t; -#endif - #define in6pcb inpcb /* for KAME src sync over BSD*'s */ #define in6p_sp inp_sp /* for KAME src sync over BSD*'s */ struct inpcbpolicy; /* * Struct inpcb is the ommon structure pcb for the Internet Protocol * implementation. * * Pointers to local and foreign host table entries, local and foreign socket * numbers, and pointers up (to a socket structure) and down (to a * protocol-specific control block) are stored here. */ LIST_HEAD(inpcbhead, inpcb); LIST_HEAD(inpcbporthead, inpcbport); -typedef u_quad_t inp_gen_t; /* * PCB with AF_INET6 null bind'ed laddr can receive AF_INET input packet. * So, AF_INET6 null laddr is also used as AF_INET null laddr, by utilizing * the following structure. */ struct in_addr_4in6 { u_int32_t ia46_pad32[3]; @@ -171,17 +163,16 @@ struct inpcb { struct icmp6_filter *inp6_icmp6filt; /* IPV6_CHECKSUM setsockopt */ int inp6_cksum; short inp6_hops; } inp_depend6; LIST_ENTRY(inpcb) inp_portlist; struct inpcbport *inp_phd; /* head of this list */ #define inp_zero_size offsetof(struct inpcb, inp_gencnt) - inp_gen_t inp_gencnt; /* generation count of this instance */ struct mtx inp_mtx; #define in6p_faddr inp_inc.inc6_faddr #define in6p_laddr inp_inc.inc6_laddr #define in6p_hops inp_depend6.inp6_hops /* default hop limit */ #define in6p_ip6_nxt inp_ip_p #define in6p_flowinfo inp_flow #define in6p_vflag inp_vflag @@ -200,36 +191,16 @@ struct inpcb { }; /* * The range of the generation count, as used in this implementation, is 9e19. * We would have to create 300 billion connections per second for this number * to roll over in a year. This seems sufficiently unlikely that we simply * don't concern ourselves with that possibility. */ -/* - * Interface exported to userland by various protocols which use inpcbs. Hack - * alert -- only define if struct xsocket is in scope. - */ -#ifdef _SYS_SOCKETVAR_H_ -struct xinpcb { - size_t xi_len; /* length of this structure */ - struct inpcb xi_inp; - struct xsocket xi_socket; - u_quad_t xi_alignment_hack; -}; - -struct xinpgen { - size_t xig_len; /* length of this structure */ - u_int xig_count; /* number of PCBs at this time */ - inp_gen_t xig_gen; /* generation count at this time */ - so_gen_t xig_sogen; /* socket generation count at this time */ -}; -#endif /* _SYS_SOCKETVAR_H_ */ - struct inpcbport { LIST_ENTRY(inpcbport) phd_hash; struct inpcbhead phd_pcblist; u_short phd_port; }; /* * Global data structure for each high-level protocol (UDP, TCP, ...) in both @@ -266,17 +237,16 @@ struct inpcbinfo { * UMA zone from which inpcbs are allocated for this protocol. */ struct uma_zone *ipi_zone; /* * Generation count--incremented each time a connection is allocated * or freed. */ - u_quad_t ipi_gencnt; struct mtx ipi_mtx; /* * vimage 1 * general use 1 */ void *ipi_pspare[2]; }; @@ -371,22 +341,17 @@ extern int ipport_firstauto; extern int ipport_lastauto; extern int ipport_hifirstauto; extern int ipport_hilastauto; extern struct callout ipport_tick_callout; void in_pcbpurgeif0(struct inpcbinfo *, struct ifnet *); int in_pcballoc(struct socket *, struct inpcbinfo *); int in_pcbbind(struct inpcb *, struct sockaddr *, struct ucred *); -int in_pcbbind_setup(struct inpcb *, struct sockaddr *, in_addr_t *, - u_short *, struct ucred *); int in_pcbconnect(struct inpcb *, struct sockaddr *, struct ucred *); -int in_pcbconnect_setup(struct inpcb *, struct sockaddr *, in_addr_t *, - u_short *, in_addr_t *, u_short *, struct inpcb **, - struct ucred *); void in_pcbdetach(struct inpcb *); void in_pcbdisconnect(struct inpcb *); void in_pcbdrop(struct inpcb *); void in_pcbfree(struct inpcb *); int in_pcbinshash(struct inpcb *); struct inpcb * in_pcblookup_local(struct inpcbinfo *, struct in_addr, u_int, int); @@ -394,18 +359,16 @@ struct inpcb * in_pcblookup_hash(struct inpcbinfo *, struct in_addr, u_int, struct in_addr, u_int, int, struct ifnet *); void in_pcbnotifyall(struct inpcbinfo *pcbinfo, struct in_addr, int, struct inpcb *(*)(struct inpcb *, int)); void in_pcbrehash(struct inpcb *); void in_pcbsetsolabel(struct socket *so); int in_getpeeraddr(struct socket *so, struct sockaddr **nam); int in_getsockaddr(struct socket *so, struct sockaddr **nam); -struct sockaddr * - in_sockaddr(in_port_t port, struct in_addr *addr); void in_pcbsosetlabel(struct socket *so); void in_pcbremlists(struct inpcb *inp); void ipport_tick(void *xtp); /* * Debugging routines compiled in when DDB is present. */ void db_print_inpcb(struct inpcb *inp, const char *name, int indent);
--- a/netwerk/sctp/src/user_ip6_var.h +++ b/netwerk/sctp/src/user_ip6_var.h @@ -90,17 +90,17 @@ struct ip6_hdr { #if !defined(__Userspace_os_Windows) #if !defined(__Userspace_os_Linux) #define s6_addr8 __u6_addr.__u6_addr8 #define s6_addr16 __u6_addr.__u6_addr16 #define s6_addr32 __u6_addr.__u6_addr32 #endif #endif -#if !defined(__Userspace_os_FreeBSD) && !defined(__Userspace_os_OpenBSD) +#if !defined(__Userspace_os_FreeBSD) && !defined(__Userspace_os_OpenBSD) && !defined(__Userspace_os_DragonFly) struct route_in6 { struct rtentry *ro_rt; struct llentry *ro_lle; struct in6_addr *ro_ia6; int ro_flags; struct sockaddr_in6 ro_dst; }; #endif
--- a/netwerk/sctp/src/user_mbuf.h +++ b/netwerk/sctp/src/user_mbuf.h @@ -158,19 +158,19 @@ struct mbstat { * Mbufs are of a single size, MSIZE (sys/param.h), which includes overhead. * An mbuf may add a single "mbuf cluster" of size MCLBYTES (also in * sys/param.h), which has no additional overhead and is used instead of the * internal data area; this is done when at least MINCLSIZE of data must be * stored. Additionally, it is possible to allocate a separate buffer * externally and attach it to the mbuf in a way similar to that of mbuf * clusters. */ -#define MLEN (MSIZE - sizeof(struct m_hdr)) /* normal data len */ -#define MHLEN (MLEN - sizeof(struct pkthdr)) /* data len w/pkthdr */ -#define MINCLSIZE (MHLEN + 1) /* smallest amount to put in cluster */ +#define MLEN ((int)(MSIZE - sizeof(struct m_hdr))) /* normal data len */ +#define MHLEN ((int)(MLEN - sizeof(struct pkthdr))) /* data len w/pkthdr */ +#define MINCLSIZE ((int)(MHLEN + 1)) /* smallest amount to put in cluster */ #define M_MAXCOMPRESS (MHLEN / 2) /* max amount to copy for compression */ /* * Header present at the beginning of every mbuf. */ struct m_hdr { struct mbuf *mh_next; /* next buffer in chain */ @@ -262,17 +262,16 @@ struct mbuf { #define M_PKTHDR 0x0002 /* start of record */ #define M_EOR 0x0004 /* end of record */ #define M_RDONLY 0x0008 /* associated data is marked read-only */ #define M_PROTO1 0x0010 /* protocol-specific */ #define M_PROTO2 0x0020 /* protocol-specific */ #define M_PROTO3 0x0040 /* protocol-specific */ #define M_PROTO4 0x0080 /* protocol-specific */ #define M_PROTO5 0x0100 /* protocol-specific */ -#define M_NOTIFICATION M_PROTO5/* SCTP notification */ #define M_SKIP_FIREWALL 0x4000 /* skip firewall processing */ #define M_FREELIST 0x8000 /* mbuf is on the free list */ /* * Flags copied when copying m_pkthdr. */ #define M_COPYFLAGS (M_PKTHDR|M_EOR|M_RDONLY|M_PROTO1|M_PROTO1|M_PROTO2|\
--- a/netwerk/sctp/src/user_recv_thread.c +++ b/netwerk/sctp/src/user_recv_thread.c @@ -30,17 +30,17 @@ #if defined(INET) || defined(INET6) #include <sys/types.h> #if !defined(__Userspace_os_Windows) #include <sys/socket.h> #include <netinet/in.h> #include <unistd.h> #include <pthread.h> -#if !defined(__Userspace_os_FreeBSD) +#if !defined(__Userspace_os_DragonFly) && !defined(__Userspace_os_FreeBSD) && !defined(__Userspace_os_NetBSD) #include <sys/uio.h> #else #include <user_ip6_var.h> #endif #endif #include <netinet/sctp_os.h> #include <netinet/sctp_var.h> #include <netinet/sctp_pcb.h> @@ -51,33 +51,33 @@ #ifdef HAVE_LINUX_IF_ADDR_H #include <linux/if_addr.h> #endif #ifdef HAVE_LINUX_RTNETLINK_H #include <linux/rtnetlink.h> #endif #endif #endif -#if defined(__Userspace_os_FreeBSD) || defined(__Userspace_os_Darwin) +#if defined(__Userspace_os_Darwin) || defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD) #include <net/route.h> #endif /* local macros and datatypes used to get IP addresses system independently */ #if !defined(IP_PKTINFO ) && ! defined(IP_RECVDSTADDR) # error "Can't determine socket option to use to get UDP IP" #endif void recv_thread_destroy(void); #define MAXLEN_MBUF_CHAIN 32 /* What should this value be? */ #define ROUNDUP(a, size) (((a) & ((size)-1)) ? (1 + ((a) | ((size)-1))) : (a)) -#if defined(__Userspace_os_FreeBSD) || defined(__Userspace_os_Darwin) +#if defined(__Userspace_os_Darwin) || defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD) #define NEXT_SA(ap) ap = (struct sockaddr *) \ ((caddr_t) ap + (ap->sa_len ? ROUNDUP(ap->sa_len, sizeof (uint32_t)) : sizeof(uint32_t))) #endif -#if defined(__Userspace_os_Darwin) || defined(__Userspace_os_FreeBSD) +#if defined(__Userspace_os_Darwin) || defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD) static void sctp_get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info) { int i; for (i = 0; i < RTAX_MAX; i++) { if (addrs & (1 << i)) { rti_info[i] = sa; @@ -178,17 +178,17 @@ recv_function_route(void *arg) if (ret < 0) { if (errno == EAGAIN) { continue; } else { break; } } } - pthread_exit(NULL); + return (NULL); } #endif #if 0 /* This does not yet work on Linux */ static void * recv_function_route(void *arg) { @@ -261,17 +261,17 @@ recv_function_route(void *arg) default: SCTPDBG(SCTP_DEBUG_USR, "Address family %d not supported.\n", rtmsg->ifa_family); break; } } } } } - pthread_exit(NULL); + return (NULL); } #endif #ifdef INET static void * recv_function_raw(void *arg) { struct mbuf **recvmbuf; @@ -355,16 +355,18 @@ recv_function_raw(void *arg) if (errno == EAGAIN) { continue; } else { break; } } #endif SCTP_HEADER_LEN(recvmbuf[0]) = n; /* length of total packet */ + SCTP_STAT_INCR(sctps_recvpackets); + SCTP_STAT_INCR_COUNTER64(sctps_inpackets); if (n <= iovlen) { SCTP_BUF_LEN(recvmbuf[0]) = n; (to_fill)++; } else { i = 0; SCTP_BUF_LEN(recvmbuf[0]) = iovlen; @@ -399,54 +401,54 @@ recv_function_raw(void *arg) #ifdef HAVE_SIN_LEN src.sin_len = sizeof(struct sockaddr_in); #endif src.sin_addr = iphdr->ip_src; src.sin_port = sh->src_port; /* SCTP does not allow broadcasts or multicasts */ if (IN_MULTICAST(ntohl(dst.sin_addr.s_addr))) { - return NULL; + return (NULL); } if (SCTP_IS_IT_BROADCAST(dst.sin_addr, recvmbuf[0])) { - return NULL; + return (NULL); } port = 0; -#if !defined(SCTP_WITH_NO_CSUM) +#if defined(SCTP_WITH_NO_CSUM) + SCTP_STAT_INCR(sctps_recvnocrc); +#else if (src.sin_addr.s_addr == dst.sin_addr.s_addr) { compute_crc = 0; + SCTP_STAT_INCR(sctps_recvnocrc); + } else { + SCTP_STAT_INCR(sctps_recvswcrc); } #endif SCTPDBG(SCTP_DEBUG_USR, "%s: Received %d bytes.", __func__, n); SCTPDBG(SCTP_DEBUG_USR, " - calling sctp_common_input_processing with off=%d\n", offset); - sctp_common_input_processing(&recvmbuf[0], sizeof(struct ip), offset, n, (struct sockaddr *)&src, (struct sockaddr *)&dst, sh, ch, #if !defined(SCTP_WITH_NO_CSUM) compute_crc, -#else - 0, #endif ecn, SCTP_DEFAULT_VRFID, port); + if (recvmbuf[0]) { + m_freem(recvmbuf[0]); + } } for (i = 0; i < MAXLEN_MBUF_CHAIN; i++) { m_free(recvmbuf[i]); } /* free the array itself */ free(recvmbuf); -#if defined (__Userspace_os_Windows) - ExitThread(0); -#else - pthread_exit(NULL); -#endif return (NULL); } #endif #if defined(INET6) static void * recv_function_raw6(void *arg) { @@ -548,16 +550,18 @@ recv_function_raw6(void *arg) if (errno == EAGAIN) { continue; } else { break; } } #endif SCTP_HEADER_LEN(recvmbuf6[0]) = n; /* length of total packet */ + SCTP_STAT_INCR(sctps_recvpackets); + SCTP_STAT_INCR_COUNTER64(sctps_inpackets); if (n <= iovlen) { SCTP_BUF_LEN(recvmbuf6[0]) = n; (to_fill)++; } else { i = 0; SCTP_BUF_LEN(recvmbuf6[0]) = iovlen; @@ -592,45 +596,46 @@ recv_function_raw6(void *arg) #endif dst.sin6_port = sh->dest_port; src.sin6_family = AF_INET6; #ifdef HAVE_SIN6_LEN src.sin6_len = sizeof(struct sockaddr_in6); #endif src.sin6_port = sh->src_port; -#if !defined(SCTP_WITH_NO_CSUM) +#if defined(SCTP_WITH_NO_CSUM) + SCTP_STAT_INCR(sctps_recvnocrc); +#else if (memcmp(&src.sin6_addr, &dst.sin6_addr, sizeof(struct in6_addr)) == 0) { compute_crc = 0; + SCTP_STAT_INCR(sctps_recvnocrc); + } else { + SCTP_STAT_INCR(sctps_recvswcrc); } #endif SCTPDBG(SCTP_DEBUG_USR, "%s: Received %d bytes.", __func__, n); SCTPDBG(SCTP_DEBUG_USR, " - calling sctp_common_input_processing with off=%d\n", offset); sctp_common_input_processing(&recvmbuf6[0], 0, offset, n, (struct sockaddr *)&src, (struct sockaddr *)&dst, sh, ch, #if !defined(SCTP_WITH_NO_CSUM) compute_crc, -#else - 0, #endif 0, SCTP_DEFAULT_VRFID, 0); + if (recvmbuf6[0]) { + m_freem(recvmbuf6[0]); + } } for (i = 0; i < MAXLEN_MBUF_CHAIN; i++) { m_free(recvmbuf6[i]); } /* free the array itself */ free(recvmbuf6); -#if defined (__Userspace_os_Windows) - ExitThread(0); -#else - pthread_exit(NULL); -#endif return (NULL); } #endif #ifdef INET static void * recv_function_udp(void *arg) { @@ -735,16 +740,18 @@ recv_function_udp(void *arg) } if ((m_ErrorCode == WSAENOTSOCK) || (m_ErrorCode == WSAEINTR)) { break; } } n = ncounter; #endif SCTP_HEADER_LEN(udprecvmbuf[0]) = n; /* length of total packet */ + SCTP_STAT_INCR(sctps_recvpackets); + SCTP_STAT_INCR_COUNTER64(sctps_inpackets); if (n <= iovlen) { SCTP_BUF_LEN(udprecvmbuf[0]) = n; (to_fill)++; } else { i = 0; SCTP_BUF_LEN(udprecvmbuf[0]) = iovlen; @@ -784,58 +791,59 @@ recv_function_udp(void *arg) memcpy((void *)&dst.sin_addr, (const void *)addr, sizeof(struct in_addr)); break; } #endif } /* SCTP does not allow broadcasts or multicasts */ if (IN_MULTICAST(ntohl(dst.sin_addr.s_addr))) { - return NULL; + return (NULL); } if (SCTP_IS_IT_BROADCAST(dst.sin_addr, udprecvmbuf[0])) { - return NULL; + return (NULL); } /*offset = sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr);*/ sh = mtod(udprecvmbuf[0], struct sctphdr *); ch = (struct sctp_chunkhdr *)((caddr_t)sh + sizeof(struct sctphdr)); offset = sizeof(struct sctphdr); port = src.sin_port; src.sin_port = sh->src_port; dst.sin_port = sh->dest_port; -#if !defined(SCTP_WITH_NO_CSUM) +#if defined(SCTP_WITH_NO_CSUM) + SCTP_STAT_INCR(sctps_recvnocrc); +#else if (src.sin_addr.s_addr == dst.sin_addr.s_addr) { compute_crc = 0; + SCTP_STAT_INCR(sctps_recvnocrc); + } else { + SCTP_STAT_INCR(sctps_recvswcrc); } #endif SCTPDBG(SCTP_DEBUG_USR, "%s: Received %d bytes.", __func__, n); SCTPDBG(SCTP_DEBUG_USR, " - calling sctp_common_input_processing with off=%d\n", offset); sctp_common_input_processing(&udprecvmbuf[0], 0, offset, n, (struct sockaddr *)&src, (struct sockaddr *)&dst, sh, ch, #if !defined(SCTP_WITH_NO_CSUM) compute_crc, -#else - 0, #endif 0, SCTP_DEFAULT_VRFID, port); + if (udprecvmbuf[0]) { + m_freem(udprecvmbuf[0]); + } } for (i = 0; i < MAXLEN_MBUF_CHAIN; i++) { m_free(udprecvmbuf[i]); } /* free the array itself */ free(udprecvmbuf); -#if defined (__Userspace_os_Windows) - ExitThread(0); -#else - pthread_exit(NULL); -#endif return (NULL); } #endif #if defined(INET6) static void * recv_function_udp6(void *arg) { @@ -940,16 +948,18 @@ recv_function_udp6(void *arg) } if ((m_ErrorCode == WSAENOTSOCK) || (m_ErrorCode == WSAEINTR)) { break; } } n = ncounter; #endif SCTP_HEADER_LEN(udprecvmbuf6[0]) = n; /* length of total packet */ + SCTP_STAT_INCR(sctps_recvpackets); + SCTP_STAT_INCR_COUNTER64(sctps_inpackets); if (n <= iovlen) { SCTP_BUF_LEN(udprecvmbuf6[0]) = n; (to_fill)++; } else { i = 0; SCTP_BUF_LEN(udprecvmbuf6[0]) = iovlen; @@ -975,54 +985,56 @@ recv_function_udp6(void *arg) info = (struct in6_pktinfo *)CMSG_DATA(cmsgptr); /*dst.sin6_port = htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port));*/ memcpy((void *)&dst.sin6_addr, (const void *)&(info->ipi6_addr), sizeof(struct in6_addr)); } } /* SCTP does not allow broadcasts or multicasts */ if (IN6_IS_ADDR_MULTICAST(&dst.sin6_addr)) { - return NULL; + return (NULL); } sh = mtod(udprecvmbuf6[0], struct sctphdr *); ch = (struct sctp_chunkhdr *)((caddr_t)sh + sizeof(struct sctphdr)); offset = sizeof(struct sctphdr); port = src.sin6_port; src.sin6_port = sh->src_port; dst.sin6_port = sh->dest_port; -#if !defined(SCTP_WITH_NO_CSUM) +#if defined(SCTP_WITH_NO_CSUM) + SCTP_STAT_INCR(sctps_recvnocrc); +#else if ((memcmp(&src.sin6_addr, &dst.sin6_addr, sizeof(struct in6_addr)) == 0)) { compute_crc = 0; + SCTP_STAT_INCR(sctps_recvnocrc); + } else { + SCTP_STAT_INCR(sctps_recvswcrc); } #endif SCTPDBG(SCTP_DEBUG_USR, "%s: Received %d bytes.", __func__, n); SCTPDBG(SCTP_DEBUG_USR, " - calling sctp_common_input_processing with off=%d\n", (int)sizeof(struct sctphdr)); sctp_common_input_processing(&udprecvmbuf6[0], 0, offset, n, (struct sockaddr *)&src, (struct sockaddr *)&dst, sh, ch, #if !defined(SCTP_WITH_NO_CSUM) compute_crc, #endif 0, SCTP_DEFAULT_VRFID, port); - + if (udprecvmbuf6[0]) { + m_freem(udprecvmbuf6[0]); + } } for (i = 0; i < MAXLEN_MBUF_CHAIN; i++) { m_free(udprecvmbuf6[i]); } /* free the array itself */ free(udprecvmbuf6); -#if defined (__Userspace_os_Windows) - ExitThread(0); -#else - pthread_exit(NULL); -#endif return (NULL); } #endif static void setReceiveBufferSize(int sfd, int new_size) { int ch = new_size; @@ -1069,17 +1081,17 @@ recv_thread_init(void) #if !defined(__Userspace_os_Windows) struct timeval timeout; timeout.tv_sec = (SOCKET_TIMEOUT / 1000); timeout.tv_usec = (SOCKET_TIMEOUT % 1000) * 1000; #else unsigned int timeout = SOCKET_TIMEOUT; /* Timeout in milliseconds */ #endif -#if defined(__Userspace_os_Darwin) || defined(__Userspace_os_FreeBSD) +#if defined(__Userspace_os_Darwin) || defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD) if (SCTP_BASE_VAR(userspace_route) == -1) { if ((SCTP_BASE_VAR(userspace_route) = socket(AF_ROUTE, SOCK_RAW, 0)) < 0) { SCTPDBG(SCTP_DEBUG_USR, "Can't create routing socket (errno = %d).\n", errno); } #if 0 struct sockaddr_nl sanl; if ((SCTP_BASE_VAR(userspace_route) = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) < 0) { @@ -1370,17 +1382,17 @@ recv_thread_init(void) setReceiveBufferSize(SCTP_BASE_VAR(userspace_udpsctp6), SB_RAW); /* 128K */ setSendBufferSize(SCTP_BASE_VAR(userspace_udpsctp6), SB_RAW); /* 128K Is this setting net.inet.raw.maxdgram value? Should it be set to 64K? */ } } } } #endif #if !defined(__Userspace_os_Windows) -#if defined(__Userspace_os_Darwin) || defined(__Userspace_os_FreeBSD) +#if defined(__Userspace_os_Darwin) || defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD) #if defined(INET) || defined(INET6) if (SCTP_BASE_VAR(userspace_route) != -1) { int rc; if ((rc = pthread_create(&SCTP_BASE_VAR(recvthreadroute), NULL, &recv_function_route, NULL))) { SCTPDBG(SCTP_DEBUG_USR, "Can't start routing thread (%d).\n", rc); close(SCTP_BASE_VAR(userspace_route)); SCTP_BASE_VAR(userspace_route) = -1; @@ -1462,17 +1474,17 @@ recv_thread_init(void) } #endif #endif } void recv_thread_destroy(void) { -#if defined(__Userspace_os_Darwin) || defined(__Userspace_os_FreeBSD) +#if defined(__Userspace_os_Darwin) || defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD) #if defined(INET) || defined(INET6) if (SCTP_BASE_VAR(userspace_route) != -1) { close(SCTP_BASE_VAR(userspace_route)); } #endif #endif #if defined(INET) if (SCTP_BASE_VAR(userspace_rawsctp) != -1) { @@ -1502,9 +1514,11 @@ recv_thread_destroy(void) #if defined(__Userspace_os_Windows) closesocket(SCTP_BASE_VAR(userspace_udpsctp6)); #else close(SCTP_BASE_VAR(userspace_udpsctp6)); #endif } #endif } +#else +int foo; #endif
--- a/netwerk/sctp/src/user_sctp_timer_iterate.c +++ b/netwerk/sctp/src/user_sctp_timer_iterate.c @@ -89,22 +89,17 @@ user_sctp_timer_iterate(void *arg) SCTP_TIMERQ_LOCK(); c = sctp_os_timer_next; } else { c = TAILQ_NEXT(c, tqe); } } SCTP_TIMERQ_UNLOCK(); } -#if defined (__Userspace_os_Windows) - ExitThread(0); -#else - pthread_exit(NULL); -#endif - return NULL; + return (NULL); } void sctp_start_timer(void) { /* * No need to do SCTP_TIMERQ_LOCK_INIT(); * here, it is being done in sctp_pcb_init()
--- a/netwerk/sctp/src/user_socket.c +++ b/netwerk/sctp/src/user_socket.c @@ -43,24 +43,21 @@ #include <netinet6/sctp6_var.h> #endif #if defined(__Userspace_os_Linux) #define __FAVOR_BSD /* (on Ubuntu at least) enables UDP header field names like BSD in RFC 768 */ #endif #if !defined (__Userspace_os_Windows) #include <netinet/udp.h> #include <arpa/inet.h> -/* Statically initializing accept_mtx and accept_cond since there is no call for ACCEPT_LOCK_INIT() */ -userland_mutex_t accept_mtx = PTHREAD_MUTEX_INITIALIZER; -userland_cond_t accept_cond = PTHREAD_COND_INITIALIZER; #else #include <user_socketvar.h> +#endif userland_mutex_t accept_mtx; userland_cond_t accept_cond; -#endif #ifdef _WIN32 #include <time.h> #include <sys/timeb.h> #endif MALLOC_DEFINE(M_PCB, "sctp_pcb", "sctp pcb"); MALLOC_DEFINE(M_SONAME, "sctp_soname", "sctp soname"); #define MAXLEN_MBUF_CHAIN 32 @@ -156,137 +153,66 @@ sbwait(struct sockbuf *sb) /* Taken from /src/sys/kern/uipc_socket.c * and modified for __Userspace__ */ static struct socket * soalloc(void) { -#if defined(__Userspace__) struct socket *so; /* * soalloc() sets of socket layer state for a socket, * called only by socreate() and sonewconn(). * * sodealloc() tears down socket layer state for a socket, * called only by sofree() and sonewconn(). * __Userspace__ TODO : Make sure so is properly deallocated * when tearing down the connection. */ so = (struct socket *)malloc(sizeof(struct socket)); - if (so == NULL) + if (so == NULL) { return (NULL); - bzero(so, sizeof(struct socket)); + } + memset(so, 0, sizeof(struct socket)); /* __Userspace__ Initializing the socket locks here */ SOCKBUF_LOCK_INIT(&so->so_snd, "so_snd"); SOCKBUF_LOCK_INIT(&so->so_rcv, "so_rcv"); SOCKBUF_COND_INIT(&so->so_snd); SOCKBUF_COND_INIT(&so->so_rcv); SOCK_COND_INIT(so); /* timeo_cond */ /* __Userspace__ Any ref counting required here? Will we have any use for aiojobq? What about gencnt and numopensockets?*/ TAILQ_INIT(&so->so_aiojobq); return (so); -#else - /* Putting the kernel version for reference. The #else - should be removed once the __Userspace__ - version is tested. - */ - struct socket *so; - - so = uma_zalloc(socket_zone, M_NOWAIT | M_ZERO); - if (so == NULL) - return (NULL); -#ifdef MAC - if (mac_init_socket(so, M_NOWAIT) != 0) { - uma_zfree(socket_zone, so); - return (NULL); - } -#endif - SOCKBUF_LOCK_INIT(&so->so_snd, "so_snd"); - SOCKBUF_LOCK_INIT(&so->so_rcv, "so_rcv"); - sx_init(&so->so_snd.sb_sx, "so_snd_sx"); - sx_init(&so->so_rcv.sb_sx, "so_rcv_sx"); - TAILQ_INIT(&so->so_aiojobq); - mtx_lock(&so_global_mtx); - so->so_gencnt = ++so_gencnt; - ++numopensockets; - mtx_unlock(&so_global_mtx); - return (so); -#endif } -#if defined(__Userspace__) -/* - * Free the storage associated with a socket at the socket layer. - */ static void sodealloc(struct socket *so) { KASSERT(so->so_count == 0, ("sodealloc(): so_count %d", so->so_count)); KASSERT(so->so_pcb == NULL, ("sodealloc(): so_pcb != NULL")); + SOCKBUF_COND_DESTROY(&so->so_snd); + SOCKBUF_COND_DESTROY(&so->so_rcv); + + SOCK_COND_DESTROY(so); + SOCKBUF_LOCK_DESTROY(&so->so_snd); SOCKBUF_LOCK_DESTROY(&so->so_rcv); - SOCKBUF_COND_DESTROY(&so->so_snd); - SOCKBUF_COND_DESTROY(&so->so_rcv); - - SOCK_COND_DESTROY(so); - free(so); } -#else /* kernel version for reference. */ -/* - * Free the storage associated with a socket at the socket layer, tear down - * locks, labels, etc. All protocol state is assumed already to have been - * torn down (and possibly never set up) by the caller. - */ -static void -sodealloc(struct socket *so) -{ - - KASSERT(so->so_count == 0, ("sodealloc(): so_count %d", so->so_count)); - KASSERT(so->so_pcb == NULL, ("sodealloc(): so_pcb != NULL")); - - mtx_lock(&so_global_mtx); - so->so_gencnt = ++so_gencnt; - --numopensockets; /* Could be below, but faster here. */ - mtx_unlock(&so_global_mtx); - if (so->so_rcv.sb_hiwat) - (void)chgsbsize(so->so_cred->cr_uidinfo, - &so->so_rcv.sb_hiwat, 0, RLIM_INFINITY); - if (so->so_snd.sb_hiwat) - (void)chgsbsize(so->so_cred->cr_uidinfo, - &so->so_snd.sb_hiwat, 0, RLIM_INFINITY); -#ifdef INET - /* remove acccept filter if one is present. */ - if (so->so_accf != NULL) - do_setopt_accept_filter(so, NULL); -#endif -#ifdef MAC - mac_destroy_socket(so); -#endif - crfree(so->so_cred); - sx_destroy(&so->so_snd.sb_sx); - sx_destroy(&so->so_rcv.sb_sx); - SOCKBUF_LOCK_DESTROY(&so->so_snd); - SOCKBUF_LOCK_DESTROY(&so->so_rcv); - uma_zfree(socket_zone, so); -} -#endif - /* Taken from /src/sys/kern/uipc_socket.c * and modified for __Userspace__ */ void sofree(struct socket *so) { struct socket *head; @@ -346,27 +272,31 @@ sofree(struct socket *so) /* Taken from /src/sys/kern/uipc_socket.c */ int soabort(so) struct socket *so; { int error; +#if defined(INET6) struct sctp_inpcb *inp; - - inp = (struct sctp_inpcb *)so->so_pcb; +#endif #if defined(INET6) - if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) + inp = (struct sctp_inpcb *)so->so_pcb; + if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) { error = sctp6_abort(so); + } else { #if defined(INET) - else error = sctp_abort(so); +#else + error = EAFNOSUPPORT; #endif + } #elif defined(INET) error = sctp_abort(so); #else error = EAFNOSUPPORT; #endif if (error) { sofree(so); return error; @@ -787,17 +717,17 @@ userspace_sctp_sendmsg(struct socket *so /* Perform error checks on destination (to) */ if (tolen > SOCK_MAXADDRLEN){ errno = ENAMETOOLONG; return (-1); } if ((tolen > 0) && - ((to == NULL) || (tolen < sizeof(struct sockaddr)))) { + ((to == NULL) || (tolen < (socklen_t)sizeof(struct sockaddr)))) { errno = EINVAL; return (-1); } /* Adding the following as part of defensive programming, in case the application does not do it when preparing the destination address.*/ #ifdef HAVE_SA_LEN if (to != NULL) { to->sa_len = tolen; @@ -957,17 +887,17 @@ userspace_sctp_sendmbuf(struct socket *s sinfo->sinfo_context = context; sinfo->sinfo_assoc_id = 0; /* Perform error checks on destination (to) */ if (tolen > SOCK_MAXADDRLEN){ error = (ENAMETOOLONG); goto sendmsg_return; } - if (tolen < offsetof(struct sockaddr, sa_data)){ + if (tolen < (socklen_t)offsetof(struct sockaddr, sa_data)){ error = (EINVAL); goto sendmsg_return; } /* Adding the following as part of defensive programming, in case the application does not do it when preparing the destination address.*/ #ifdef HAVE_SA_LEN to->sa_len = tolen; #endif @@ -1039,20 +969,25 @@ userspace_sctp_recvmsg(struct socket *so } else { fromlen = 0; } error = sctp_sorecvmsg(so, &auio, (struct mbuf **)NULL, from, fromlen, msg_flags, (struct sctp_sndrcvinfo *)sinfo, 1); if (error) { - if (auio.uio_resid != (int)ulen && (error == ERESTART || - error == EINTR || error == EWOULDBLOCK)) + if (auio.uio_resid != (int)ulen && + (error == EINTR || +#if !defined(__Userspace_os_NetBSD) + error == ERESTART || +#endif + error == EWOULDBLOCK)) { error = 0; } + } if ((fromlenp != NULL) && (fromlen > 0) && (from != NULL)) { switch (from->sa_family) { #if defined(INET) case AF_INET: *fromlenp = sizeof(struct sockaddr_in); break; #endif #if defined(INET6) @@ -1128,27 +1063,31 @@ usrsctp_recvv(struct socket *so, } else { fromlen = 0; } errno = sctp_sorecvmsg(so, &auio, (struct mbuf **)NULL, from, fromlen, msg_flags, (struct sctp_sndrcvinfo *)&seinfo, 1); if (errno) { if (auio.uio_resid != (int)ulen && - (errno == ERESTART || errno == EINTR || errno == EWOULDBLOCK)) { + (errno == EINTR || +#if !defined(__Userspace_os_NetBSD) + errno == ERESTART || +#endif + errno == EWOULDBLOCK)) { errno = 0; } } if ((*msg_flags & MSG_NOTIFICATION) == 0) { struct sctp_inpcb *inp; inp = (struct sctp_inpcb *)so->so_pcb; if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVNXTINFO) && sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVRCVINFO) && - *infolen >= sizeof(struct sctp_recvv_rn) && + *infolen >= (socklen_t)sizeof(struct sctp_recvv_rn) && seinfo.sreinfo_next_flags & SCTP_NEXT_MSG_AVAIL) { rn = (struct sctp_recvv_rn *)info; rn->recvv_rcvinfo.rcv_sid = seinfo.sinfo_stream; rn->recvv_rcvinfo.rcv_ssn = seinfo.sinfo_ssn; rn->recvv_rcvinfo.rcv_flags = seinfo.sinfo_flags; rn->recvv_rcvinfo.rcv_ppid = seinfo.sinfo_ppid; rn->recvv_rcvinfo.rcv_context = seinfo.sinfo_context; rn->recvv_rcvinfo.rcv_tsn = seinfo.sinfo_tsn; @@ -1166,17 +1105,17 @@ usrsctp_recvv(struct socket *so, rn->recvv_nxtinfo.nxt_flags |= SCTP_COMPLETE; } rn->recvv_nxtinfo.nxt_ppid = seinfo.sreinfo_next_ppid; rn->recvv_nxtinfo.nxt_length = seinfo.sreinfo_next_length; rn->recvv_nxtinfo.nxt_assoc_id = seinfo.sreinfo_next_aid; *infolen = (socklen_t)sizeof(struct sctp_recvv_rn); *infotype = SCTP_RECVV_RN; } else if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVRCVINFO) && - *infolen >= sizeof(struct sctp_rcvinfo)) { + *infolen >= (socklen_t)sizeof(struct sctp_rcvinfo)) { rcv = (struct sctp_rcvinfo *)info; rcv->rcv_sid = seinfo.sinfo_stream; rcv->rcv_ssn = seinfo.sinfo_ssn; rcv->rcv_flags = seinfo.sinfo_flags; rcv->rcv_ppid = seinfo.sinfo_ppid; rcv->rcv_context = seinfo.sinfo_context; rcv->rcv_tsn = seinfo.sinfo_tsn; rcv->rcv_cumtsn = seinfo.sinfo_cumtsn; @@ -1424,68 +1363,41 @@ usrsctp_socket(int domain, int type, int u_long sb_max = SB_MAX; u_long sb_max_adj = SB_MAX * MCLBYTES / (MSIZE + MCLBYTES); /* adjusted sb_max */ static u_long sb_efficiency = 8; /* parameter for sbreserve() */ -#if defined (__Userspace__) /* * Allot mbufs to a sockbuf. Attempt to scale mbmax so that mbcnt doesn't * become limiting if buffering efficiency is near the normal case. */ int 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; if (sb->sb_lowat > (int)sb->sb_hiwat) sb->sb_lowat = (int)sb->sb_hiwat; return (1); } -#else /* kernel version for reference */ -/* - * Allot mbufs to a sockbuf. Attempt to scale mbmax so that mbcnt doesn't - * become limiting if buffering efficiency is near the normal case. - */ -int -sbreserve_locked(struct sockbuf *sb, u_long cc, struct socket *so, - struct thread *td) + +static int +sbreserve(struct sockbuf *sb, u_long cc, struct socket *so) { - rlim_t sbsize_limit; - - SOCKBUF_LOCK_ASSERT(sb); - - /* - * td will only be NULL when we're in an interrupt (e.g. in - * tcp_input()). - * - * XXXRW: This comment needs updating, as might the code. - */ - if (cc > sb_max_adj) - return (0); - if (td != NULL) { - PROC_LOCK(td->td_proc); - sbsize_limit = lim_cur(td->td_proc, RLIMIT_SBSIZE); - PROC_UNLOCK(td->td_proc); - } else - sbsize_limit = RLIM_INFINITY; - if (!chgsbsize(so->so_cred->cr_uidinfo, &sb->sb_hiwat, cc, - sbsize_limit)) - return (0); - sb->sb_mbmax = min(cc * sb_efficiency, sb_max); - if (sb->sb_lowat > sb->sb_hiwat) - sb->sb_lowat = sb->sb_hiwat; - return (1); + int error; + + SOCKBUF_LOCK(sb); + error = sbreserve_locked(sb, cc, so); + SOCKBUF_UNLOCK(sb); + return (error); } -#endif - - #if defined(__Userspace__) int soreserve(struct socket *so, u_long sndcc, u_long rcvcc) { SOCKBUF_LOCK(&so->so_snd); SOCKBUF_LOCK(&so->so_rcv); so->so_snd.sb_hiwat = (uint32_t)sndcc; @@ -1836,18 +1748,43 @@ user_accept(struct socket *head, struct if (sa == NULL) { if (name) *namelen = 0; goto done; } if (name) { #ifdef HAVE_SA_LEN /* check sa_len before it is destroyed */ - if (*namelen > sa->sa_len) + if (*namelen > sa->sa_len) { *namelen = sa->sa_len; + } +#else + socklen_t sa_len; + + switch (sa->sa_family) { +#ifdef INET + case AF_INET: + sa_len = sizeof(struct sockaddr_in); + break; +#endif +#ifdef INET6 + case AF_INET6: + sa_len = sizeof(struct sockaddr_in6); + break; +#endif + case AF_CONN: + sa_len = sizeof(struct sockaddr_conn); + break; + default: + sa_len = 0; + break; + } + if (*namelen > sa_len) { + *namelen = sa_len; + } #endif *name = sa; sa = NULL; } noconnection: if (sa) { FREE(sa, M_SONAME); } @@ -2078,32 +2015,41 @@ int user_connect(struct socket *so, stru if (SleepConditionVariableCS(SOCK_COND(so), SOCK_MTX(so), INFINITE)) error = 0; else error = -1; #else error = pthread_cond_wait(SOCK_COND(so), SOCK_MTX(so)); #endif if (error) { - if (error == EINTR || error == ERESTART) +#if defined(__Userspace_os_NetBSD) + if (error == EINTR) { +#else + if (error == EINTR || error == ERESTART) { +#endif interrupted = 1; + } break; } } if (error == 0) { error = so->so_error; so->so_error = 0; } SOCK_UNLOCK(so); bad: - if (!interrupted) + if (!interrupted) { so->so_state &= ~SS_ISCONNECTING; - if (error == ERESTART) + } +#if !defined(__Userspace_os_NetBSD) + if (error == ERESTART) { error = EINTR; + } +#endif done1: return (error); } int usrsctp_connect(struct socket *so, struct sockaddr *name, int namelen) { struct sockaddr *sa; @@ -2194,16 +2140,17 @@ usrsctp_finish(void) if (SCTP_BASE_VAR(sctp_pcb_initialized) == 0) { return (0); } if (SCTP_INP_INFO_TRYLOCK()) { if (!LIST_EMPTY(&SCTP_BASE_INFO(listhead))) { SCTP_INP_INFO_RUNLOCK(); return (-1); } + SCTP_INP_INFO_RUNLOCK(); } else { return (-1); } sctp_finish(); return (0); } int @@ -2223,16 +2170,48 @@ usrsctp_setsockopt(struct socket *so, in if (so == NULL) { errno = EBADF; return (-1); } switch (level) { case SOL_SOCKET: { switch (option_name) { + case SO_RCVBUF: + if (option_len < (socklen_t)sizeof(int)) { + errno = EINVAL; + return (-1); + } else { + int *buf_size; + + buf_size = (int *)option_value; + if (*buf_size < 1) { + errno = EINVAL; + return (-1); + } + sbreserve(&so->so_rcv, (u_long)*buf_size, so); + return (0); + } + break; + case SO_SNDBUF: + if (option_len < (socklen_t)sizeof(int)) { + errno = EINVAL; + return (-1); + } else { + int *buf_size; + + buf_size = (int *)option_value; + if (*buf_size < 1) { + errno = EINVAL; + return (-1); + } + sbreserve(&so->so_snd, (u_long)*buf_size, so); + return (0); + } + break; case SO_LINGER: if (option_len < (socklen_t)sizeof(struct linger)) { errno = EINVAL; return (-1); } else { struct linger *l; l = (struct linger *)option_value; @@ -2284,16 +2263,42 @@ usrsctp_getsockopt(struct socket *so, in } if (option_len == NULL) { errno = EFAULT; return (-1); } switch (level) { case SOL_SOCKET: switch (option_name) { + case SO_RCVBUF: + if (*option_len < (socklen_t)sizeof(int)) { + errno = EINVAL; + return (-1); + } else { + int *buf_size; + + buf_size = (int *)option_value; + *buf_size = so->so_rcv.sb_hiwat;; + *option_len = (socklen_t)sizeof(int); + return (0); + } + break; + case SO_SNDBUF: + if (*option_len < (socklen_t)sizeof(int)) { + errno = EINVAL; + return (-1); + } else { + int *buf_size; + + buf_size = (int *)option_value; + *buf_size = so->so_snd.sb_hiwat; + *option_len = (socklen_t)sizeof(int); + return (0); + } + break; case SO_LINGER: if (*option_len < (socklen_t)sizeof(struct linger)) { errno = EINVAL; return (-1); } else { struct linger *l; l = (struct linger *)option_value; @@ -2336,23 +2341,27 @@ userspace_getsockopt(struct socket *so, return (usrsctp_getsockopt(so, level, option_name, option_value, option_len)); } int usrsctp_bindx(struct socket *so, struct sockaddr *addrs, int addrcnt, int flags) { struct sctp_getaddresses *gaddrs; struct sockaddr *sa; +#ifdef INET struct sockaddr_in *sin; +#endif #ifdef INET6 struct sockaddr_in6 *sin6; #endif int i; size_t argsz; +#if defined(INET) || defined(INET6) uint16_t sport = 0; +#endif /* validate the flags */ if ((flags != SCTP_BINDX_ADD_ADDR) && (flags != SCTP_BINDX_REM_ADDR)) { errno = EFAULT; return (-1); } /* validate the address count and list */ @@ -2382,17 +2391,17 @@ usrsctp_bindx(struct socket *so, struct return (-1); } } else { /* save off the port */ sport = sin->sin_port; } } #ifndef HAVE_SA_LEN - sa = (struct sockaddr *)((caddr_t)sa + sizeof(struct sockaddr_in)); + sa = (struct sockaddr *)((caddr_t)sa + sizeof(struct sockaddr_in)); #endif break; #endif #ifdef INET6 case AF_INET6: #ifdef HAVE_SA_LEN if (sa->sa_len != sizeof(struct sockaddr_in6)) { errno = EINVAL; @@ -2409,37 +2418,29 @@ usrsctp_bindx(struct socket *so, struct return (-1); } } else { /* save off the port */ sport = sin6->sin6_port; } } #ifndef HAVE_SA_LEN - sa = (struct sockaddr *)((caddr_t)sa + sizeof(struct sockaddr_in6)); + sa = (struct sockaddr *)((caddr_t)sa + sizeof(struct sockaddr_in6)); #endif break; #endif default: /* Invalid address family specified. */ - errno = EINVAL; + errno = EAFNOSUPPORT; return (-1); } #ifdef HAVE_SA_LEN sa = (struct sockaddr *)((caddr_t)sa + sa->sa_len); #endif } - /* - * Now if there was a port mentioned, assure that the first address - * has that port to make sure it fails or succeeds correctly. - */ - if (sport) { - sin = (struct sockaddr_in *)sa; - sin->sin_port = sport; - } argsz = sizeof(struct sctp_getaddresses) + sizeof(struct sockaddr_storage); if ((gaddrs = (struct sctp_getaddresses *)malloc(argsz)) == NULL) { errno = ENOMEM; return (-1); } sa = addrs; for (i = 0; i < addrcnt; i++) { @@ -2467,32 +2468,54 @@ usrsctp_bindx(struct socket *so, struct sa_len = sizeof(struct sockaddr_in6); break; #endif default: sa_len = 0; break; } memcpy(gaddrs->addr, sa, sa_len); + /* + * Now, if there was a port mentioned, assure that the + * first address has that port to make sure it fails or + * succeeds correctly. + */ + if ((i == 0) && (sport != 0)) { + switch (gaddrs->addr->sa_family) { +#ifdef INET + case AF_INET: + sin = (struct sockaddr_in *)gaddrs->addr; + sin->sin_port = sport; + break; +#endif +#ifdef INET6 + case AF_INET6: + sin6 = (struct sockaddr_in6 *)gaddrs->addr; + sin6->sin6_port = sport; + break; +#endif + } + } if (usrsctp_setsockopt(so, IPPROTO_SCTP, flags, gaddrs, (socklen_t)argsz) != 0) { free(gaddrs); return (-1); } sa = (struct sockaddr *)((caddr_t)sa + sa_len); #endif } free(gaddrs); return (0); } int usrsctp_connectx(struct socket *so, const struct sockaddr *addrs, int addrcnt, sctp_assoc_t *id) { +#if defined(INET) || defined(INET6) char buf[SCTP_STACK_BUF_SIZE]; int i, ret, cnt, *aa; char *cpto; const struct sockaddr *at; sctp_assoc_t *p_id; size_t len = sizeof(int); /* validate the address count and list */ @@ -2559,16 +2582,20 @@ usrsctp_connectx(struct socket *so, aa = (int *)buf; *aa = cnt; ret = usrsctp_setsockopt(so, IPPROTO_SCTP, SCTP_CONNECT_X, (void *)buf, (socklen_t)len); if ((ret == 0) && id) { p_id = (sctp_assoc_t *)buf; *id = *p_id; } return (ret); +#else + errno = EINVAL; + return (-1); +#endif } int usrsctp_getpaddrs(struct socket *so, sctp_assoc_t id, struct sockaddr **raddrs) { struct sctp_getaddresses *addrs; struct sockaddr *sa; sctp_assoc_t asoc; @@ -2775,16 +2802,18 @@ sctp_userspace_ip_output(int *result, st if (SCTP_BUF_LEN(m) < len) { if ((m = m_pullup(m, len)) == 0) { SCTP_PRINTF("Can not get the UDP/IP header in the first mbuf.\n"); return; } ip = mtod(m, struct ip *); } udp = (struct udphdr *)(ip + 1); + } else { + udp = NULL; } if (!use_udp_tunneling) { if (ip->ip_src.s_addr == INADDR_ANY) { /* TODO get addr of outgoing interface */ SCTP_PRINTF("Why did the SCTP implementation did not choose a source address?\n"); } /* TODO need to worry about ro->ro_dst as in ip_output? */ @@ -2931,16 +2960,18 @@ void sctp_userspace_ip6_output(int *resu if (SCTP_BUF_LEN(m) < len) { if ((m = m_pullup(m, len)) == 0) { SCTP_PRINTF("Can not get the UDP/IP header in the first mbuf.\n"); return; } ip6 = mtod(m, struct ip6_hdr *); } udp = (struct udphdr *)(ip6 + 1); + } else { + udp = NULL; } if (!use_udp_tunneling) { if (ip6->ip6_src.s6_addr == in6addr_any.s6_addr) { /* TODO get addr of outgoing interface */ SCTP_PRINTF("Why did the SCTP implementation did not choose a source address?\n"); } /* TODO need to worry about ro->ro_dst as in ip_output? */ @@ -3155,16 +3186,18 @@ usrsctp_freedumpbuffer(char *buf) void usrsctp_conninput(void *addr, const void *buffer, size_t length, uint8_t ecn_bits) { struct sockaddr_conn src, dst; struct mbuf *m; struct sctphdr *sh; struct sctp_chunkhdr *ch; + SCTP_STAT_INCR(sctps_recvpackets); + SCTP_STAT_INCR_COUNTER64(sctps_inpackets); memset(&src, 0, sizeof(struct sockaddr_conn)); src.sconn_family = AF_CONN; #ifdef HAVE_SCONN_LEN src.sconn_len = sizeof(struct sockaddr_conn); #endif src.sconn_addr = addr; memset(&dst, 0, sizeof(struct sockaddr_conn)); dst.sconn_family = AF_CONN; @@ -3190,32 +3223,37 @@ usrsctp_conninput(void *addr, const void (struct sockaddr *)&src, (struct sockaddr *)&dst, sh, ch, #if !defined(SCTP_WITH_NO_CSUM) 1, #endif ecn_bits, SCTP_DEFAULT_VRFID, 0); + if (m) { + sctp_m_freem(m); + } return; } #define USRSCTP_SYSCTL_SET_DEF(__field) \ void usrsctp_sysctl_set_ ## __field(uint32_t value) { \ SCTP_BASE_SYSCTL(__field) = value; \ } USRSCTP_SYSCTL_SET_DEF(sctp_sendspace) 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_strict_sacks) +#if !defined(SCTP_WITH_NO_CSUM) USRSCTP_SYSCTL_SET_DEF(sctp_no_csum_on_loopback) +#endif USRSCTP_SYSCTL_SET_DEF(sctp_peer_chunk_oh) USRSCTP_SYSCTL_SET_DEF(sctp_max_burst_default) USRSCTP_SYSCTL_SET_DEF(sctp_max_chunks_on_queue) USRSCTP_SYSCTL_SET_DEF(sctp_hashtblsize) USRSCTP_SYSCTL_SET_DEF(sctp_pcbtblsize) USRSCTP_SYSCTL_SET_DEF(sctp_min_split_point) USRSCTP_SYSCTL_SET_DEF(sctp_chunkscale) USRSCTP_SYSCTL_SET_DEF(sctp_delayed_sack_time_default) @@ -3281,17 +3319,19 @@ uint32_t usrsctp_sysctl_get_ ## __field( } USRSCTP_SYSCTL_GET_DEF(sctp_sendspace) 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_strict_sacks) +#if !defined(SCTP_WITH_NO_CSUM) USRSCTP_SYSCTL_GET_DEF(sctp_no_csum_on_loopback) +#endif USRSCTP_SYSCTL_GET_DEF(sctp_peer_chunk_oh) USRSCTP_SYSCTL_GET_DEF(sctp_max_burst_default) USRSCTP_SYSCTL_GET_DEF(sctp_max_chunks_on_queue) USRSCTP_SYSCTL_GET_DEF(sctp_hashtblsize) USRSCTP_SYSCTL_GET_DEF(sctp_pcbtblsize) USRSCTP_SYSCTL_GET_DEF(sctp_min_split_point) USRSCTP_SYSCTL_GET_DEF(sctp_chunkscale) USRSCTP_SYSCTL_GET_DEF(sctp_delayed_sack_time_default) @@ -3346,8 +3386,12 @@ USRSCTP_SYSCTL_GET_DEF(sctp_rttvar_eqret USRSCTP_SYSCTL_GET_DEF(sctp_steady_step) USRSCTP_SYSCTL_GET_DEF(sctp_use_dccc_ecn) USRSCTP_SYSCTL_GET_DEF(sctp_buffer_splitting) USRSCTP_SYSCTL_GET_DEF(sctp_initial_cwnd) #ifdef SCTP_DEBUG USRSCTP_SYSCTL_GET_DEF(sctp_debug_on) #endif +void usrsctp_get_stat(struct sctpstat *stat) +{ + *stat = SCTP_BASE_STATS; +}
--- a/netwerk/sctp/src/user_socketvar.h +++ b/netwerk/sctp/src/user_socketvar.h @@ -32,48 +32,43 @@ #ifndef _USER_SOCKETVAR_H_ #define _USER_SOCKETVAR_H_ #if defined(__Userspace_os_Darwin) #include <sys/types.h> #include <unistd.h> #endif -#if defined(ANDROID) -/* Android bionic libc is missing some defines in sys/types.h. Pick them - * up elsewhere */ -#include <linux/coda.h> -#endif /* #include <sys/selinfo.h> */ /*__Userspace__ alternative?*/ /* for struct selinfo */ /* #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_Windows) && !defined(__Userspace_os_FreeBSD) +#if !defined(__Userspace_os_DragonFly) && !defined(__Userspace_os_FreeBSD) && !defined(__Userspace_os_NetBSD) && !defined(__Userspace_os_Windows) #include <sys/uio.h> #endif #define SOCK_MAXADDRLEN 255 #if !defined(MSG_NOTIFICATION) #define MSG_NOTIFICATION 0x2000 /* SCTP notification */ #endif #define SCTP_SO_LINGER 0x0001 #define SCTP_SO_ACCEPTCONN 0x0002 #define SS_CANTRCVMORE 0x020 #define SS_CANTSENDMORE 0x010 -#if defined (__Userspace_os_FreeBSD) || defined(__Userspace_os_OpenBSD) || defined(__Userspace_os_Darwin) || 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) #define UIO_MAXIOV 1024 #define ERESTART (-1) #endif -#if !defined(__Userspace_os_Darwin) && !defined(__Userspace_os_OpenBSD) +#if !defined(__Userspace_os_Darwin) && !defined(__Userspace_os_NetBSD) && !defined(__Userspace_os_OpenBSD) enum uio_rw { UIO_READ, UIO_WRITE }; #endif -#if !defined(__Userspace_os_OpenBSD) +#if !defined(__Userspace_os_NetBSD) && !defined(__Userspace_os_OpenBSD) /* Segment flag values. */ enum uio_seg { UIO_USERSPACE, /* from user data space */ UIO_SYSSPACE /* from system space */ }; #endif struct proc { @@ -102,26 +97,24 @@ struct uio { /* * Kernel structure per socket. * Contains send and receive buffer queues, * handle on protocol and pointer to protocol * private data and error information. */ #if defined (__Userspace_os_Windows) #define AF_ROUTE 17 -typedef __int32 u_quad_t; typedef __int32 pid_t; typedef unsigned __int32 uid_t; enum sigType { SIGNAL = 0, BROADCAST = 1, MAX_EVENTS = 2 }; #endif -typedef u_quad_t so_gen_t; /*- * Locking key to struct socket: * (a) constant after allocation, no locking required. * (b) locked by SOCK_LOCK(so). * (c) locked by SOCKBUF_LOCK(&so->so_rcv). * (d) locked by SOCKBUF_LOCK(&so->so_snd). * (e) locked by ACCEPT_LOCK(). @@ -215,17 +208,17 @@ struct socket { #define SB_AUTOSIZE 0x800 /* automatically size socket buffer */ void (*so_upcall)(struct socket *, void *, int); void *so_upcallarg; struct ucred *so_cred; /* (a) user credentials */ struct label *so_label; /* (b) MAC label for socket */ struct label *so_peerlabel; /* (b) cached MAC label for peer */ /* NB: generation count must not be first. */ - so_gen_t so_gencnt; /* (h) generation count */ + uint32_t so_gencnt; /* (h) generation count */ void *so_emuldata; /* (b) private data for emulators */ struct so_accf { struct accept_filter *so_accept_filter; void *so_accept_filter_arg; /* saved filter args */ char *so_accept_filter_str; /* saved user args */ } *so_accf; }; @@ -250,16 +243,17 @@ extern userland_cond_t accept_cond; EnterCriticalSection(&accept_mtx); \ } while (0) #define ACCEPT_UNLOCK() do { \ LeaveCriticalSection(&accept_mtx); \ } while (0) #define ACCEPT_UNLOCK_ASSERT() #else extern userland_mutex_t accept_mtx; +extern userland_cond_t accept_cond; #define ACCEPT_LOCK_ASSERT() KASSERT(pthread_mutex_trylock(&accept_mtx) == EBUSY, ("%s: accept_mtx not locked", __func__)) #define ACCEPT_LOCK() (void)pthread_mutex_lock(&accept_mtx) #define ACCEPT_UNLOCK() (void)pthread_mutex_unlock(&accept_mtx) #define ACCEPT_UNLOCK_ASSERT() do{ \ KASSERT(pthread_mutex_trylock(&accept_mtx) == 0, ("%s: accept_mtx locked", __func__)); \ (void)pthread_mutex_unlock(&accept_mtx); \ } while (0) #endif @@ -738,17 +732,17 @@ void socantsendmore(struct socket *so); (int)((sb)->sb_mbmax - (sb)->sb_mbcnt))) /* do we have to send all at once on a socket? */ #define sosendallatonce(so) \ ((so)->so_proto->pr_flags & PR_ATOMIC) /* can we read something from so? */ #define soreadable(so) \ - ((so)->so_rcv.sb_cc >= (so)->so_rcv.sb_lowat || \ + ((int)((so)->so_rcv.sb_cc) >= (so)->so_rcv.sb_lowat || \ ((so)->so_rcv.sb_state & SBS_CANTRCVMORE) || \ !TAILQ_EMPTY(&(so)->so_comp) || (so)->so_error) #if 0 /* original */ #define PR_CONNREQUIRED 0x04 /* from sys/protosw.h "needed" for sowriteable */ #define sowriteable(so) \ ((sbspace(&(so)->so_snd) >= (so)->so_snd.sb_lowat && \ (((so)->so_state&SS_ISCONNECTED) || \
--- a/netwerk/sctp/src/usrsctp.h +++ b/netwerk/sctp/src/usrsctp.h @@ -32,20 +32,21 @@ #define __USRSCTP_H__ #ifdef __cplusplus extern "C" { #endif #include <sys/types.h> #ifdef _WIN32 +#ifdef _MSC_VER +#pragma warning(disable: 4200) +#endif #include <winsock2.h> #include <ws2tcpip.h> -#include <ws2ipdef.h> -#include <ws2def.h> #else #include <sys/socket.h> #include <netinet/in.h> #endif #ifndef MSG_NOTIFICATION /* This definition MUST be in sync with usrsctplib/user_socketvar.h */ #define MSG_NOTIFICATION 0x2000 @@ -986,17 +987,19 @@ void usrsctp_sysctl_set_ ## __field(uint uint32_t usrsctp_sysctl_get_ ## __field(void); USRSCTP_SYSCTL_DECL(sctp_sendspace) 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_strict_sacks) +#if !defined(SCTP_WITH_NO_CSUM) USRSCTP_SYSCTL_DECL(sctp_no_csum_on_loopback) +#endif USRSCTP_SYSCTL_DECL(sctp_peer_chunk_oh) USRSCTP_SYSCTL_DECL(sctp_max_burst_default) USRSCTP_SYSCTL_DECL(sctp_max_chunks_on_queue) USRSCTP_SYSCTL_DECL(sctp_hashtblsize) USRSCTP_SYSCTL_DECL(sctp_pcbtblsize) USRSCTP_SYSCTL_DECL(sctp_min_split_point) USRSCTP_SYSCTL_DECL(sctp_chunkscale) USRSCTP_SYSCTL_DECL(sctp_delayed_sack_time_default) @@ -1011,16 +1014,17 @@ USRSCTP_SYSCTL_DECL(sctp_rto_max_default USRSCTP_SYSCTL_DECL(sctp_rto_min_default) USRSCTP_SYSCTL_DECL(sctp_rto_initial_default) USRSCTP_SYSCTL_DECL(sctp_init_rto_max_default) USRSCTP_SYSCTL_DECL(sctp_valid_cookie_life_default) USRSCTP_SYSCTL_DECL(sctp_init_rtx_max_default) USRSCTP_SYSCTL_DECL(sctp_assoc_rtx_max_default) USRSCTP_SYSCTL_DECL(sctp_path_rtx_max_default) USRSCTP_SYSCTL_DECL(sctp_add_more_threshold) +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) @@ -1056,12 +1060,172 @@ USRSCTP_SYSCTL_DECL(sctp_initial_cwnd) USRSCTP_SYSCTL_DECL(sctp_debug_on) /* More specific values can be found in sctp_constants, but * are not considered to be part of the API. */ #define SCTP_DEBUG_NONE 0x00000000 #define SCTP_DEBUG_ALL 0xffffffff #endif #undef USRSCTP_SYSCTL_DECL +struct sctp_timeval { + uint32_t tv_sec; + uint32_t tv_usec; +}; + +struct sctpstat { + struct sctp_timeval sctps_discontinuitytime; /* sctpStats 18 (TimeStamp) */ + /* MIB according to RFC 3873 */ + uint32_t sctps_currestab; /* sctpStats 1 (Gauge32) */ + uint32_t sctps_activeestab; /* sctpStats 2 (Counter32) */ + uint32_t sctps_restartestab; + uint32_t sctps_collisionestab; + uint32_t sctps_passiveestab; /* sctpStats 3 (Counter32) */ + uint32_t sctps_aborted; /* sctpStats 4 (Counter32) */ + uint32_t sctps_shutdown; /* sctpStats 5 (Counter32) */ + uint32_t sctps_outoftheblue; /* sctpStats 6 (Counter32) */ + uint32_t sctps_checksumerrors; /* sctpStats 7 (Counter32) */ + uint32_t sctps_outcontrolchunks; /* sctpStats 8 (Counter64) */ + uint32_t sctps_outorderchunks; /* sctpStats 9 (Counter64) */ + uint32_t sctps_outunorderchunks; /* sctpStats 10 (Counter64) */ + uint32_t sctps_incontrolchunks; /* sctpStats 11 (Counter64) */ + uint32_t sctps_inorderchunks; /* sctpStats 12 (Counter64) */ + uint32_t sctps_inunorderchunks; /* sctpStats 13 (Counter64) */ + uint32_t sctps_fragusrmsgs; /* sctpStats 14 (Counter64) */ + uint32_t sctps_reasmusrmsgs; /* sctpStats 15 (Counter64) */ + uint32_t sctps_outpackets; /* sctpStats 16 (Counter64) */ + uint32_t sctps_inpackets; /* sctpStats 17 (Counter64) */ + + /* input statistics: */ + uint32_t sctps_recvpackets; /* total input packets */ + uint32_t sctps_recvdatagrams; /* total input datagrams */ + uint32_t sctps_recvpktwithdata; /* total packets that had data */ + uint32_t sctps_recvsacks; /* total input SACK chunks */ + uint32_t sctps_recvdata; /* total input DATA chunks */ + uint32_t sctps_recvdupdata; /* total input duplicate DATA chunks */ + uint32_t sctps_recvheartbeat; /* total input HB chunks */ + uint32_t sctps_recvheartbeatack; /* total input HB-ACK chunks */ + uint32_t sctps_recvecne; /* total input ECNE chunks */ + uint32_t sctps_recvauth; /* total input AUTH chunks */ + uint32_t sctps_recvauthmissing; /* total input chunks missing AUTH */ + uint32_t sctps_recvivalhmacid; /* total number of invalid HMAC ids received */ + uint32_t sctps_recvivalkeyid; /* total number of invalid secret ids received */ + uint32_t sctps_recvauthfailed; /* total number of auth failed */ + uint32_t sctps_recvexpress; /* total fast path receives all one chunk */ + uint32_t sctps_recvexpressm; /* total fast path multi-part data */ + uint32_t sctps_recvnocrc; + uint32_t sctps_recvswcrc; + uint32_t sctps_recvhwcrc; + + /* output statistics: */ + uint32_t sctps_sendpackets; /* total output packets */ + uint32_t sctps_sendsacks; /* total output SACKs */ + uint32_t sctps_senddata; /* total output DATA chunks */ + uint32_t sctps_sendretransdata; /* total output retransmitted DATA chunks */ + uint32_t sctps_sendfastretrans; /* total output fast retransmitted DATA chunks */ + uint32_t sctps_sendmultfastretrans; /* total FR's that happened more than once + * to same chunk (u-del multi-fr algo). + */ + uint32_t sctps_sendheartbeat; /* total output HB chunks */ + uint32_t sctps_sendecne; /* total output ECNE chunks */ + uint32_t sctps_sendauth; /* total output AUTH chunks FIXME */ + uint32_t sctps_senderrors; /* ip_output error counter */ + uint32_t sctps_sendnocrc; + uint32_t sctps_sendswcrc; + uint32_t sctps_sendhwcrc; + /* PCKDROPREP statistics: */ + uint32_t sctps_pdrpfmbox; /* Packet drop from middle box */ + uint32_t sctps_pdrpfehos; /* P-drop from end host */ + uint32_t sctps_pdrpmbda; /* P-drops with data */ + uint32_t sctps_pdrpmbct; /* P-drops, non-data, non-endhost */ + uint32_t sctps_pdrpbwrpt; /* P-drop, non-endhost, bandwidth rep only */ + uint32_t sctps_pdrpcrupt; /* P-drop, not enough for chunk header */ + uint32_t sctps_pdrpnedat; /* P-drop, not enough data to confirm */ + uint32_t sctps_pdrppdbrk; /* P-drop, where process_chunk_drop said break */ + uint32_t sctps_pdrptsnnf; /* P-drop, could not find TSN */ + uint32_t sctps_pdrpdnfnd; /* P-drop, attempt reverse TSN lookup */ + uint32_t sctps_pdrpdiwnp; /* P-drop, e-host confirms zero-rwnd */ + uint32_t sctps_pdrpdizrw; /* P-drop, midbox confirms no space */ + uint32_t sctps_pdrpbadd; /* P-drop, data did not match TSN */ + uint32_t sctps_pdrpmark; /* P-drop, TSN's marked for Fast Retran */ + /* timeouts */ + uint32_t sctps_timoiterator; /* Number of iterator timers that fired */ + uint32_t sctps_timodata; /* Number of T3 data time outs */ + uint32_t sctps_timowindowprobe; /* Number of window probe (T3) timers that fired */ + uint32_t sctps_timoinit; /* Number of INIT timers that fired */ + uint32_t sctps_timosack; /* Number of sack timers that fired */ + uint32_t sctps_timoshutdown; /* Number of shutdown timers that fired */ + uint32_t sctps_timoheartbeat; /* Number of heartbeat timers that fired */ + uint32_t sctps_timocookie; /* Number of times a cookie timeout fired */ + uint32_t sctps_timosecret; /* Number of times an endpoint changed its cookie secret*/ + uint32_t sctps_timopathmtu; /* Number of PMTU timers that fired */ + uint32_t sctps_timoshutdownack; /* Number of shutdown ack timers that fired */ + uint32_t sctps_timoshutdownguard; /* Number of shutdown guard timers that fired */ + uint32_t sctps_timostrmrst; /* Number of stream reset timers that fired */ + uint32_t sctps_timoearlyfr; /* Number of early FR timers that fired */ + uint32_t sctps_timoasconf; /* Number of times an asconf timer fired */ + uint32_t sctps_timodelprim; /* Number of times a prim_deleted timer fired */ + uint32_t sctps_timoautoclose; /* Number of times auto close timer fired */ + uint32_t sctps_timoassockill; /* Number of asoc free timers expired */ + uint32_t sctps_timoinpkill; /* Number of inp free timers expired */ + /* former early FR counters */ + uint32_t sctps_spare[11]; + /* others */ + uint32_t sctps_hdrops; /* packet shorter than header */ + uint32_t sctps_badsum; /* checksum error */ + uint32_t sctps_noport; /* no endpoint for port */ + uint32_t sctps_badvtag; /* bad v-tag */ + uint32_t sctps_badsid; /* bad SID */ + uint32_t sctps_nomem; /* no memory */ + uint32_t sctps_fastretransinrtt; /* number of multiple FR in a RTT window */ + uint32_t sctps_markedretrans; + uint32_t sctps_naglesent; /* nagle allowed sending */ + uint32_t sctps_naglequeued; /* nagle doesn't allow sending */ + uint32_t sctps_maxburstqueued; /* max burst doesn't allow sending */ + uint32_t sctps_ifnomemqueued; /* look ahead tells us no memory in + * interface ring buffer OR we had a + * send error and are queuing one send. + */ + uint32_t sctps_windowprobed; /* total number of window probes sent */ + uint32_t sctps_lowlevelerr; /* total times an output error causes us + * to clamp down on next user send. + */ + uint32_t sctps_lowlevelerrusr; /* total times sctp_senderrors were caused from + * a user send from a user invoked send not + * a sack response + */ + uint32_t sctps_datadropchklmt; /* Number of in data drops due to chunk limit reached */ + uint32_t sctps_datadroprwnd; /* Number of in data drops due to rwnd limit reached */ + uint32_t sctps_ecnereducedcwnd; /* Number of times a ECN reduced the cwnd */ + uint32_t sctps_vtagexpress; /* Used express lookup via vtag */ + uint32_t sctps_vtagbogus; /* Collision in express lookup. */ + uint32_t sctps_primary_randry; /* Number of times the sender ran dry of user data on primary */ + uint32_t sctps_cmt_randry; /* Same for above */ + uint32_t sctps_slowpath_sack; /* Sacks the slow way */ + uint32_t sctps_wu_sacks_sent; /* Window Update only sacks sent */ + uint32_t sctps_sends_with_flags; /* number of sends with sinfo_flags !=0 */ + uint32_t sctps_sends_with_unord; /* number of unordered sends */ + uint32_t sctps_sends_with_eof; /* number of sends with EOF flag set */ + uint32_t sctps_sends_with_abort; /* number of sends with ABORT flag set */ + uint32_t sctps_protocol_drain_calls;/* number of times protocol drain called */ + uint32_t sctps_protocol_drains_done;/* number of times we did a protocol drain */ + uint32_t sctps_read_peeks; /* Number of times recv was called with peek */ + uint32_t sctps_cached_chk; /* Number of cached chunks used */ + uint32_t sctps_cached_strmoq; /* Number of cached stream oq's used */ + uint32_t sctps_left_abandon; /* Number of unread messages abandoned by close */ + uint32_t sctps_send_burst_avoid; /* Unused */ + uint32_t sctps_send_cwnd_avoid; /* Send cwnd full avoidance, already max burst inflight to net */ + uint32_t sctps_fwdtsn_map_over; /* number of map array over-runs via fwd-tsn's */ + uint32_t sctps_queue_upd_ecne; /* Number of times we queued or updated an ECN chunk on send queue */ + uint32_t sctps_reserved[31]; /* Future ABI compat - remove int's from here when adding new */ +}; + +void +usrsctp_get_stat(struct sctpstat *); + +#ifdef _WIN32 +#ifdef _MSC_VER +#pragma warning(default: 4200) +#endif +#endif #ifdef __cplusplus } #endif #endif