diff options
author | Primiano Tucci <primiano@google.com> | 2014-09-30 14:46:36 +0100 |
---|---|---|
committer | Primiano Tucci <primiano@google.com> | 2014-09-30 14:46:36 +0100 |
commit | 6306c865a9a058a72d461702e959cd853f9f134d (patch) | |
tree | ccbf50fa007be0752f9d1ada900d8cfc01698021 | |
parent | ed9a6fb519aa7606cab965b2c4218756e849ddb6 (diff) | |
parent | 793f45e9442f232795b0a33a22de234710c06613 (diff) | |
download | usrsctplib-lollipop-mr1-release.tar.gz |
Merge from Chromium at DEPS revision 267aeeb8d85candroid-cts-5.1_r9android-cts-5.1_r8android-cts-5.1_r7android-cts-5.1_r6android-cts-5.1_r5android-cts-5.1_r4android-cts-5.1_r3android-cts-5.1_r28android-cts-5.1_r27android-cts-5.1_r26android-cts-5.1_r25android-cts-5.1_r24android-cts-5.1_r23android-cts-5.1_r22android-cts-5.1_r21android-cts-5.1_r20android-cts-5.1_r2android-cts-5.1_r19android-cts-5.1_r18android-cts-5.1_r17android-cts-5.1_r16android-cts-5.1_r15android-cts-5.1_r14android-cts-5.1_r13android-cts-5.1_r10android-cts-5.1_r1android-5.1.1_r9android-5.1.1_r8android-5.1.1_r7android-5.1.1_r6android-5.1.1_r5android-5.1.1_r4android-5.1.1_r38android-5.1.1_r37android-5.1.1_r36android-5.1.1_r35android-5.1.1_r34android-5.1.1_r33android-5.1.1_r30android-5.1.1_r3android-5.1.1_r29android-5.1.1_r28android-5.1.1_r26android-5.1.1_r25android-5.1.1_r24android-5.1.1_r23android-5.1.1_r22android-5.1.1_r20android-5.1.1_r2android-5.1.1_r19android-5.1.1_r18android-5.1.1_r17android-5.1.1_r16android-5.1.1_r15android-5.1.1_r14android-5.1.1_r13android-5.1.1_r12android-5.1.1_r10android-5.1.1_r1android-5.1.0_r5android-5.1.0_r4android-5.1.0_r3android-5.1.0_r1lollipop-mr1-wfc-releaselollipop-mr1-releaselollipop-mr1-fi-releaselollipop-mr1-devlollipop-mr1-cts-release
This commit was generated by merge_to_master.py.
Change-Id: Id2579b1aabf6c5e804383e7c1fc9fb39de3dad8d
-rwxr-xr-x | netinet/sctp.h | 11 | ||||
-rwxr-xr-x | netinet/sctp_asconf.c | 140 | ||||
-rwxr-xr-x | netinet/sctp_auth.c | 29 | ||||
-rwxr-xr-x | netinet/sctp_auth.h | 3 | ||||
-rwxr-xr-x | netinet/sctp_constants.h | 35 | ||||
-rwxr-xr-x | netinet/sctp_header.h | 8 | ||||
-rwxr-xr-x | netinet/sctp_indata.c | 33 | ||||
-rwxr-xr-x | netinet/sctp_input.c | 267 | ||||
-rwxr-xr-x | netinet/sctp_output.c | 603 | ||||
-rwxr-xr-x | netinet/sctp_pcb.c | 211 | ||||
-rwxr-xr-x | netinet/sctp_pcb.h | 12 | ||||
-rwxr-xr-x | netinet/sctp_peeloff.c | 18 | ||||
-rwxr-xr-x | netinet/sctp_structs.h | 45 | ||||
-rwxr-xr-x | netinet/sctp_sysctl.c | 1179 | ||||
-rwxr-xr-x | netinet/sctp_sysctl.h | 82 | ||||
-rwxr-xr-x | netinet/sctp_timer.c | 26 | ||||
-rwxr-xr-x | netinet/sctp_uio.h | 24 | ||||
-rwxr-xr-x | netinet/sctp_usrreq.c | 512 | ||||
-rwxr-xr-x | netinet/sctp_var.h | 80 | ||||
-rwxr-xr-x | netinet/sctputil.c | 188 | ||||
-rwxr-xr-x | netinet/sctputil.h | 32 | ||||
-rw-r--r-- | netinet6/sctp6_usrreq.c | 16 | ||||
-rwxr-xr-x | user_socket.c | 19 | ||||
-rw-r--r-- | usrsctp.h | 11 |
24 files changed, 2063 insertions, 1521 deletions
diff --git a/netinet/sctp.h b/netinet/sctp.h index b4a1fe9..a2ab878 100755 --- a/netinet/sctp.h +++ b/netinet/sctp.h @@ -32,7 +32,7 @@ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp.h 264679 2014-04-19 19:21:06Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp.h 269945 2014-08-13 15:50:16Z tuexen $"); #endif #ifndef _NETINET_SCTP_H_ @@ -131,6 +131,13 @@ struct sctp_paramhdr { #define SCTP_DEFAULT_PRINFO 0x00000022 #define SCTP_PEER_ADDR_THLDS 0x00000023 #define SCTP_REMOTE_UDP_ENCAPS_PORT 0x00000024 +#define SCTP_ECN_SUPPORTED 0x00000025 +#define SCTP_PR_SUPPORTED 0x00000026 +#define SCTP_AUTH_SUPPORTED 0x00000027 +#define SCTP_ASCONF_SUPPORTED 0x00000028 +#define SCTP_RECONFIG_SUPPORTED 0x00000029 +#define SCTP_NRSACK_SUPPORTED 0x00000030 +#define SCTP_PKTDROP_SUPPORTED 0x00000031 /* * read-only options @@ -143,6 +150,8 @@ struct sctp_paramhdr { #define SCTP_GET_ASSOC_NUMBER 0x00000104 /* ro */ #define SCTP_GET_ASSOC_ID_LIST 0x00000105 /* ro */ #define SCTP_TIMEOUTS 0x00000106 +#define SCTP_PR_STREAM_STATUS 0x00000107 +#define SCTP_PR_ASSOC_STATUS 0x00000108 /* * user socket options: BSD implementation specific diff --git a/netinet/sctp_asconf.c b/netinet/sctp_asconf.c index 0f35ae1..a0d5cee 100755 --- a/netinet/sctp_asconf.c +++ b/netinet/sctp_asconf.c @@ -32,7 +32,7 @@ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_asconf.c 267674 2014-06-20 13:26:49Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp_asconf.c 271228 2014-09-07 17:07:19Z tuexen $"); #endif #include <netinet/sctp_os.h> @@ -153,7 +153,7 @@ sctp_process_asconf_add_ip(struct sockaddr *src, struct sctp_asconf_paramhdr *ap { struct sctp_nets *net; struct mbuf *m_reply = NULL; - struct sockaddr_storage sa_store; + union sctp_sockstore store; struct sctp_paramhdr *ph; uint16_t param_type, aparam_length; #if defined(INET) || defined(INET6) @@ -177,7 +177,7 @@ sctp_process_asconf_add_ip(struct sockaddr *src, struct sctp_asconf_paramhdr *ap #if defined(INET) || defined(INET6) param_length = ntohs(ph->param_length); #endif - sa = (struct sockaddr *)&sa_store; + sa = &store.sa; switch (param_type) { #ifdef INET case SCTP_IPV4_ADDRESS: @@ -186,7 +186,7 @@ sctp_process_asconf_add_ip(struct sockaddr *src, struct sctp_asconf_paramhdr *ap return (NULL); } v4addr = (struct sctp_ipv4addr_param *)ph; - sin = (struct sockaddr_in *)&sa_store; + sin = &store.sin; bzero(sin, sizeof(*sin)); sin->sin_family = AF_INET; #ifdef HAVE_SIN_LEN @@ -211,7 +211,7 @@ sctp_process_asconf_add_ip(struct sockaddr *src, struct sctp_asconf_paramhdr *ap return (NULL); } v6addr = (struct sctp_ipv6addr_param *)ph; - sin6 = (struct sockaddr_in6 *)&sa_store; + sin6 = &store.sin6; bzero(sin6, sizeof(*sin6)); sin6->sin6_family = AF_INET6; #ifdef HAVE_SIN6_LEN @@ -307,7 +307,7 @@ sctp_process_asconf_delete_ip(struct sockaddr *src, struct sctp_tcb *stcb, int response_required) { struct mbuf *m_reply = NULL; - struct sockaddr_storage sa_store; + union sctp_sockstore store; struct sctp_paramhdr *ph; uint16_t param_type, aparam_length; #if defined(INET) || defined(INET6) @@ -331,7 +331,7 @@ sctp_process_asconf_delete_ip(struct sockaddr *src, #if defined(INET) || defined(INET6) param_length = ntohs(ph->param_length); #endif - sa = (struct sockaddr *)&sa_store; + sa = &store.sa; switch (param_type) { #ifdef INET case SCTP_IPV4_ADDRESS: @@ -340,7 +340,7 @@ sctp_process_asconf_delete_ip(struct sockaddr *src, return (NULL); } v4addr = (struct sctp_ipv4addr_param *)ph; - sin = (struct sockaddr_in *)&sa_store; + sin = &store.sin; bzero(sin, sizeof(*sin)); sin->sin_family = AF_INET; #ifdef HAVE_SIN_LEN @@ -362,7 +362,7 @@ sctp_process_asconf_delete_ip(struct sockaddr *src, return (NULL); } v6addr = (struct sctp_ipv6addr_param *)ph; - sin6 = (struct sockaddr_in6 *)&sa_store; + sin6 = &store.sin6; bzero(sin6, sizeof(*sin6)); sin6->sin6_family = AF_INET6; #ifdef HAVE_SIN6_LEN @@ -429,7 +429,7 @@ sctp_process_asconf_delete_ip(struct sockaddr *src, aparam_length); } else { if (response_required) { - m_reply = sctp_asconf_success_response(aph->correlation_id); + m_reply = sctp_asconf_success_response(aph->correlation_id); } /* notify upper layer */ sctp_ulp_notify(SCTP_NOTIFY_ASCONF_DELETE_IP, stcb, 0, sa, SCTP_SO_NOT_LOCKED); @@ -443,7 +443,7 @@ sctp_process_asconf_set_primary(struct sockaddr *src, struct sctp_tcb *stcb, int response_required) { struct mbuf *m_reply = NULL; - struct sockaddr_storage sa_store; + union sctp_sockstore store; struct sctp_paramhdr *ph; uint16_t param_type, aparam_length; #if defined(INET) || defined(INET6) @@ -466,7 +466,7 @@ sctp_process_asconf_set_primary(struct sockaddr *src, #if defined(INET) || defined(INET6) param_length = ntohs(ph->param_length); #endif - sa = (struct sockaddr *)&sa_store; + sa = &store.sa; switch (param_type) { #ifdef INET case SCTP_IPV4_ADDRESS: @@ -475,7 +475,7 @@ sctp_process_asconf_set_primary(struct sockaddr *src, return (NULL); } v4addr = (struct sctp_ipv4addr_param *)ph; - sin = (struct sockaddr_in *)&sa_store; + sin = &store.sin; bzero(sin, sizeof(*sin)); sin->sin_family = AF_INET; #ifdef HAVE_SIN_LEN @@ -495,7 +495,7 @@ sctp_process_asconf_set_primary(struct sockaddr *src, return (NULL); } v6addr = (struct sctp_ipv6addr_param *)ph; - sin6 = (struct sockaddr_in6 *)&sa_store; + sin6 = &store.sin6; bzero(sin6, sizeof(*sin6)); sin6->sin6_family = AF_INET6; #ifdef HAVE_SIN6_LEN @@ -552,11 +552,11 @@ sctp_process_asconf_set_primary(struct sockaddr *src, are transmitted to the new primary destination. (by micchie) */ if ((sctp_is_mobility_feature_on(stcb->sctp_ep, - SCTP_MOBILITY_BASE) || + SCTP_MOBILITY_BASE) || sctp_is_mobility_feature_on(stcb->sctp_ep, - SCTP_MOBILITY_FASTHANDOFF)) && + SCTP_MOBILITY_FASTHANDOFF)) && sctp_is_mobility_feature_on(stcb->sctp_ep, - SCTP_MOBILITY_PRIM_DELETED) && + SCTP_MOBILITY_PRIM_DELETED) && (stcb->asoc.primary_destination->dest_state & SCTP_ADDR_UNCONFIRMED) == 0) { @@ -731,13 +731,11 @@ sctp_handle_asconf(struct mbuf *m, unsigned int offset, } switch (param_type) { case SCTP_ADD_IP_ADDRESS: - asoc->peer_supports_asconf = 1; m_result = sctp_process_asconf_add_ip(src, aph, stcb, (cnt < SCTP_BASE_SYSCTL(sctp_hb_maxburst)), error); cnt++; break; case SCTP_DEL_IP_ADDRESS: - asoc->peer_supports_asconf = 1; m_result = sctp_process_asconf_delete_ip(src, aph, stcb, error); break; @@ -745,7 +743,6 @@ sctp_handle_asconf(struct mbuf *m, unsigned int offset, /* not valid in an ASCONF chunk */ break; case SCTP_SET_PRIM_ADDR: - asoc->peer_supports_asconf = 1; m_result = sctp_process_asconf_set_primary(src, aph, stcb, error); break; @@ -936,8 +933,6 @@ sctp_addr_match(struct sctp_paramhdr *ph, struct sockaddr *sa) void sctp_asconf_cleanup(struct sctp_tcb *stcb, struct sctp_nets *net) { - /* mark peer as ASCONF incapable */ - stcb->asoc.peer_supports_asconf = 0; /* * clear out any existing asconfs going out */ @@ -1099,7 +1094,7 @@ sctp_path_check_and_react(struct sctp_tcb *stcb, struct sctp_ifa *newifa) } /* Retransmit unacknowledged DATA chunks immediately */ if (sctp_is_mobility_feature_on(stcb->sctp_ep, - SCTP_MOBILITY_FASTHANDOFF)) { + SCTP_MOBILITY_FASTHANDOFF)) { sctp_net_immediate_retrans(stcb, net); } /* also, SET PRIMARY is maybe already sent */ @@ -1157,7 +1152,7 @@ sctp_path_check_and_react(struct sctp_tcb *stcb, struct sctp_ifa *newifa) continue; /* Retransmit unacknowledged DATA chunks immediately */ if (sctp_is_mobility_feature_on(stcb->sctp_ep, - SCTP_MOBILITY_FASTHANDOFF)) { + SCTP_MOBILITY_FASTHANDOFF)) { sctp_net_immediate_retrans(stcb, net); } /* Send SET PRIMARY for this new address */ @@ -1193,9 +1188,9 @@ sctp_asconf_addr_mgmt_ack(struct sctp_tcb *stcb, struct sctp_ifa *addr, uint32_t #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Userspace__) if (sctp_is_mobility_feature_on(stcb->sctp_ep, - SCTP_MOBILITY_BASE) || + SCTP_MOBILITY_BASE) || sctp_is_mobility_feature_on(stcb->sctp_ep, - SCTP_MOBILITY_FASTHANDOFF)) { + SCTP_MOBILITY_FASTHANDOFF)) { sctp_path_check_and_react(stcb, addr); return; } @@ -1281,7 +1276,7 @@ sctp_asconf_queue_mgmt(struct sctp_tcb *stcb, struct sctp_ifa *ifa, { struct sockaddr_in6 *sin6; - sin6 = (struct sockaddr_in6 *)&ifa->address.sa; + sin6 = &ifa->address.sin6; aa->ap.addrp.ph.param_type = SCTP_IPV6_ADDRESS; aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv6addr_param)); aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) + @@ -1296,7 +1291,7 @@ sctp_asconf_queue_mgmt(struct sctp_tcb *stcb, struct sctp_ifa *ifa, { struct sockaddr_in *sin; - sin = (struct sockaddr_in *)&ifa->address.sa; + sin = &ifa->address.sin; aa->ap.addrp.ph.param_type = SCTP_IPV4_ADDRESS; aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv4addr_param)); aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) + @@ -1348,7 +1343,7 @@ sctp_asconf_queue_add(struct sctp_tcb *stcb, struct sctp_ifa *ifa, int pending_delete_queued = 0; /* see if peer supports ASCONF */ - if (stcb->asoc.peer_supports_asconf == 0) { + if (stcb->asoc.asconf_supported == 0) { return (-1); } @@ -1440,7 +1435,7 @@ sctp_asconf_queue_sa_delete(struct sctp_tcb *stcb, struct sockaddr *sa) return (-1); } /* see if peer supports ASCONF */ - if (stcb->asoc.peer_supports_asconf == 0) { + if (stcb->asoc.asconf_supported == 0) { return (-1); } /* make sure the request isn't already in the queue */ @@ -1560,7 +1555,7 @@ sctp_asconf_find_param(struct sctp_tcb *stcb, uint32_t correlation_id) * notifications based on the error response */ static void -sctp_asconf_process_error(struct sctp_tcb *stcb, +sctp_asconf_process_error(struct sctp_tcb *stcb SCTP_UNUSED, struct sctp_asconf_paramhdr *aph) { struct sctp_error_cause *eh; @@ -1598,10 +1593,7 @@ sctp_asconf_process_error(struct sctp_tcb *stcb, switch (param_type) { case SCTP_ADD_IP_ADDRESS: case SCTP_DEL_IP_ADDRESS: - stcb->asoc.peer_supports_asconf = 0; - break; case SCTP_SET_PRIM_ADDR: - stcb->asoc.peer_supports_asconf = 0; break; default: break; @@ -1637,8 +1629,6 @@ sctp_asconf_process_param_ack(struct sctp_tcb *stcb, SCTPDBG(SCTP_DEBUG_ASCONF1, "process_param_ack: set primary IP address\n"); /* nothing to do... peer may start using this addr */ - if (flag == 0) - stcb->asoc.peer_supports_asconf = 0; break; default: /* should NEVER happen */ @@ -1656,11 +1646,11 @@ sctp_asconf_process_param_ack(struct sctp_tcb *stcb, * cleanup from a bad asconf ack parameter */ static void -sctp_asconf_ack_clear(struct sctp_tcb *stcb) +sctp_asconf_ack_clear(struct sctp_tcb *stcb SCTP_UNUSED) { /* assume peer doesn't really know how to do asconfs */ - stcb->asoc.peer_supports_asconf = 0; /* XXX we could free the pending queue here */ + } void @@ -1950,7 +1940,7 @@ sctp_addr_mgmt_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, { struct sockaddr_in6 *sin6; - sin6 = (struct sockaddr_in6 *)&ifa->address.sin6; + sin6 = &ifa->address.sin6; if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { /* we skip unspecifed addresses */ return; @@ -1983,7 +1973,7 @@ sctp_addr_mgmt_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, SCTP_IPV6_V6ONLY(inp6)) return; - sin = (struct sockaddr_in *)&ifa->address.sa; + sin = &ifa->address.sin; if (sin->sin_addr.s_addr == 0) { /* we skip unspecifed addresses */ return; @@ -2003,7 +1993,7 @@ sctp_addr_mgmt_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, /* queue an asconf for this address add/delete */ if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_DO_ASCONF)) { /* does the peer do asconf? */ - if (stcb->asoc.peer_supports_asconf) { + if (stcb->asoc.asconf_supported) { /* queue an asconf for this addr */ status = sctp_asconf_queue_add(stcb, ifa, type); @@ -2141,7 +2131,7 @@ sctp_asconf_iterator_stcb(struct sctp_inpcb *inp, struct sctp_tcb *stcb, else continue; } - sin6 = (struct sockaddr_in6 *)&ifa->address.sin6; + sin6 = &ifa->address.sin6; if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { /* we skip unspecifed addresses */ continue; @@ -2177,7 +2167,7 @@ sctp_asconf_iterator_stcb(struct sctp_inpcb *inp, struct sctp_tcb *stcb, SCTP_IPV6_V6ONLY(inp6)) continue; - sin = (struct sockaddr_in *)&ifa->address.sa; + sin = &ifa->address.sin; if (sin->sin_addr.s_addr == 0) { /* we skip unspecifed addresses */ continue; @@ -2257,7 +2247,7 @@ sctp_asconf_iterator_stcb(struct sctp_inpcb *inp, struct sctp_tcb *stcb, } /* queue an asconf for this address add/delete */ if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_DO_ASCONF) && - stcb->asoc.peer_supports_asconf) { + stcb->asoc.asconf_supported == 1) { /* queue an asconf for this addr */ status = sctp_asconf_queue_add(stcb, ifa, type); /* @@ -2308,7 +2298,7 @@ sctp_asconf_iterator_end(void *ptr, uint32_t val SCTP_UNUSED) int32_t sctp_set_primary_ip_address_sa(struct sctp_tcb *stcb, struct sockaddr *sa) { - uint32_t vrf_id; + uint32_t vrf_id; struct sctp_ifa *ifa; /* find the ifa for the desired set primary */ @@ -2496,7 +2486,7 @@ sctp_find_valid_localaddr(struct sctp_tcb *stcb, int addr_locked) if (stcb->asoc.scope.ipv4_addr_legal) { struct sockaddr_in *sin; - sin = (struct sockaddr_in *)&sctp_ifa->address.sa; + sin = &sctp_ifa->address.sin; if (sin->sin_addr.s_addr == 0) { /* skip unspecifed addresses */ continue; @@ -2530,7 +2520,7 @@ sctp_find_valid_localaddr(struct sctp_tcb *stcb, int addr_locked) continue; } - sin6 = (struct sockaddr_in6 *)&sctp_ifa->address.sa; + sin6 = &sctp_ifa->address.sin6; if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { /* we skip unspecifed addresses */ continue; @@ -2798,15 +2788,13 @@ sctp_process_initack_addresses(struct sctp_tcb *stcb, struct mbuf *m, struct sctp_paramhdr tmp_param, *ph; uint16_t plen, ptype; struct sctp_ifa *sctp_ifa; + union sctp_sockstore store; #ifdef INET6 struct sctp_ipv6addr_param addr6_store; - struct sockaddr_in6 sin6; #endif #ifdef INET struct sctp_ipv4addr_param addr4_store; - struct sockaddr_in sin; #endif - struct sockaddr *sa; uint32_t vrf_id; SCTPDBG(SCTP_DEBUG_ASCONF2, "processing init-ack addresses\n"); @@ -2819,25 +2807,6 @@ sctp_process_initack_addresses(struct sctp_tcb *stcb, struct mbuf *m, if ((offset + sizeof(struct sctp_paramhdr)) > length) { return; } - /* init the addresses */ -#ifdef INET6 - bzero(&sin6, sizeof(sin6)); - sin6.sin6_family = AF_INET6; -#ifdef HAVE_SIN6_LEN - sin6.sin6_len = sizeof(sin6); -#endif - sin6.sin6_port = stcb->rport; -#endif - -#ifdef INET - bzero(&sin, sizeof(sin)); - sin.sin_family = AF_INET; -#ifdef HAVE_SIN_LEN - sin.sin_len = sizeof(sin); -#endif - sin.sin_port = stcb->rport; -#endif - /* go through the addresses in the init-ack */ ph = (struct sctp_paramhdr *) sctp_m_getptr(m, offset, sizeof(struct sctp_paramhdr), @@ -2860,9 +2829,13 @@ sctp_process_initack_addresses(struct sctp_tcb *stcb, struct mbuf *m, a6p == NULL) { return; } - memcpy(&sin6.sin6_addr, a6p->addr, - sizeof(struct in6_addr)); - sa = (struct sockaddr *)&sin6; + memset(&store, 0, sizeof(union sctp_sockstore)); + store.sin6.sin6_family = AF_INET6; +#ifdef HAVE_SIN6_LEN + store.sin6.sin6_len = sizeof(struct sockaddr_in6); +#endif + store.sin6.sin6_port = stcb->rport; + memcpy(&store.sin6.sin6_addr, a6p->addr, sizeof(struct in6_addr)); break; } #endif @@ -2879,8 +2852,13 @@ sctp_process_initack_addresses(struct sctp_tcb *stcb, struct mbuf *m, a4p == NULL) { return; } - sin.sin_addr.s_addr = a4p->addr; - sa = (struct sockaddr *)&sin; + memset(&store, 0, sizeof(union sctp_sockstore)); + store.sin.sin_family = AF_INET; +#ifdef HAVE_SIN_LEN + store.sin.sin_len = sizeof(struct sockaddr_in); +#endif + store.sin.sin_port = stcb->rport; + store.sin.sin_addr.s_addr = a4p->addr; break; } #endif @@ -2894,7 +2872,7 @@ sctp_process_initack_addresses(struct sctp_tcb *stcb, struct mbuf *m, } else { vrf_id = SCTP_DEFAULT_VRFID; } - sctp_ifa = sctp_find_ifa_by_addr(sa, vrf_id, + sctp_ifa = sctp_find_ifa_by_addr(&store.sa, vrf_id, SCTP_ADDR_NOT_LOCKED); if (sctp_ifa == NULL) { /* address doesn't exist anymore */ @@ -2903,9 +2881,9 @@ sctp_process_initack_addresses(struct sctp_tcb *stcb, struct mbuf *m, /* are ASCONFs allowed ? */ if ((sctp_is_feature_on(stcb->sctp_ep, SCTP_PCB_FLAGS_DO_ASCONF)) && - stcb->asoc.peer_supports_asconf) { + stcb->asoc.asconf_supported) { /* queue an ASCONF DEL_IP_ADDRESS */ - status = sctp_asconf_queue_sa_delete(stcb, sa); + status = sctp_asconf_queue_sa_delete(stcb, &store.sa); /* * if queued ok, and in correct state, send * out the ASCONF. @@ -2939,7 +2917,7 @@ next_addr: if ((offset + sizeof(struct sctp_paramhdr)) > length) return; ph = (struct sctp_paramhdr *)sctp_m_getptr(m, offset, - sizeof(struct sctp_paramhdr), (uint8_t *) & tmp_param); + sizeof(struct sctp_paramhdr), (uint8_t *)&tmp_param); } /* while */ } @@ -3151,7 +3129,7 @@ sctp_check_address_list_all(struct sctp_tcb *stcb, struct mbuf *m, int offset, switch (sctp_ifa->address.sa.sa_family) { #ifdef INET case AF_INET: - sin = (struct sockaddr_in *)&sctp_ifa->address.sin; + sin = &sctp_ifa->address.sin; #if defined(__FreeBSD__) if (prison_check_ip4(stcb->sctp_ep->ip_inp.inp.inp_cred, &sin->sin_addr) != 0) { @@ -3167,7 +3145,7 @@ sctp_check_address_list_all(struct sctp_tcb *stcb, struct mbuf *m, int offset, #endif #ifdef INET6 case AF_INET6: - sin6 = (struct sockaddr_in6 *)&sctp_ifa->address.sin6; + sin6 = &sctp_ifa->address.sin6; #if defined(__FreeBSD__) if (prison_check_ip6(stcb->sctp_ep->ip_inp.inp.inp_cred, &sin6->sin6_addr) != 0) { @@ -3250,7 +3228,7 @@ sctp_addr_mgmt_ep_sa(struct sctp_inpcb *inp, struct sockaddr *sa, #endif if (sctp_ifap) { ifa = sctp_ifap; - } else if (type == SCTP_ADD_IP_ADDRESS) { + } else if (type == SCTP_ADD_IP_ADDRESS) { /* For an add the address MUST be on the system */ ifa = sctp_find_ifa_by_addr(sa, vrf_id, SCTP_ADDR_NOT_LOCKED); } else if (type == SCTP_DEL_IP_ADDRESS) { diff --git a/netinet/sctp_auth.c b/netinet/sctp_auth.c index dfad97e..00ff978 100755 --- a/netinet/sctp_auth.c +++ b/netinet/sctp_auth.c @@ -32,7 +32,7 @@ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_auth.c 257804 2013-11-07 18:50:11Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp_auth.c 269858 2014-08-12 11:30:16Z tuexen $"); #endif #include <netinet/sctp_os.h> @@ -135,11 +135,6 @@ sctp_auth_delete_chunk(uint8_t chunk, sctp_auth_chklist_t *list) if (list == NULL) return (-1); - /* is chunk restricted? */ - if ((chunk == SCTP_ASCONF) || - (chunk == SCTP_ASCONF_ACK)) { - return (-1); - } if (list->chunks[chunk] == 1) { list->chunks[chunk] = 0; list->num_chunks--; @@ -160,16 +155,6 @@ sctp_auth_get_chklist_size(const sctp_auth_chklist_t *list) } /* - * set the default list of chunks requiring AUTH - */ -void -sctp_auth_set_default_chunks(sctp_auth_chklist_t *list) -{ - (void)sctp_auth_add_chunk(SCTP_ASCONF, list); - (void)sctp_auth_add_chunk(SCTP_ASCONF_ACK, list); -} - -/* * return the current number and list of required chunks caller must * guarantee ptr has space for up to 256 bytes */ @@ -397,9 +382,9 @@ sctp_compare_key(sctp_key_t *key1, sctp_key_t *key2) val1 = (i < (maxlen - key1len)) ? 0 : *(key_1++); val2 = (i < (maxlen - key2len)) ? 0 : *(key_2++); if (val1 > val2) { - return (1); + return (1); } else if (val1 < val2) { - return (-1); + return (-1); } } /* keys are equal value, so check lengths */ @@ -800,7 +785,7 @@ sctp_verify_hmac_param (struct sctp_auth_hmac_algo *hmacs, uint32_t num_hmacs) for (i = 0; i < num_hmacs; i++) { if (ntohs(hmacs->hmac_ids[i]) == SCTP_AUTH_HMAC_ID_SHA1) { - return (0); + return (0); } } return (-1); @@ -1554,7 +1539,7 @@ sctp_auth_get_cookie_params(struct sctp_tcb *stcb, struct mbuf *m, } } if (stcb->asoc.authinfo.random != NULL) - sctp_free_key(stcb->asoc.authinfo.random); + sctp_free_key(stcb->asoc.authinfo.random); stcb->asoc.authinfo.random = new_key; stcb->asoc.authinfo.random_len = random_len; sctp_clear_cachedkeys(stcb, stcb->asoc.authinfo.assoc_keyid); @@ -1818,6 +1803,7 @@ sctp_notify_authentication(struct sctp_tcb *stcb, uint32_t indication, SCTP_BUF_LEN(m_notify) = 0; auth = mtod(m_notify, struct sctp_authkey_event *); + memset(auth, 0, sizeof(struct sctp_authkey_event)); auth->auth_type = SCTP_AUTHENTICATION_EVENT; auth->auth_flags = 0; auth->auth_length = sizeof(*auth); @@ -1975,8 +1961,7 @@ sctp_validate_init_auth_params(struct mbuf *m, int offset, int limit) "SCTP: peer sent chunk list w/o AUTH\n"); return (-1); } - if (!SCTP_BASE_SYSCTL(sctp_asconf_auth_nochk) && peer_supports_asconf && - !peer_supports_auth) { + if (peer_supports_asconf && !peer_supports_auth) { SCTPDBG(SCTP_DEBUG_AUTH1, "SCTP: peer supports ASCONF but not AUTH\n"); return (-1); diff --git a/netinet/sctp_auth.h b/netinet/sctp_auth.h index eeff278..04649ad 100755 --- a/netinet/sctp_auth.h +++ b/netinet/sctp_auth.h @@ -32,7 +32,7 @@ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_auth.h 257804 2013-11-07 18:50:11Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp_auth.h 269858 2014-08-12 11:30:16Z tuexen $"); #endif #ifndef _NETINET_SCTP_AUTH_H_ @@ -116,7 +116,6 @@ extern sctp_auth_chklist_t *sctp_copy_chunklist(sctp_auth_chklist_t *chklist); extern int sctp_auth_add_chunk(uint8_t chunk, sctp_auth_chklist_t *list); extern int sctp_auth_delete_chunk(uint8_t chunk, sctp_auth_chklist_t *list); extern size_t sctp_auth_get_chklist_size(const sctp_auth_chklist_t *list); -extern void sctp_auth_set_default_chunks(sctp_auth_chklist_t *list); extern int sctp_serialize_auth_chunks(const sctp_auth_chklist_t *list, uint8_t *ptr); extern int sctp_pack_auth_chunks(const sctp_auth_chklist_t *list, diff --git a/netinet/sctp_constants.h b/netinet/sctp_constants.h index 12e0c13..ff4874d 100755 --- a/netinet/sctp_constants.h +++ b/netinet/sctp_constants.h @@ -32,7 +32,7 @@ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_constants.h 263921 2014-03-29 20:21:36Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp_constants.h 271204 2014-09-06 19:12:14Z tuexen $"); #endif #ifndef _NETINET_SCTP_CONSTANTS_H_ @@ -272,42 +272,9 @@ extern void getwintimeofday(struct timeval *tv); /* how many addresses per assoc remote and local */ #define SCTP_SCALE_FOR_ADDR 2 -/* default AUTO_ASCONF mode enable(1)/disable(0) value (sysctl) */ -#if defined(__APPLE__) -#if !defined(SCTP_APPLE_AUTO_ASCONF) -#define SCTP_DEFAULT_AUTO_ASCONF 0 -#else -#define SCTP_DEFAULT_AUTO_ASCONF 1 -#endif -#else -#define SCTP_DEFAULT_AUTO_ASCONF 1 -#endif - /* default MULTIPLE_ASCONF mode enable(1)/disable(0) value (sysctl) */ #define SCTP_DEFAULT_MULTIPLE_ASCONFS 0 -/* default MOBILITY_BASE mode enable(1)/disable(0) value (sysctl) */ -#if defined(__APPLE__) -#if !defined(SCTP_APPLE_MOBILITY_BASE) -#define SCTP_DEFAULT_MOBILITY_BASE 0 -#else -#define SCTP_DEFAULT_MOBILITY_BASE 1 -#endif -#else -#define SCTP_DEFAULT_MOBILITY_BASE 0 -#endif - -/* default MOBILITY_FASTHANDOFF mode enable(1)/disable(0) value (sysctl) */ -#if defined(__APPLE__) -#if !defined(SCTP_APPLE_MOBILITY_FASTHANDOFF) -#define SCTP_DEFAULT_MOBILITY_FASTHANDOFF 0 -#else -#define SCTP_DEFAULT_MOBILITY_FASTHANDOFF 1 -#endif -#else -#define SCTP_DEFAULT_MOBILITY_FASTHANDOFF 0 -#endif - /* * Theshold for rwnd updates, we have to read (sb_hiwat >> * SCTP_RWND_HIWAT_SHIFT) before we will look to see if we need to send a diff --git a/netinet/sctp_header.h b/netinet/sctp_header.h index e6f441c..a860c18 100755 --- a/netinet/sctp_header.h +++ b/netinet/sctp_header.h @@ -32,7 +32,7 @@ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_header.h 240198 2012-09-07 13:36:42Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp_header.h 269376 2014-08-01 12:42:37Z tuexen $"); #endif #ifndef _NETINET_SCTP_HEADER_H_ @@ -94,12 +94,6 @@ struct sctp_supported_addr_param { uint16_t addr_type[2]; /* array of supported address types */ } SCTP_PACKED; -/* ECN parameter */ -struct sctp_ecn_supported_param { - struct sctp_paramhdr ph;/* type=SCTP_ECN_CAPABLE */ -} SCTP_PACKED; - - /* heartbeat info parameter */ struct sctp_heartbeat_info_param { struct sctp_paramhdr ph; diff --git a/netinet/sctp_indata.c b/netinet/sctp_indata.c index 125c82f..22a551f 100755 --- a/netinet/sctp_indata.c +++ b/netinet/sctp_indata.c @@ -32,7 +32,7 @@ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_indata.c 264838 2014-04-23 21:20:55Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp_indata.c 269448 2014-08-02 21:36:40Z tuexen $"); #endif #include <netinet/sctp_os.h> @@ -261,6 +261,11 @@ sctp_build_ctl_nchunk(struct sctp_inpcb *inp, struct sctp_sndrcvinfo *sinfo) #else cmh = mtod(ret, struct cmsghdr *); #endif + /* + * Make sure that there is no un-initialized padding between + * the cmsg header and cmsg data and after the cmsg data. + */ + memset(cmh, 0, len); if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVRCVINFO)) { cmh->cmsg_level = IPPROTO_SCTP; cmh->cmsg_len = CMSG_LEN(sizeof(struct sctp_rcvinfo)); @@ -411,7 +416,7 @@ sctp_service_reassembly(struct sctp_tcb *stcb, struct sctp_association *asoc) } /* Now free the address and data */ sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED); - /*sa_ignore FREED_MEMORY*/ + /*sa_ignore FREED_MEMORY*/ } return; } @@ -665,8 +670,8 @@ sctp_queue_data_to_stream(struct sctp_tcb *stcb, struct sctp_association *asoc, * Ok, we did not deliver this guy, find the correct place * to put it on the queue. */ - if (SCTP_TSN_GE(asoc->cumulative_tsn, control->sinfo_tsn)) { - goto protocol_error; + if (SCTP_TSN_GE(asoc->cumulative_tsn, control->sinfo_tsn)) { + goto protocol_error; } if (TAILQ_EMPTY(&strm->inqueue)) { /* Empty queue */ @@ -871,7 +876,7 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, snprintf(msg, sizeof(msg), "Expected B-bit for TSN=%8.8x, SID=%4.4x, SSN=%4.4x", chk->rec.data.TSN_seq, - chk->rec.data.stream_number, + chk->rec.data.stream_number, chk->rec.data.stream_seq); op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_2; @@ -888,7 +893,7 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, snprintf(msg, sizeof(msg), "Didn't expect B-bit for TSN=%8.8x, SID=%4.4x, SSN=%4.4x", chk->rec.data.TSN_seq, - chk->rec.data.stream_number, + chk->rec.data.stream_number, chk->rec.data.stream_seq); op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_3; @@ -2522,7 +2527,7 @@ sctp_process_data(struct mbuf **mm, int iphlen, int *offset, int length, SCTP_BUF_LEN(merr) = sizeof(*phd); SCTP_BUF_NEXT(merr) = SCTP_M_COPYM(m, *offset, chk_length, M_NOWAIT); if (SCTP_BUF_NEXT(merr)) { - if (sctp_pad_lastmbuf(SCTP_BUF_NEXT(merr), SCTP_SIZE32(chk_length) - chk_length, NULL)) { + if (sctp_pad_lastmbuf(SCTP_BUF_NEXT(merr), SCTP_SIZE32(chk_length) - chk_length, NULL) == NULL) { sctp_m_freem(merr); } else { sctp_queue_op_err(stcb, merr); @@ -2973,7 +2978,7 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc, num_dests_sacked++; } } - if (stcb->asoc.peer_supports_prsctp) { + if (stcb->asoc.prsctp_supported) { (void)SCTP_GETTIME_TIMEVAL(&now); } TAILQ_FOREACH(tp1, &asoc->sent_queue, sctp_next) { @@ -2994,7 +2999,7 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc, /* done */ break; } - if (stcb->asoc.peer_supports_prsctp) { + if (stcb->asoc.prsctp_supported) { if ((PR_SCTP_TTL_ENABLED(tp1->flags)) && tp1->sent < SCTP_DATAGRAM_ACKED) { /* Is it expired? */ #ifndef __FreeBSD__ @@ -3247,7 +3252,7 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc, /* remove from the total flight */ sctp_total_flight_decrease(stcb, tp1); - if ((stcb->asoc.peer_supports_prsctp) && + if ((stcb->asoc.prsctp_supported) && (PR_SCTP_RTX_ENABLED(tp1->flags))) { /* Has it been retransmitted tv_sec times? - we store the retran count there. */ if (tp1->snd_count > tp1->rec.data.timetodrop.tv_sec) { @@ -3379,7 +3384,7 @@ sctp_try_advance_peer_ack_point(struct sctp_tcb *stcb, struct timeval now; int now_filled = 0; - if (asoc->peer_supports_prsctp == 0) { + if (asoc->prsctp_supported == 0) { return (NULL); } TAILQ_FOREACH_SAFE(tp1, &asoc->sent_queue, sctp_next, tp2) { @@ -4063,7 +4068,7 @@ again: asoc->advanced_peer_ack_point = cumack; } /* PR-Sctp issues need to be addressed too */ - if ((asoc->peer_supports_prsctp) && (asoc->pr_sctp_cnt > 0)) { + if ((asoc->prsctp_supported) && (asoc->pr_sctp_cnt > 0)) { struct sctp_tmit_chunk *lchk; uint32_t old_adv_peer_ack_point; @@ -4501,7 +4506,7 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup, sctp_free_bufspace(stcb, asoc, tp1, 1); sctp_m_freem(tp1->data); tp1->data = NULL; - if (asoc->peer_supports_prsctp && PR_SCTP_BUF_ENABLED(tp1->flags)) { + if (asoc->prsctp_supported && PR_SCTP_BUF_ENABLED(tp1->flags)) { asoc->sent_queue_cnt_removeable--; } } @@ -4936,7 +4941,7 @@ again: asoc->advanced_peer_ack_point = cum_ack; } /* C2. try to further move advancedPeerAckPoint ahead */ - if ((asoc->peer_supports_prsctp) && (asoc->pr_sctp_cnt > 0)) { + if ((asoc->prsctp_supported) && (asoc->pr_sctp_cnt > 0)) { struct sctp_tmit_chunk *lchk; uint32_t old_adv_peer_ack_point; diff --git a/netinet/sctp_input.c b/netinet/sctp_input.c index df244e8..cb7968f 100755 --- a/netinet/sctp_input.c +++ b/netinet/sctp_input.c @@ -32,7 +32,7 @@ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_input.c 263237 2014-03-16 12:32:16Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp_input.c 271230 2014-09-07 18:05:37Z tuexen $"); #endif #include <netinet/sctp_os.h> @@ -49,7 +49,7 @@ __FBSDID("$FreeBSD: head/sys/netinet/sctp_input.c 263237 2014-03-16 12:32:16Z tu #include <netinet/sctp_bsd_addr.h> #include <netinet/sctp_timer.h> #include <netinet/sctp_crc32.h> -#if defined INET || defined INET6 +#if defined(INET) || defined(INET6) #if !defined(__Userspace_os_Windows) #include <netinet/udp.h> #endif @@ -507,7 +507,7 @@ sctp_process_init_ack(struct mbuf *m, int iphlen, int offset, return (-1); } /* if the peer doesn't support asconf, flush the asconf queue */ - if (asoc->peer_supports_asconf == 0) { + if (asoc->asconf_supported == 0) { struct sctp_asconf_addr *param, *nparam; TAILQ_FOREACH_SAFE(param, &asoc->asconf_queue, next, nparam) { @@ -593,20 +593,11 @@ static void sctp_handle_heartbeat_ack(struct sctp_heartbeat_chunk *cp, struct sctp_tcb *stcb, struct sctp_nets *net) { - struct sockaddr_storage store; + union sctp_sockstore store; struct sctp_nets *r_net, *f_net; struct timeval tv; int req_prim = 0; uint16_t old_error_counter; -#ifdef INET - struct sockaddr_in *sin; -#endif -#ifdef INET6 - struct sockaddr_in6 *sin6; -#endif -#if defined(__Userspace__) - struct sockaddr_conn *sconn; -#endif if (ntohs(cp->ch.chunk_length) != sizeof(struct sctp_heartbeat_chunk)) { /* Invalid length */ @@ -618,14 +609,13 @@ sctp_handle_heartbeat_ack(struct sctp_heartbeat_chunk *cp, #ifdef INET case AF_INET: if (cp->heartbeat.hb_info.addr_len == sizeof(struct sockaddr_in)) { - sin = (struct sockaddr_in *)&store; - sin->sin_family = cp->heartbeat.hb_info.addr_family; + store.sin.sin_family = cp->heartbeat.hb_info.addr_family; #ifdef HAVE_SIN_LEN - sin->sin_len = cp->heartbeat.hb_info.addr_len; + store.sin.sin_len = cp->heartbeat.hb_info.addr_len; #endif - sin->sin_port = stcb->rport; - memcpy(&sin->sin_addr, cp->heartbeat.hb_info.address, - sizeof(sin->sin_addr)); + store.sin.sin_port = stcb->rport; + memcpy(&store.sin.sin_addr, cp->heartbeat.hb_info.address, + sizeof(store.sin.sin_addr)); } else { return; } @@ -634,14 +624,12 @@ sctp_handle_heartbeat_ack(struct sctp_heartbeat_chunk *cp, #ifdef INET6 case AF_INET6: if (cp->heartbeat.hb_info.addr_len == sizeof(struct sockaddr_in6)) { - sin6 = (struct sockaddr_in6 *)&store; - sin6->sin6_family = cp->heartbeat.hb_info.addr_family; + store.sin6.sin6_family = cp->heartbeat.hb_info.addr_family; #ifdef HAVE_SIN6_LEN - sin6->sin6_len = cp->heartbeat.hb_info.addr_len; + store.sin6.sin6_len = cp->heartbeat.hb_info.addr_len; #endif - sin6->sin6_port = stcb->rport; - memcpy(&sin6->sin6_addr, cp->heartbeat.hb_info.address, - sizeof(sin6->sin6_addr)); + store.sin6.sin6_port = stcb->rport; + memcpy(&store.sin6.sin6_addr, cp->heartbeat.hb_info.address, sizeof(struct in6_addr)); } else { return; } @@ -650,14 +638,12 @@ sctp_handle_heartbeat_ack(struct sctp_heartbeat_chunk *cp, #if defined(__Userspace__) case AF_CONN: if (cp->heartbeat.hb_info.addr_len == sizeof(struct sockaddr_conn)) { - sconn = (struct sockaddr_conn *)&store; - sconn->sconn_family = cp->heartbeat.hb_info.addr_family; + store.sconn.sconn_family = cp->heartbeat.hb_info.addr_family; #ifdef HAVE_SCONN_LEN - sconn->sconn_len = cp->heartbeat.hb_info.addr_len; + store.sconn.sconn_len = cp->heartbeat.hb_info.addr_len; #endif - sconn->sconn_port = stcb->rport; - memcpy(&sconn->sconn_addr, cp->heartbeat.hb_info.address, - sizeof(sconn->sconn_addr)); + store.sconn.sconn_port = stcb->rport; + memcpy(&store.sconn.sconn_addr, cp->heartbeat.hb_info.address, sizeof(void *)); } else { return; } @@ -666,7 +652,7 @@ sctp_handle_heartbeat_ack(struct sctp_heartbeat_chunk *cp, default: return; } - r_net = sctp_findnet(stcb, (struct sockaddr *)&store); + r_net = sctp_findnet(stcb, &store.sa); if (r_net == NULL) { SCTPDBG(SCTP_DEBUG_INPUT1, "Huh? I can't find the address I sent it to, discard\n"); return; @@ -730,11 +716,11 @@ sctp_handle_heartbeat_ack(struct sctp_heartbeat_chunk *cp, /* Mobility adaptation */ if (req_prim) { if ((sctp_is_mobility_feature_on(stcb->sctp_ep, - SCTP_MOBILITY_BASE) || - sctp_is_mobility_feature_on(stcb->sctp_ep, - SCTP_MOBILITY_FASTHANDOFF)) && - sctp_is_mobility_feature_on(stcb->sctp_ep, - SCTP_MOBILITY_PRIM_DELETED)) { + SCTP_MOBILITY_BASE) || + sctp_is_mobility_feature_on(stcb->sctp_ep, + SCTP_MOBILITY_FASTHANDOFF)) && + sctp_is_mobility_feature_on(stcb->sctp_ep, + SCTP_MOBILITY_PRIM_DELETED)) { sctp_timer_stop(SCTP_TIMER_TYPE_PRIM_DELETED, stcb->sctp_ep, stcb, NULL, SCTP_FROM_SCTP_TIMER+SCTP_LOC_7); if (sctp_is_mobility_feature_on(stcb->sctp_ep, @@ -796,17 +782,16 @@ sctp_handle_nat_colliding_state(struct sctp_tcb *stcb) static int sctp_handle_nat_missing_state(struct sctp_tcb *stcb, struct sctp_nets *net) - { - /* return 0 means we want you to proceed with the abort - * non-zero means no abort processing - */ - if (stcb->asoc.peer_supports_auth == 0) { - SCTPDBG(SCTP_DEBUG_INPUT2, "sctp_handle_nat_missing_state: Peer does not support AUTH, cannot send an asconf\n"); - return (0); - } - sctp_asconf_send_nat_state_update(stcb, net); - return (1); + /* return 0 means we want you to proceed with the abort + * non-zero means no abort processing + */ + if (stcb->asoc.auth_supported == 0) { + SCTPDBG(SCTP_DEBUG_INPUT2, "sctp_handle_nat_missing_state: Peer does not support AUTH, cannot send an asconf\n"); + return (0); + } + sctp_asconf_send_nat_state_update(stcb, net); + return (1); } @@ -1122,7 +1107,7 @@ sctp_process_unrecog_chunk(struct sctp_tcb *stcb, struct sctp_paramhdr *phdr, sctp_asconf_cleanup(stcb, net); break; case SCTP_FORWARD_CUM_TSN: - stcb->asoc.peer_supports_prsctp = 0; + stcb->asoc.prsctp_supported = 0; break; default: SCTPDBG(SCTP_DEBUG_INPUT2, @@ -1136,6 +1121,7 @@ sctp_process_unrecog_chunk(struct sctp_tcb *stcb, struct sctp_paramhdr *phdr, * Skip past the param header and then we will find the param that caused the * problem. There are a number of param's in a ASCONF OR the prsctp param * these will turn of specific features. + * XXX: Is this the right thing to do? */ static void sctp_process_unrecog_param(struct sctp_tcb *stcb, struct sctp_paramhdr *phdr) @@ -1146,7 +1132,7 @@ sctp_process_unrecog_param(struct sctp_tcb *stcb, struct sctp_paramhdr *phdr) switch (ntohs(pbad->param_type)) { /* pr-sctp draft */ case SCTP_PRSCTP_SUPPORTED: - stcb->asoc.peer_supports_prsctp = 0; + stcb->asoc.prsctp_supported = 0; break; case SCTP_SUPPORTED_CHUNK_EXT: break; @@ -1157,14 +1143,14 @@ sctp_process_unrecog_param(struct sctp_tcb *stcb, struct sctp_paramhdr *phdr) case SCTP_ADD_IP_ADDRESS: case SCTP_DEL_IP_ADDRESS: case SCTP_SET_PRIM_ADDR: - stcb->asoc.peer_supports_asconf = 0; + stcb->asoc.asconf_supported = 0; break; case SCTP_SUCCESS_REPORT: case SCTP_ERROR_CAUSE_IND: SCTPDBG(SCTP_DEBUG_INPUT2, "Huh, the peer does not support success? or error cause?\n"); SCTPDBG(SCTP_DEBUG_INPUT2, "Turning off ASCONF to this strange peer\n"); - stcb->asoc.peer_supports_asconf = 0; + stcb->asoc.asconf_supported = 0; break; default: SCTPDBG(SCTP_DEBUG_INPUT2, @@ -1523,6 +1509,9 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, int retval; int spec_flag = 0; uint32_t how_indx; +#if defined(SCTP_DETAILED_STR_STATS) + int j; +#endif net = *netp; /* I know that the TCB is non-NULL from the caller */ @@ -1605,7 +1594,7 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, return (NULL); } - switch (SCTP_GET_STATE(asoc)) { + switch (SCTP_GET_STATE(asoc)) { case SCTP_STATE_COOKIE_WAIT: case SCTP_STATE_COOKIE_ECHOED: /* @@ -1662,7 +1651,7 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, atomic_add_int(&stcb->asoc.refcnt, -1); if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) { SCTP_SOCKET_UNLOCK(so, 1); - return (NULL); + return (NULL); } #endif soisconnected(stcb->sctp_socket); @@ -1983,6 +1972,15 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, 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; +#if defined(SCTP_DETAILED_STR_STATS) + for (j = 0; j < SCTP_PR_SCTP_MAX + 1; j++) { + asoc->strmout[i].abandoned_sent[j] = 0; + asoc->strmout[i].abandoned_unsent[j] = 0; + } +#else + asoc->strmout[i].abandoned_sent[0] = 0; + asoc->strmout[i].abandoned_unsent[0] = 0; +#endif stcb->asoc.strmout[i].stream_no = i; stcb->asoc.strmout[i].next_sequence_send = 0; stcb->asoc.strmout[i].last_msg_incomplete = 0; @@ -2070,22 +2068,12 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset, struct sctp_tcb *stcb; struct sctp_init_chunk *init_cp, init_buf; struct sctp_init_ack_chunk *initack_cp, initack_buf; - struct sockaddr_storage sa_store; - struct sockaddr *initack_src = (struct sockaddr *)&sa_store; + union sctp_sockstore store; struct sctp_association *asoc; int init_offset, initack_offset, initack_limit; int retval; int error = 0; uint8_t auth_chunk_buf[SCTP_PARAM_BUFFER_SIZE]; -#ifdef INET - struct sockaddr_in *sin; -#endif -#ifdef INET6 - struct sockaddr_in6 *sin6; -#endif -#if defined(__Userspace__) - struct sockaddr_conn *sconn; -#endif #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) struct socket *so; @@ -2325,39 +2313,35 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset, #ifdef INET case SCTP_IPV4_ADDRESS: /* source addr is IPv4 */ - sin = (struct sockaddr_in *)initack_src; - memset(sin, 0, sizeof(*sin)); - sin->sin_family = AF_INET; + memset(&store.sin, 0, sizeof(struct sockaddr_in)); + store.sin.sin_family = AF_INET; #ifdef HAVE_SIN_LEN - sin->sin_len = sizeof(struct sockaddr_in); + store.sin.sin_len = sizeof(struct sockaddr_in); #endif - sin->sin_addr.s_addr = cookie->laddress[0]; + store.sin.sin_addr.s_addr = cookie->laddress[0]; break; #endif #ifdef INET6 case SCTP_IPV6_ADDRESS: /* source addr is IPv6 */ - sin6 = (struct sockaddr_in6 *)initack_src; - memset(sin6, 0, sizeof(*sin6)); - sin6->sin6_family = AF_INET6; + memset(&store.sin6, 0, sizeof(struct sockaddr_in6)); + store.sin6.sin6_family = AF_INET6; #ifdef HAVE_SIN6_LEN - sin6->sin6_len = sizeof(struct sockaddr_in6); + store.sin6.sin6_len = sizeof(struct sockaddr_in6); #endif - sin6->sin6_scope_id = cookie->scope_id; - memcpy(&sin6->sin6_addr, cookie->laddress, - sizeof(sin6->sin6_addr)); + store.sin6.sin6_scope_id = cookie->scope_id; + memcpy(&store.sin6.sin6_addr, cookie->laddress, sizeof(struct in6_addr)); break; #endif #if defined(__Userspace__) case SCTP_CONN_ADDRESS: - /* source addr is IPv4 */ - sconn = (struct sockaddr_conn *)initack_src; - memset(sconn, 0, sizeof(struct sockaddr_conn)); - sconn->sconn_family = AF_CONN; + /* source addr is conn */ + memset(&store.sconn, 0, sizeof(struct sockaddr_conn)); + store.sconn.sconn_family = AF_CONN; #ifdef HAVE_SCONN_LEN - sconn->sconn_len = sizeof(struct sockaddr_conn); + store.sconn.sconn_len = sizeof(struct sockaddr_conn); #endif - memcpy(&sconn->sconn_addr, cookie->laddress, sizeof(void *)); + memcpy(&store.sconn.sconn_addr, cookie->laddress, sizeof(void *)); break; #endif default: @@ -2438,7 +2422,7 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset, sctp_check_address_list(stcb, m, initack_offset + sizeof(struct sctp_init_ack_chunk), initack_limit - (initack_offset + sizeof(struct sctp_init_ack_chunk)), - initack_src, cookie->local_scope, cookie->site_scope, + &store.sa, cookie->local_scope, cookie->site_scope, cookie->ipv4_scope, cookie->loopback_scope); @@ -2840,7 +2824,7 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset, sctp_ulp_notify(notification, *stcb, 0, NULL, SCTP_SO_NOT_LOCKED); if (send_int_conf) { sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_CONFIRMED, - (*stcb), 0, (void *)netl, SCTP_SO_NOT_LOCKED); + (*stcb), 0, (void *)netl, SCTP_SO_NOT_LOCKED); } return (m); } @@ -2918,7 +2902,7 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset, inp->sctp_flags = (SCTP_PCB_FLAGS_TCPTYPE | SCTP_PCB_FLAGS_CONNECTED | SCTP_PCB_FLAGS_IN_TCPPOOL | - SCTP_PCB_FLAGS_UNBOUND | + SCTP_PCB_FLAGS_UNBOUND | (SCTP_PCB_COPY_FLAGS & (*inp_p)->sctp_flags) | SCTP_PCB_FLAGS_DONT_WAKE); inp->sctp_features = (*inp_p)->sctp_features; @@ -2926,7 +2910,13 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset, inp->sctp_socket = so; inp->sctp_frag_point = (*inp_p)->sctp_frag_point; inp->sctp_cmt_on_off = (*inp_p)->sctp_cmt_on_off; - inp->sctp_ecn_enable = (*inp_p)->sctp_ecn_enable; + inp->ecn_supported = (*inp_p)->ecn_supported; + inp->prsctp_supported = (*inp_p)->prsctp_supported; + inp->auth_supported = (*inp_p)->auth_supported; + inp->asconf_supported = (*inp_p)->asconf_supported; + inp->reconfig_supported = (*inp_p)->reconfig_supported; + inp->nrsack_supported = (*inp_p)->nrsack_supported; + inp->pktdrop_supported = (*inp_p)->pktdrop_supported; inp->partial_delivery_point = (*inp_p)->partial_delivery_point; inp->sctp_context = (*inp_p)->sctp_context; inp->local_strreset_support = (*inp_p)->local_strreset_support; @@ -3031,8 +3021,9 @@ sctp_handle_cookie_ack(struct sctp_cookie_ack_chunk *cp SCTP_UNUSED, SCTPDBG(SCTP_DEBUG_INPUT2, "sctp_handle_cookie_ack: handling COOKIE-ACK\n"); - if (stcb == NULL) + if ((stcb == NULL) || (net == NULL)) { return; + } asoc = &stcb->asoc; @@ -3108,7 +3099,7 @@ sctp_handle_cookie_ack(struct sctp_cookie_ack_chunk *cp SCTP_UNUSED, * in flight) */ if ((sctp_is_feature_on(stcb->sctp_ep, SCTP_PCB_FLAGS_DO_ASCONF)) && - (stcb->asoc.peer_supports_asconf) && + (stcb->asoc.asconf_supported == 1) && (!TAILQ_EMPTY(&stcb->asoc.asconf_queue))) { #ifdef SCTP_TIMER_BASED_ASCONF sctp_timer_start(SCTP_TIMER_TYPE_ASCONF, @@ -4570,7 +4561,7 @@ sctp_process_control(struct mbuf *m, int iphlen, int *offset, int length, */ if ((ch->chunk_type == SCTP_AUTHENTICATION) && (stcb == NULL) && - !SCTP_BASE_SYSCTL(sctp_auth_disable)) { + (inp->auth_supported == 1)) { /* save this chunk for later processing */ auth_skipped = 1; auth_offset = *offset; @@ -4842,7 +4833,7 @@ sctp_process_control(struct mbuf *m, int iphlen, int *offset, int length, /* check to see if this chunk required auth, but isn't */ if ((stcb != NULL) && - !SCTP_BASE_SYSCTL(sctp_auth_disable) && + (stcb->asoc.auth_supported == 1) && sctp_auth_is_required_chunk(ch->chunk_type, stcb->asoc.local_auth_chunks) && !stcb->asoc.authenticated) { /* "silently" ignore */ @@ -4897,7 +4888,7 @@ sctp_process_control(struct mbuf *m, int iphlen, int *offset, int length, SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_INIT-ACK\n"); if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) { /* We are not interested anymore */ - if ((stcb) && (stcb->asoc.total_output_queue_size)) { + if ((stcb) && (stcb->asoc.total_output_queue_size)) { ; } else { if (locked_tcb != stcb) { @@ -5051,8 +5042,7 @@ sctp_process_control(struct mbuf *m, int iphlen, int *offset, int length, SCTPDBG(SCTP_DEBUG_INDATA1, "No stcb when processing NR-SACK chunk\n"); break; } - if ((stcb->asoc.sctp_nr_sack_on_off == 0) || - (stcb->asoc.peer_supports_nr_sack == 0)) { + if (stcb->asoc.nrsack_supported == 0) { goto unknown_chunk; } if (chk_length < sizeof(struct sctp_nr_sack_chunk)) { @@ -5367,6 +5357,9 @@ sctp_process_control(struct mbuf *m, int iphlen, int *offset, int length, return (NULL); } if (stcb) { + if (stcb->asoc.ecn_supported == 0) { + goto unknown_chunk; + } if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { sctp_misc_ints(SCTP_THRESHOLD_CLEAR, stcb->asoc.overall_error_count, @@ -5392,6 +5385,9 @@ sctp_process_control(struct mbuf *m, int iphlen, int *offset, int length, return (NULL); } if (stcb) { + if (stcb->asoc.ecn_supported == 0) { + goto unknown_chunk; + } if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { sctp_misc_ints(SCTP_THRESHOLD_CLEAR, stcb->asoc.overall_error_count, @@ -5425,6 +5421,9 @@ sctp_process_control(struct mbuf *m, int iphlen, int *offset, int length, SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_ASCONF\n"); /* He's alive so give him credit */ if (stcb) { + if (stcb->asoc.asconf_supported == 0) { + goto unknown_chunk; + } if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { sctp_misc_ints(SCTP_THRESHOLD_CLEAR, stcb->asoc.overall_error_count, @@ -5449,6 +5448,9 @@ sctp_process_control(struct mbuf *m, int iphlen, int *offset, int length, return (NULL); } if ((stcb) && netp && *netp) { + if (stcb->asoc.asconf_supported == 0) { + goto unknown_chunk; + } /* He's alive so give him credit */ if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { sctp_misc_ints(SCTP_THRESHOLD_CLEAR, @@ -5478,6 +5480,10 @@ sctp_process_control(struct mbuf *m, int iphlen, int *offset, int length, /* He's alive so give him credit */ if (stcb) { int abort_flag = 0; + + if (stcb->asoc.prsctp_supported == 0) { + goto unknown_chunk; + } stcb->asoc.overall_error_count = 0; if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { sctp_misc_ints(SCTP_THRESHOLD_CLEAR, @@ -5532,13 +5538,8 @@ sctp_process_control(struct mbuf *m, int iphlen, int *offset, int length, *offset = length; return (NULL); } - if (stcb->asoc.peer_supports_strreset == 0) { - /* - * hmm, peer should have announced this, but - * we will turn it on since he is sending us - * a stream reset. - */ - stcb->asoc.peer_supports_strreset = 1; + if (stcb->asoc.reconfig_supported == 0) { + goto unknown_chunk; } if (sctp_handle_stream_reset(stcb, m, *offset, ch)) { /* stop processing */ @@ -5560,6 +5561,9 @@ sctp_process_control(struct mbuf *m, int iphlen, int *offset, int length, if (ch && (stcb) && netp && (*netp)) { + if (stcb->asoc.pktdrop_supported == 0) { + goto unknown_chunk; + } sctp_handle_packet_dropped((struct sctp_pktdrop_chunk *)ch, stcb, *netp, min(chk_length, (sizeof(chunk_buf) - 4))); @@ -5567,12 +5571,8 @@ sctp_process_control(struct mbuf *m, int iphlen, int *offset, int length, } break; - case SCTP_AUTHENTICATION: SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_AUTHENTICATION\n"); - if (SCTP_BASE_SYSCTL(sctp_auth_disable)) - goto unknown_chunk; - if (stcb == NULL) { /* save the first AUTH for later processing */ if (auth_skipped == 0) { @@ -5583,6 +5583,9 @@ sctp_process_control(struct mbuf *m, int iphlen, int *offset, int length, /* skip this chunk (temporarily) */ goto next_chunk; } + if (stcb->asoc.auth_supported == 0) { + goto unknown_chunk; + } if ((chk_length < (sizeof(struct sctp_auth_chunk))) || (chk_length > (sizeof(struct sctp_auth_chunk) + SCTP_AUTH_DIGEST_LEN_MAX))) { @@ -5632,7 +5635,7 @@ sctp_process_control(struct mbuf *m, int iphlen, int *offset, int length, SCTP_BUF_LEN(mm) = sizeof(*phd); SCTP_BUF_NEXT(mm) = SCTP_M_COPYM(m, *offset, chk_length, M_NOWAIT); if (SCTP_BUF_NEXT(mm)) { - if (sctp_pad_lastmbuf(SCTP_BUF_NEXT(mm), SCTP_SIZE32(chk_length) - chk_length, NULL)) { + if (sctp_pad_lastmbuf(SCTP_BUF_NEXT(mm), SCTP_SIZE32(chk_length) - chk_length, NULL) == NULL) { sctp_m_freem(mm); } else { #ifdef SCTP_MBUF_LOGGING @@ -5756,7 +5759,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt calc_check, check, (void *)m, length, iphlen); stcb = sctp_findassociation_addr(m, offset, src, dst, sh, ch, &inp, &net, vrf_id); -#if defined INET || defined INET6 +#if defined(INET) || defined(INET6) if ((net != NULL) && (port != 0)) { if (net->port == 0) { sctp_pathmtu_adjustment(stcb, net->mtu - sizeof(struct udphdr)); @@ -5791,7 +5794,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt } stcb = sctp_findassociation_addr(m, offset, src, dst, sh, ch, &inp, &net, vrf_id); -#if defined INET || defined INET6 +#if defined(INET) || defined(INET6) if ((net != NULL) && (port != 0)) { if (net->port == 0) { sctp_pathmtu_adjustment(stcb, net->mtu - sizeof(struct udphdr)); @@ -5898,7 +5901,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt * timer is clearing out the assoc, we should * NOT respond to any packet.. its OOTB. */ - SCTP_TCB_UNLOCK(stcb); + SCTP_TCB_UNLOCK(stcb); stcb = NULL; snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s\n", __FILE__, __LINE__, __FUNCTION__); op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), @@ -5907,7 +5910,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt #if defined(__FreeBSD__) use_mflowid, mflowid, #endif - vrf_id, port); + vrf_id, port); goto out; } @@ -5919,15 +5922,15 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt src, dst, sh, ch, inp, stcb, &net, &fwd_tsn_seen, #if defined(__FreeBSD__) - use_mflowid, mflowid, + use_mflowid, mflowid, #endif vrf_id, port); if (stcb) { /* This covers us if the cookie-echo was there * and it changes our INP. */ - inp = stcb->sctp_ep; -#if defined INET || defined INET6 + inp = stcb->sctp_ep; +#if defined(INET) || defined(INET6) if ((net) && (port)) { if (net->port == 0) { sctp_pathmtu_adjustment(stcb, net->mtu - sizeof(struct udphdr)); @@ -5948,7 +5951,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt * chunks */ if ((stcb != NULL) && - !SCTP_BASE_SYSCTL(sctp_auth_disable) && + (stcb->asoc.auth_supported == 1) && sctp_auth_is_required_chunk(SCTP_DATA, stcb->asoc.local_auth_chunks)) { /* "silently" ignore */ SCTP_STAT_INCR(sctps_recvauthmissing); @@ -5993,7 +5996,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt */ if ((length > offset) && (stcb != NULL) && - !SCTP_BASE_SYSCTL(sctp_auth_disable) && + (stcb->asoc.auth_supported == 1) && sctp_auth_is_required_chunk(SCTP_DATA, stcb->asoc.local_auth_chunks) && !stcb->asoc.authenticated) { /* "silently" ignore */ @@ -6079,7 +6082,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt /* take care of ecn */ if ((data_processed == 1) && - (stcb->asoc.ecn_allowed == 1) && + (stcb->asoc.ecn_supported == 1) && ((ecn_bits & SCTP_CE_BITS) == SCTP_CE_BITS)) { /* Yep, we need to add a ECNE */ sctp_send_ecn_echo(stcb, net, high_tsn); @@ -6381,17 +6384,28 @@ sctp_input(i_pak, va_alist) extern int *sctp_cpuarry; #endif +#if defined(__FreeBSD__) && __FreeBSD_version >= 1100020 +int +sctp_input(struct mbuf **mp, int *offp, int proto SCTP_UNUSED) +{ + struct mbuf *m; + int off; + + m = *mp; + off = *offp; +#else void sctp_input(struct mbuf *m, int off) { +#endif #if defined(__FreeBSD__) && defined(SCTP_MCORE_INPUT) && defined(SMP) - struct ip *ip; - struct sctphdr *sh; - int offset; - int cpu_to_use; - uint32_t flowid, tag; - if (mp_ncpus > 1) { + struct ip *ip; + struct sctphdr *sh; + int offset; + int cpu_to_use; + uint32_t flowid, tag; + if (m->m_flags & M_FLOWID) { flowid = m->m_pkthdr.flowid; } else { @@ -6402,7 +6416,11 @@ sctp_input(struct mbuf *m, int off) if (SCTP_BUF_LEN(m) < offset) { if ((m = m_pullup(m, offset)) == NULL) { SCTP_STAT_INCR(sctps_hdrops); +#if defined(__FreeBSD__) && __FreeBSD_version >= 1100020 + return (IPPROTO_DONE); +#else return; +#endif } } ip = mtod(m, struct ip *); @@ -6414,10 +6432,17 @@ sctp_input(struct mbuf *m, int off) } cpu_to_use = sctp_cpuarry[flowid % mp_ncpus]; sctp_queue_to_mcore(m, off, cpu_to_use); +#if defined(__FreeBSD__) && __FreeBSD_version >= 1100020 + return (IPPROTO_DONE); +#else return; +#endif } #endif sctp_input_with_port(m, off, 0); +#if defined(__FreeBSD__) && __FreeBSD_version >= 1100020 + return (IPPROTO_DONE); +#endif } #endif #endif diff --git a/netinet/sctp_output.c b/netinet/sctp_output.c index 14f2cc0..a305ea5 100755 --- a/netinet/sctp_output.c +++ b/netinet/sctp_output.c @@ -32,7 +32,7 @@ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_output.c 267674 2014-06-20 13:26:49Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp_output.c 271230 2014-09-07 18:05:37Z tuexen $"); #endif #include <netinet/sctp_os.h> @@ -57,7 +57,7 @@ __FBSDID("$FreeBSD: head/sys/netinet/sctp_output.c 267674 2014-06-20 13:26:49Z t #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 INET || defined INET6 +#if defined(INET) || defined(INET6) #if !defined(__Userspace_os_Windows) #include <netinet/udp.h> #endif @@ -1908,7 +1908,7 @@ sctp_is_address_in_scope(struct sctp_ifa *ifa, if (scope->ipv4_addr_legal) { struct sockaddr_in *sin; - sin = (struct sockaddr_in *)&ifa->address.sin; + sin = &ifa->address.sin; if (sin->sin_addr.s_addr == 0) { /* not in scope , unspecified */ return (0); @@ -1940,7 +1940,7 @@ sctp_is_address_in_scope(struct sctp_ifa *ifa, return (0); } /* ok to use deprecated addresses? */ - sin6 = (struct sockaddr_in6 *)&ifa->address.sin6; + sin6 = &ifa->address.sin6; if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { /* skip unspecifed addresses */ return (0); @@ -2021,7 +2021,7 @@ sctp_add_addr_to_mbuf(struct mbuf *m, struct sctp_ifa *ifa, uint16_t *len) struct sctp_ipv4addr_param *ipv4p; struct sockaddr_in *sin; - sin = (struct sockaddr_in *)&ifa->address.sin; + sin = &ifa->address.sin; ipv4p = (struct sctp_ipv4addr_param *)parmh; parmh->param_type = htons(SCTP_IPV4_ADDRESS); parmh->param_length = htons(plen); @@ -2036,7 +2036,7 @@ sctp_add_addr_to_mbuf(struct mbuf *m, struct sctp_ifa *ifa, uint16_t *len) struct sctp_ipv6addr_param *ipv6p; struct sockaddr_in6 *sin6; - sin6 = (struct sockaddr_in6 *)&ifa->address.sin6; + sin6 = &ifa->address.sin6; ipv6p = (struct sctp_ipv6addr_param *)parmh; parmh->param_type = htons(SCTP_IPV6_ADDRESS); parmh->param_length = htons(plen); @@ -2103,14 +2103,14 @@ sctp_add_addresses_to_i_ia(struct sctp_inpcb *inp, struct sctp_tcb *stcb, if ((sctp_ifap->address.sa.sa_family == AF_INET) && (prison_check_ip4(inp->ip_inp.inp.inp_cred, &sctp_ifap->address.sin.sin_addr) != 0)) { - continue; + continue; } #endif #ifdef INET6 if ((sctp_ifap->address.sa.sa_family == AF_INET6) && (prison_check_ip6(inp->ip_inp.inp.inp_cred, &sctp_ifap->address.sin6.sin6_addr) != 0)) { - continue; + continue; } #endif #endif @@ -2153,14 +2153,14 @@ sctp_add_addresses_to_i_ia(struct sctp_inpcb *inp, struct sctp_tcb *stcb, if ((sctp_ifap->address.sa.sa_family == AF_INET) && (prison_check_ip4(inp->ip_inp.inp.inp_cred, &sctp_ifap->address.sin.sin_addr) != 0)) { - continue; + continue; } #endif #ifdef INET6 if ((sctp_ifap->address.sa.sa_family == AF_INET6) && (prison_check_ip6(inp->ip_inp.inp.inp_cred, &sctp_ifap->address.sin6.sin6_addr) != 0)) { - continue; + continue; } #endif #endif @@ -2210,7 +2210,7 @@ sctp_add_addresses_to_i_ia(struct sctp_inpcb *inp, struct sctp_tcb *stcb, continue; } if (laddr->ifa->localifa_flags & SCTP_BEING_DELETED) - /* Address being deleted by the system, dont + /* Address being deleted by the system, dont * list. */ continue; @@ -2671,7 +2671,7 @@ sctp_choose_boundspecific_stcb(struct sctp_inpcb *inp, sctp_ifn = sctp_find_ifn( ifn, ifn_index); /* - * first question, is the ifn we will emit on in our list? If so, + * first question, is the ifn we will emit on in our list? If so, * we want that one. First we look for a preferred. Second, we go * for an acceptable. */ @@ -3707,6 +3707,9 @@ sctp_process_cmsgs_for_init(struct sctp_tcb *stcb, struct mbuf *control, int *er if (stcb->asoc.streamoutcnt < stcb->asoc.pre_open_streams) { struct sctp_stream_out *tmp_str; unsigned int i; +#if defined(SCTP_DETAILED_STR_STATS) + int j; +#endif /* Default is NOT correct */ SCTPDBG(SCTP_DEBUG_OUTPUT1, "Ok, default:%d pre_open:%d\n", @@ -3728,6 +3731,15 @@ sctp_process_cmsgs_for_init(struct sctp_tcb *stcb, struct mbuf *control, int *er TAILQ_INIT(&stcb->asoc.strmout[i].outqueue); stcb->asoc.strmout[i].chunks_on_queues = 0; stcb->asoc.strmout[i].next_sequence_send = 0; +#if defined(SCTP_DETAILED_STR_STATS) + for (j = 0; j < SCTP_PR_SCTP_MAX + 1; j++) { + stcb->asoc.strmout[i].abandoned_sent[j] = 0; + stcb->asoc.strmout[i].abandoned_unsent[j] = 0; + } +#else + stcb->asoc.strmout[i].abandoned_sent[0] = 0; + stcb->asoc.strmout[i].abandoned_unsent[0] = 0; +#endif stcb->asoc.strmout[i].stream_no = i; stcb->asoc.strmout[i].last_msg_incomplete = 0; stcb->asoc.ss_functions.sctp_ss_init_stream(&stcb->asoc.strmout[i], NULL); @@ -4013,7 +4025,7 @@ sctp_add_cookie(struct mbuf *init, int init_offset, static uint8_t sctp_get_ect(struct sctp_tcb *stcb) { - if ((stcb != NULL) && (stcb->asoc.ecn_allowed == 1)) { + if ((stcb != NULL) && (stcb->asoc.ecn_supported == 1)) { return (SCTP_ECT0_BIT); } else { return (0); @@ -5042,7 +5054,7 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int so_locked #endif ) { - struct mbuf *m; + struct mbuf *m, *m_last; struct sctp_nets *net; struct sctp_init_chunk *init; struct sctp_supported_addr_param *sup_addr; @@ -5102,12 +5114,6 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int so_locked } chunk_len = (uint16_t)sizeof(struct sctp_init_chunk); padding_len = 0; - /* - * assume peer supports asconf in order to be able to queue - * local address changes while an INIT is in flight and before - * the assoc is established. - */ - stcb->asoc.peer_supports_asconf = 1; /* Now lets put the chunk header in place */ init = mtod(m, struct sctp_init_chunk *); /* now the chunk header */ @@ -5124,125 +5130,74 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int so_locked init->init.num_inbound_streams = htons(stcb->asoc.max_inbound_streams); init->init.initial_tsn = htonl(stcb->asoc.init_seq_number); - if (stcb->asoc.scope.ipv4_addr_legal || stcb->asoc.scope.ipv6_addr_legal) { - uint8_t i; - - parameter_len = (uint16_t)sizeof(struct sctp_paramhdr); - if (stcb->asoc.scope.ipv4_addr_legal) { - parameter_len += (uint16_t)sizeof(uint16_t); - } - if (stcb->asoc.scope.ipv6_addr_legal) { - parameter_len += (uint16_t)sizeof(uint16_t); - } - sup_addr = (struct sctp_supported_addr_param *)(mtod(m, caddr_t) + chunk_len); - sup_addr->ph.param_type = htons(SCTP_SUPPORTED_ADDRTYPE); - sup_addr->ph.param_length = htons(parameter_len); - i = 0; - if (stcb->asoc.scope.ipv4_addr_legal) { - sup_addr->addr_type[i++] = htons(SCTP_IPV4_ADDRESS); - } - if (stcb->asoc.scope.ipv6_addr_legal) { - sup_addr->addr_type[i++] = htons(SCTP_IPV6_ADDRESS); - } - padding_len = 4 - 2 * i; - chunk_len += parameter_len; - } - /* Adaptation layer indication parameter */ if (inp->sctp_ep.adaptation_layer_indicator_provided) { - if (padding_len > 0) { - memset(mtod(m, caddr_t) + chunk_len, 0, padding_len); - chunk_len += padding_len; - padding_len = 0; - } parameter_len = (uint16_t)sizeof(struct sctp_adaptation_layer_indication); ali = (struct sctp_adaptation_layer_indication *)(mtod(m, caddr_t) + chunk_len); ali->ph.param_type = htons(SCTP_ULP_ADAPTATION); ali->ph.param_length = htons(parameter_len); - ali->indication = ntohl(inp->sctp_ep.adaptation_layer_indicator); + ali->indication = htonl(inp->sctp_ep.adaptation_layer_indicator); chunk_len += parameter_len; } - if (SCTP_BASE_SYSCTL(sctp_inits_include_nat_friendly)) { - /* Add NAT friendly parameter. */ - if (padding_len > 0) { - memset(mtod(m, caddr_t) + chunk_len, 0, padding_len); - chunk_len += padding_len; - padding_len = 0; - } + /* ECN parameter */ + if (stcb->asoc.ecn_supported == 1) { parameter_len = (uint16_t)sizeof(struct sctp_paramhdr); ph = (struct sctp_paramhdr *)(mtod(m, caddr_t) + chunk_len); - ph->param_type = htons(SCTP_HAS_NAT_SUPPORT); + ph->param_type = htons(SCTP_ECN_CAPABLE); ph->param_length = htons(parameter_len); chunk_len += parameter_len; } - /* now any cookie time extensions */ - if (stcb->asoc.cookie_preserve_req) { - struct sctp_cookie_perserve_param *cookie_preserve; - - if (padding_len > 0) { - memset(mtod(m, caddr_t) + chunk_len, 0, padding_len); - chunk_len += padding_len; - padding_len = 0; - } - parameter_len = (uint16_t)sizeof(struct sctp_cookie_perserve_param); - cookie_preserve = (struct sctp_cookie_perserve_param *)(mtod(m, caddr_t) + chunk_len); - cookie_preserve->ph.param_type = htons(SCTP_COOKIE_PRESERVE); - cookie_preserve->ph.param_length = htons(parameter_len); - cookie_preserve->time = htonl(stcb->asoc.cookie_preserve_req); - stcb->asoc.cookie_preserve_req = 0; + /* PR-SCTP supported parameter */ + if (stcb->asoc.prsctp_supported == 1) { + parameter_len = (uint16_t)sizeof(struct sctp_paramhdr); + ph = (struct sctp_paramhdr *)(mtod(m, caddr_t) + chunk_len); + ph->param_type = htons(SCTP_PRSCTP_SUPPORTED); + ph->param_length = htons(parameter_len); chunk_len += parameter_len; } - /* ECN parameter */ - if (stcb->asoc.ecn_allowed == 1) { - if (padding_len > 0) { - memset(mtod(m, caddr_t) + chunk_len, 0, padding_len); - chunk_len += padding_len; - padding_len = 0; - } + /* Add NAT friendly parameter. */ + if (SCTP_BASE_SYSCTL(sctp_inits_include_nat_friendly)) { parameter_len = (uint16_t)sizeof(struct sctp_paramhdr); ph = (struct sctp_paramhdr *)(mtod(m, caddr_t) + chunk_len); - ph->param_type = htons(SCTP_ECN_CAPABLE); + ph->param_type = htons(SCTP_HAS_NAT_SUPPORT); ph->param_length = htons(parameter_len); chunk_len += parameter_len; } - /* And now tell the peer we do support PR-SCTP. */ - if (padding_len > 0) { - memset(mtod(m, caddr_t) + chunk_len, 0, padding_len); - chunk_len += padding_len; - padding_len = 0; - } - parameter_len = (uint16_t)sizeof(struct sctp_paramhdr); - ph = (struct sctp_paramhdr *)(mtod(m, caddr_t) + chunk_len); - ph->param_type = htons(SCTP_PRSCTP_SUPPORTED); - ph->param_length = htons(parameter_len); - chunk_len += parameter_len; - - /* And now tell the peer we do all the extensions */ - pr_supported = (struct sctp_supported_chunk_types_param *)(mtod(m, caddr_t) + chunk_len); - pr_supported->ph.param_type = htons(SCTP_SUPPORTED_CHUNK_EXT); + /* And now tell the peer which extensions we support */ num_ext = 0; - pr_supported->chunk_types[num_ext++] = SCTP_ASCONF; - pr_supported->chunk_types[num_ext++] = SCTP_ASCONF_ACK; - pr_supported->chunk_types[num_ext++] = SCTP_FORWARD_CUM_TSN; - pr_supported->chunk_types[num_ext++] = SCTP_PACKET_DROPPED; - pr_supported->chunk_types[num_ext++] = SCTP_STREAM_RESET; - if (!SCTP_BASE_SYSCTL(sctp_auth_disable)) { + pr_supported = (struct sctp_supported_chunk_types_param *)(mtod(m, caddr_t) + chunk_len); + if (stcb->asoc.prsctp_supported == 1) { + pr_supported->chunk_types[num_ext++] = SCTP_FORWARD_CUM_TSN; + } + if (stcb->asoc.auth_supported == 1) { pr_supported->chunk_types[num_ext++] = SCTP_AUTHENTICATION; } - if (stcb->asoc.sctp_nr_sack_on_off == 1) { + if (stcb->asoc.asconf_supported == 1) { + pr_supported->chunk_types[num_ext++] = SCTP_ASCONF; + pr_supported->chunk_types[num_ext++] = SCTP_ASCONF_ACK; + } + if (stcb->asoc.reconfig_supported == 1) { + pr_supported->chunk_types[num_ext++] = SCTP_STREAM_RESET; + } + if (stcb->asoc.nrsack_supported == 1) { pr_supported->chunk_types[num_ext++] = SCTP_NR_SELECTIVE_ACK; } - parameter_len = (uint16_t)sizeof(struct sctp_supported_chunk_types_param) + num_ext; - pr_supported->ph.param_length = htons(parameter_len); - padding_len = SCTP_SIZE32(parameter_len) - parameter_len; - chunk_len += parameter_len; - + if (stcb->asoc.pktdrop_supported == 1) { + pr_supported->chunk_types[num_ext++] = SCTP_PACKET_DROPPED; + } + if (num_ext > 0) { + parameter_len = (uint16_t)sizeof(struct sctp_supported_chunk_types_param) + num_ext; + pr_supported->ph.param_type = htons(SCTP_SUPPORTED_CHUNK_EXT); + pr_supported->ph.param_length = htons(parameter_len); + padding_len = SCTP_SIZE32(parameter_len) - parameter_len; + chunk_len += parameter_len; + } /* add authentication parameters */ - if (!SCTP_BASE_SYSCTL(sctp_auth_disable)) { + if (stcb->asoc.auth_supported) { /* attach RANDOM parameter, if available */ if (stcb->asoc.authinfo.random != NULL) { struct sctp_auth_random *randp; @@ -5260,8 +5215,7 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int so_locked chunk_len += parameter_len; } /* add HMAC_ALGO parameter */ - if ((stcb->asoc.local_hmacs != NULL) && - (stcb->asoc.local_hmacs->num_algo > 0)) { + if (stcb->asoc.local_hmacs != NULL) { struct sctp_auth_hmac_algo *hmacs; if (padding_len > 0) { @@ -5279,7 +5233,7 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int so_locked chunk_len += parameter_len; } /* add CHUNKS parameter */ - if (sctp_auth_get_chklist_size(stcb->asoc.local_auth_chunks) > 0) { + if (stcb->asoc.local_auth_chunks != NULL) { struct sctp_auth_chunk_list *chunks; if (padding_len > 0) { @@ -5297,8 +5251,55 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int so_locked chunk_len += parameter_len; } } - SCTP_BUF_LEN(m) = chunk_len; + /* now any cookie time extensions */ + if (stcb->asoc.cookie_preserve_req) { + struct sctp_cookie_perserve_param *cookie_preserve; + + if (padding_len > 0) { + memset(mtod(m, caddr_t) + chunk_len, 0, padding_len); + chunk_len += padding_len; + padding_len = 0; + } + parameter_len = (uint16_t)sizeof(struct sctp_cookie_perserve_param); + cookie_preserve = (struct sctp_cookie_perserve_param *)(mtod(m, caddr_t) + chunk_len); + cookie_preserve->ph.param_type = htons(SCTP_COOKIE_PRESERVE); + cookie_preserve->ph.param_length = htons(parameter_len); + cookie_preserve->time = htonl(stcb->asoc.cookie_preserve_req); + stcb->asoc.cookie_preserve_req = 0; + chunk_len += parameter_len; + } + + if (stcb->asoc.scope.ipv4_addr_legal || stcb->asoc.scope.ipv6_addr_legal) { + uint8_t i; + + if (padding_len > 0) { + memset(mtod(m, caddr_t) + chunk_len, 0, padding_len); + chunk_len += padding_len; + padding_len = 0; + } + parameter_len = (uint16_t)sizeof(struct sctp_paramhdr); + if (stcb->asoc.scope.ipv4_addr_legal) { + parameter_len += (uint16_t)sizeof(uint16_t); + } + if (stcb->asoc.scope.ipv6_addr_legal) { + parameter_len += (uint16_t)sizeof(uint16_t); + } + sup_addr = (struct sctp_supported_addr_param *)(mtod(m, caddr_t) + chunk_len); + sup_addr->ph.param_type = htons(SCTP_SUPPORTED_ADDRTYPE); + sup_addr->ph.param_length = htons(parameter_len); + i = 0; + if (stcb->asoc.scope.ipv4_addr_legal) { + sup_addr->addr_type[i++] = htons(SCTP_IPV4_ADDRESS); + } + if (stcb->asoc.scope.ipv6_addr_legal) { + sup_addr->addr_type[i++] = htons(SCTP_IPV6_ADDRESS); + } + padding_len = 4 - 2 * i; + chunk_len += parameter_len; + } + + SCTP_BUF_LEN(m) = chunk_len; /* now the addresses */ /* To optimize this we could put the scoping stuff * into a structure and remove the individual uint8's from @@ -5306,18 +5307,13 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int so_locked * address within the stcb. But for now this is a quick * hack to get the address stuff teased apart. */ - sctp_add_addresses_to_i_ia(inp, stcb, &stcb->asoc.scope, m, cnt_inits_to, &padding_len, &chunk_len); + m_last = sctp_add_addresses_to_i_ia(inp, stcb, &stcb->asoc.scope, + m, cnt_inits_to, + &padding_len, &chunk_len); init->ch.chunk_length = htons(chunk_len); if (padding_len > 0) { - struct mbuf *m_at, *mp_last; - - mp_last = NULL; - for (m_at = m; m_at; m_at = SCTP_BUF_NEXT(m_at)) { - if (SCTP_BUF_NEXT(m_at) == NULL) - mp_last = m_at; - } - if ((mp_last == NULL) || sctp_add_pad_tombuf(mp_last, padding_len)) { + if (sctp_add_pad_tombuf(m_last, padding_len) == NULL) { sctp_m_freem(m); return; } @@ -5453,10 +5449,9 @@ sctp_arethere_unrecognized_parameters(struct mbuf *in_initpkt, at += padded_size; break; case SCTP_HAS_NAT_SUPPORT: - *nat_friendly = 1; - /* fall through */ + *nat_friendly = 1; + /* fall through */ case SCTP_PRSCTP_SUPPORTED: - if (padded_size != sizeof(struct sctp_paramhdr)) { SCTPDBG(SCTP_DEBUG_OUTPUT1, "Invalid size - error prsctp/nat support %d\n", plen); goto invalid_size; @@ -5464,7 +5459,7 @@ sctp_arethere_unrecognized_parameters(struct mbuf *in_initpkt, at += padded_size; break; case SCTP_ECN_CAPABLE: - if (padded_size != sizeof(struct sctp_ecn_supported_param)) { + if (padded_size != sizeof(struct sctp_paramhdr)) { SCTPDBG(SCTP_DEBUG_OUTPUT1, "Invalid size - error ecn %d\n", plen); goto invalid_size; } @@ -5848,13 +5843,13 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb, uint32_t vrf_id, uint16_t port, int hold_inp_lock) { struct sctp_association *asoc; - struct mbuf *m, *m_at, *m_tmp, *m_cookie, *op_err, *mp_last; + struct mbuf *m, *m_tmp, *m_last, *m_cookie, *op_err; struct sctp_init_ack_chunk *initack; struct sctp_adaptation_layer_indication *ali; - struct sctp_ecn_supported_param *ecn; - struct sctp_prsctp_supported_param *prsctp; struct sctp_supported_chunk_types_param *pr_supported; + struct sctp_paramhdr *ph; union sctp_sockstore *over_addr; + struct sctp_scoping scp; #ifdef INET struct sockaddr_in *dst4 = (struct sockaddr_in *)dst; struct sockaddr_in *src4 = (struct sockaddr_in *)src; @@ -5876,18 +5871,16 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb, uint8_t *signature = NULL; int cnt_inits_to = 0; uint16_t his_limit, i_want; - int abort_flag, padval; - int num_ext; - int p_len; + int abort_flag; int nat_friendly = 0; struct socket *so; + uint16_t num_ext, chunk_len, padding_len, parameter_len; if (stcb) { asoc = &stcb->asoc; } else { asoc = NULL; } - mp_last = NULL; if ((asoc != NULL) && (SCTP_GET_STATE(asoc) != SCTP_STATE_COOKIE_WAIT) && (sctp_are_there_new_addresses(asoc, init_pkt, offset, src))) { @@ -5934,7 +5927,8 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb, sctp_m_freem(op_err); return; } - SCTP_BUF_LEN(m) = sizeof(struct sctp_init_chunk); + chunk_len = (uint16_t)sizeof(struct sctp_init_ack_chunk); + padding_len = 0; /* * We might not overwrite the identification[] completely and on @@ -6311,161 +6305,183 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb, /* adaptation layer indication parameter */ if (inp->sctp_ep.adaptation_layer_indicator_provided) { - ali = (struct sctp_adaptation_layer_indication *)((caddr_t)initack + sizeof(*initack)); + parameter_len = (uint16_t)sizeof(struct sctp_adaptation_layer_indication); + ali = (struct sctp_adaptation_layer_indication *)(mtod(m, caddr_t) + chunk_len); ali->ph.param_type = htons(SCTP_ULP_ADAPTATION); - ali->ph.param_length = htons(sizeof(*ali)); - ali->indication = ntohl(inp->sctp_ep.adaptation_layer_indicator); - SCTP_BUF_LEN(m) += sizeof(*ali); - ecn = (struct sctp_ecn_supported_param *)((caddr_t)ali + sizeof(*ali)); - } else { - ecn = (struct sctp_ecn_supported_param *)((caddr_t)initack + sizeof(*initack)); + ali->ph.param_length = htons(parameter_len); + ali->indication = htonl(inp->sctp_ep.adaptation_layer_indicator); + chunk_len += parameter_len; } /* ECN parameter */ - if (((asoc != NULL) && (asoc->ecn_allowed == 1)) || - (inp->sctp_ecn_enable == 1)) { - ecn->ph.param_type = htons(SCTP_ECN_CAPABLE); - ecn->ph.param_length = htons(sizeof(*ecn)); - SCTP_BUF_LEN(m) += sizeof(*ecn); - - prsctp = (struct sctp_prsctp_supported_param *)((caddr_t)ecn + - sizeof(*ecn)); - } else { - prsctp = (struct sctp_prsctp_supported_param *)((caddr_t)ecn); + if (((asoc != NULL) && (asoc->ecn_supported == 1)) || + ((asoc == NULL) && (inp->ecn_supported == 1))) { + parameter_len = (uint16_t)sizeof(struct sctp_paramhdr); + ph = (struct sctp_paramhdr *)(mtod(m, caddr_t) + chunk_len); + ph->param_type = htons(SCTP_ECN_CAPABLE); + ph->param_length = htons(parameter_len); + chunk_len += parameter_len; + } + + /* PR-SCTP supported parameter */ + if (((asoc != NULL) && (asoc->prsctp_supported == 1)) || + ((asoc == NULL) && (inp->prsctp_supported == 1))) { + parameter_len = (uint16_t)sizeof(struct sctp_paramhdr); + ph = (struct sctp_paramhdr *)(mtod(m, caddr_t) + chunk_len); + ph->param_type = htons(SCTP_PRSCTP_SUPPORTED); + ph->param_length = htons(parameter_len); + chunk_len += parameter_len; } - /* And now tell the peer we do pr-sctp */ - prsctp->ph.param_type = htons(SCTP_PRSCTP_SUPPORTED); - prsctp->ph.param_length = htons(sizeof(*prsctp)); - SCTP_BUF_LEN(m) += sizeof(*prsctp); - if (nat_friendly) { - /* Add NAT friendly parameter */ - struct sctp_paramhdr *ph; - ph = (struct sctp_paramhdr *)(mtod(m, caddr_t) + SCTP_BUF_LEN(m)); + /* Add NAT friendly parameter */ + if (nat_friendly) { + parameter_len = (uint16_t)sizeof(struct sctp_paramhdr); + ph = (struct sctp_paramhdr *)(mtod(m, caddr_t) + chunk_len); ph->param_type = htons(SCTP_HAS_NAT_SUPPORT); - ph->param_length = htons(sizeof(struct sctp_paramhdr)); - SCTP_BUF_LEN(m) += sizeof(struct sctp_paramhdr); + ph->param_length = htons(parameter_len); + chunk_len += parameter_len; } - /* And now tell the peer we do all the extensions */ - pr_supported = (struct sctp_supported_chunk_types_param *)(mtod(m, caddr_t) + SCTP_BUF_LEN(m)); - pr_supported->ph.param_type = htons(SCTP_SUPPORTED_CHUNK_EXT); + + /* And now tell the peer which extensions we support */ num_ext = 0; - pr_supported->chunk_types[num_ext++] = SCTP_ASCONF; - pr_supported->chunk_types[num_ext++] = SCTP_ASCONF_ACK; - pr_supported->chunk_types[num_ext++] = SCTP_FORWARD_CUM_TSN; - pr_supported->chunk_types[num_ext++] = SCTP_PACKET_DROPPED; - pr_supported->chunk_types[num_ext++] = SCTP_STREAM_RESET; - if (!SCTP_BASE_SYSCTL(sctp_auth_disable)) + pr_supported = (struct sctp_supported_chunk_types_param *)(mtod(m, caddr_t) + chunk_len); + if (((asoc != NULL) && (asoc->prsctp_supported == 1)) || + ((asoc == NULL) && (inp->prsctp_supported == 1))) { + pr_supported->chunk_types[num_ext++] = SCTP_FORWARD_CUM_TSN; + } + if (((asoc != NULL) && (asoc->auth_supported == 1)) || + ((asoc == NULL) && (inp->auth_supported == 1))) { pr_supported->chunk_types[num_ext++] = SCTP_AUTHENTICATION; - if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off)) + } + if (((asoc != NULL) && (asoc->asconf_supported == 1)) || + ((asoc == NULL) && (inp->asconf_supported == 1))) { + pr_supported->chunk_types[num_ext++] = SCTP_ASCONF; + pr_supported->chunk_types[num_ext++] = SCTP_ASCONF_ACK; + } + if (((asoc != NULL) && (asoc->reconfig_supported == 1)) || + ((asoc == NULL) && (inp->reconfig_supported == 1))) { + pr_supported->chunk_types[num_ext++] = SCTP_STREAM_RESET; + } + if (((asoc != NULL) && (asoc->nrsack_supported == 1)) || + ((asoc == NULL) && (inp->nrsack_supported == 1))) { pr_supported->chunk_types[num_ext++] = SCTP_NR_SELECTIVE_ACK; - p_len = sizeof(*pr_supported) + num_ext; - pr_supported->ph.param_length = htons(p_len); - bzero((caddr_t)pr_supported + p_len, SCTP_SIZE32(p_len) - p_len); - SCTP_BUF_LEN(m) += SCTP_SIZE32(p_len); - + } + if (((asoc != NULL) && (asoc->pktdrop_supported == 1)) || + ((asoc == NULL) && (inp->pktdrop_supported == 1))) { + pr_supported->chunk_types[num_ext++] = SCTP_PACKET_DROPPED; + } + if (num_ext > 0) { + parameter_len = (uint16_t)sizeof(struct sctp_supported_chunk_types_param) + num_ext; + pr_supported->ph.param_type = htons(SCTP_SUPPORTED_CHUNK_EXT); + pr_supported->ph.param_length = htons(parameter_len); + padding_len = SCTP_SIZE32(parameter_len) - parameter_len; + chunk_len += parameter_len; + } + /* add authentication parameters */ - if (!SCTP_BASE_SYSCTL(sctp_auth_disable)) { + if (((asoc != NULL) && (asoc->auth_supported == 1)) || + ((asoc == NULL) && (inp->auth_supported == 1))) { struct sctp_auth_random *randp; struct sctp_auth_hmac_algo *hmacs; struct sctp_auth_chunk_list *chunks; - uint16_t random_len; + if (padding_len > 0) { + memset(mtod(m, caddr_t) + chunk_len, 0, padding_len); + chunk_len += padding_len; + padding_len = 0; + } /* generate and add RANDOM parameter */ - random_len = SCTP_AUTH_RANDOM_SIZE_DEFAULT; - randp = (struct sctp_auth_random *)(mtod(m, caddr_t) + SCTP_BUF_LEN(m)); + randp = (struct sctp_auth_random *)(mtod(m, caddr_t) + chunk_len); + parameter_len = (uint16_t)sizeof(struct sctp_auth_random) + + SCTP_AUTH_RANDOM_SIZE_DEFAULT; randp->ph.param_type = htons(SCTP_RANDOM); - p_len = sizeof(*randp) + random_len; - randp->ph.param_length = htons(p_len); - SCTP_READ_RANDOM(randp->random_data, random_len); - /* zero out any padding required */ - bzero((caddr_t)randp + p_len, SCTP_SIZE32(p_len) - p_len); - SCTP_BUF_LEN(m) += SCTP_SIZE32(p_len); + randp->ph.param_length = htons(parameter_len); + SCTP_READ_RANDOM(randp->random_data, SCTP_AUTH_RANDOM_SIZE_DEFAULT); + padding_len = SCTP_SIZE32(parameter_len) - parameter_len; + chunk_len += parameter_len; + if (padding_len > 0) { + memset(mtod(m, caddr_t) + chunk_len, 0, padding_len); + chunk_len += padding_len; + padding_len = 0; + } /* add HMAC_ALGO parameter */ - hmacs = (struct sctp_auth_hmac_algo *)(mtod(m, caddr_t) + SCTP_BUF_LEN(m)); - p_len = sctp_serialize_hmaclist(inp->sctp_ep.local_hmacs, - (uint8_t *) hmacs->hmac_ids); - if (p_len > 0) { - p_len += sizeof(*hmacs); - hmacs->ph.param_type = htons(SCTP_HMAC_LIST); - hmacs->ph.param_length = htons(p_len); - /* zero out any padding required */ - bzero((caddr_t)hmacs + p_len, SCTP_SIZE32(p_len) - p_len); - SCTP_BUF_LEN(m) += SCTP_SIZE32(p_len); + hmacs = (struct sctp_auth_hmac_algo *)(mtod(m, caddr_t) + chunk_len); + parameter_len = (uint16_t)sizeof(struct sctp_auth_hmac_algo) + + sctp_serialize_hmaclist(inp->sctp_ep.local_hmacs, + (uint8_t *)hmacs->hmac_ids); + hmacs->ph.param_type = htons(SCTP_HMAC_LIST); + hmacs->ph.param_length = htons(parameter_len); + padding_len = SCTP_SIZE32(parameter_len) - parameter_len; + chunk_len += parameter_len; + + if (padding_len > 0) { + memset(mtod(m, caddr_t) + chunk_len, 0, padding_len); + chunk_len += padding_len; + padding_len = 0; } /* add CHUNKS parameter */ - chunks = (struct sctp_auth_chunk_list *)(mtod(m, caddr_t) + SCTP_BUF_LEN(m)); - p_len = sctp_serialize_auth_chunks(inp->sctp_ep.local_auth_chunks, - chunks->chunk_types); - if (p_len > 0) { - p_len += sizeof(*chunks); - chunks->ph.param_type = htons(SCTP_CHUNK_LIST); - chunks->ph.param_length = htons(p_len); - /* zero out any padding required */ - bzero((caddr_t)chunks + p_len, SCTP_SIZE32(p_len) - p_len); - SCTP_BUF_LEN(m) += SCTP_SIZE32(p_len); - } + chunks = (struct sctp_auth_chunk_list *)(mtod(m, caddr_t) + chunk_len); + parameter_len = (uint16_t)sizeof(struct sctp_auth_chunk_list) + + sctp_serialize_auth_chunks(inp->sctp_ep.local_auth_chunks, + chunks->chunk_types); + chunks->ph.param_type = htons(SCTP_CHUNK_LIST); + chunks->ph.param_length = htons(parameter_len); + padding_len = SCTP_SIZE32(parameter_len) - parameter_len; + chunk_len += parameter_len; } - m_at = m; + SCTP_BUF_LEN(m) = chunk_len; + m_last = m; /* now the addresses */ - { - struct sctp_scoping scp; - /* To optimize this we could put the scoping stuff - * into a structure and remove the individual uint8's from - * the stc structure. Then we could just sifa in the - * address within the stc.. but for now this is a quick - * hack to get the address stuff teased apart. - */ - scp.ipv4_addr_legal = stc.ipv4_addr_legal; - scp.ipv6_addr_legal = stc.ipv6_addr_legal; + /* To optimize this we could put the scoping stuff + * into a structure and remove the individual uint8's from + * the stc structure. Then we could just sifa in the + * address within the stc.. but for now this is a quick + * hack to get the address stuff teased apart. + */ + scp.ipv4_addr_legal = stc.ipv4_addr_legal; + scp.ipv6_addr_legal = stc.ipv6_addr_legal; #if defined(__Userspace__) - scp.conn_addr_legal = stc.conn_addr_legal; -#endif - scp.loopback_scope = stc.loopback_scope; - scp.ipv4_local_scope = stc.ipv4_scope; - scp.local_scope = stc.local_scope; - scp.site_scope = stc.site_scope; - m_at = sctp_add_addresses_to_i_ia(inp, stcb, &scp, m_at, cnt_inits_to, NULL, NULL); + scp.conn_addr_legal = stc.conn_addr_legal; +#endif + scp.loopback_scope = stc.loopback_scope; + scp.ipv4_local_scope = stc.ipv4_scope; + scp.local_scope = stc.local_scope; + scp.site_scope = stc.site_scope; + m_last = sctp_add_addresses_to_i_ia(inp, stcb, &scp, m_last, + cnt_inits_to, + &padding_len, &chunk_len); + /* padding_len can only be positive, if no addresses have been added */ + if (padding_len > 0) { + memset(mtod(m, caddr_t) + chunk_len, 0, padding_len); + chunk_len += padding_len; + SCTP_BUF_LEN(m) += padding_len; + padding_len = 0; } /* tack on the operational error if present */ if (op_err) { - struct mbuf *ol; - int llen; - llen = 0; - ol = op_err; - - while (ol) { - llen += SCTP_BUF_LEN(ol); - ol = SCTP_BUF_NEXT(ol); - } - if (llen % 4) { - /* must add a pad to the param */ - uint32_t cpthis = 0; - int padlen; - - padlen = 4 - (llen % 4); - m_copyback(op_err, llen, padlen, (caddr_t)&cpthis); - } - while (SCTP_BUF_NEXT(m_at) != NULL) { - m_at = SCTP_BUF_NEXT(m_at); + parameter_len = 0; + for (m_tmp = op_err; m_tmp != NULL; m_tmp = SCTP_BUF_NEXT(m_tmp)) { + parameter_len += SCTP_BUF_LEN(m_tmp); } - SCTP_BUF_NEXT(m_at) = op_err; - while (SCTP_BUF_NEXT(m_at) != NULL) { - m_at = SCTP_BUF_NEXT(m_at); + padding_len = SCTP_SIZE32(parameter_len) - parameter_len; + SCTP_BUF_NEXT(m_last) = op_err; + while (SCTP_BUF_NEXT(m_last) != NULL) { + m_last = SCTP_BUF_NEXT(m_last); } + chunk_len += parameter_len; } - /* pre-calulate the size and update pkt header and chunk header */ - p_len = 0; - for (m_tmp = m; m_tmp; m_tmp = SCTP_BUF_NEXT(m_tmp)) { - p_len += SCTP_BUF_LEN(m_tmp); - if (SCTP_BUF_NEXT(m_tmp) == NULL) { - /* m_tmp should now point to last one */ - break; + if (padding_len > 0) { + m_last = sctp_add_pad_tombuf(m_last, padding_len); + if (m_last == NULL) { + /* Houston we have a problem, no space */ + sctp_m_freem(m); + return; } + chunk_len += padding_len; + padding_len = 0; } - /* Now we must build a cookie */ m_cookie = sctp_add_cookie(init_pkt, offset, m, 0, &stc, &signature); if (m_cookie == NULL) { @@ -6474,20 +6490,21 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb, return; } /* Now append the cookie to the end and update the space/size */ - SCTP_BUF_NEXT(m_tmp) = m_cookie; - - for (m_tmp = m_cookie; m_tmp; m_tmp = SCTP_BUF_NEXT(m_tmp)) { - p_len += SCTP_BUF_LEN(m_tmp); + SCTP_BUF_NEXT(m_last) = m_cookie; + parameter_len = 0; + for (m_tmp = m_cookie; m_tmp != NULL; m_tmp = SCTP_BUF_NEXT(m_tmp)) { + parameter_len += SCTP_BUF_LEN(m_tmp); if (SCTP_BUF_NEXT(m_tmp) == NULL) { - /* m_tmp should now point to last one */ - mp_last = m_tmp; - break; + m_last = m_tmp; } } + padding_len = SCTP_SIZE32(parameter_len) - parameter_len; + chunk_len += parameter_len; + /* Place in the size, but we don't include * the last pad (if any) in the INIT-ACK. */ - initack->ch.chunk_length = htons(p_len); + initack->ch.chunk_length = htons(chunk_len); /* Time to sign the cookie, we don't sign over the cookie * signature though thus we set trailer. @@ -6500,11 +6517,8 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb, * We sifa 0 here to NOT set IP_DF if its IPv4, we ignore the return * here since the timer will drive a retranmission. */ - padval = p_len % 4; - if ((padval) && (mp_last)) { - /* see my previous comments on mp_last */ - if (sctp_add_pad_tombuf(mp_last, (4 - padval))) { - /* Houston we have a problem, no space */ + if (padding_len > 0) { + if (sctp_add_pad_tombuf(m_last, padding_len) == NULL) { sctp_m_freem(m); return; } @@ -6537,7 +6551,7 @@ sctp_prune_prsctp(struct sctp_tcb *stcb, struct sctp_tmit_chunk *chk, *nchk; SCTP_TCB_LOCK_ASSERT(stcb); - if ((asoc->peer_supports_prsctp) && + if ((asoc->prsctp_supported) && (asoc->sent_queue_cnt_removeable > 0)) { TAILQ_FOREACH(chk, &asoc->sent_queue, sctp_next) { /* @@ -7944,7 +7958,6 @@ re_look: sctp_auth_key_acquire(stcb, chk->auth_keyid); chk->holds_key_ref = 1; } - #if defined(__FreeBSD__) || defined(__Panda__) chk->rec.data.TSN_seq = atomic_fetchadd_int(&asoc->sending_seq, 1); #else @@ -7993,12 +8006,10 @@ re_look: int pads; pads = SCTP_SIZE32(chk->book_size) - chk->send_size; - if (sctp_pad_lastmbuf(chk->data, pads, chk->last_mbuf) == 0) { - chk->pad_inplace = 1; - } - if ((lm = SCTP_BUF_NEXT(chk->last_mbuf)) != NULL) { - /* pad added an mbuf */ + lm = sctp_pad_lastmbuf(chk->data, pads, chk->last_mbuf); + if (lm != NULL) { chk->last_mbuf = lm; + chk->pad_inplace = 1; } chk->send_size += pads; } @@ -8239,7 +8250,6 @@ sctp_med_chunk_output(struct sctp_inpcb *inp, #endif *num_out = 0; auth_keyid = stcb->asoc.authinfo.active_keyid; - if ((asoc->state & SCTP_STATE_SHUTDOWN_PENDING) || (asoc->state & SCTP_STATE_SHUTDOWN_RECEIVED) || (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXPLICIT_EOR))) { @@ -10443,7 +10453,7 @@ sctp_chunk_output (struct sctp_inpcb *inp, /* Do we have something to send, data or control AND * a sack timer running, if so piggy-back the sack. */ - if (SCTP_OS_TIMER_PENDING(&stcb->asoc.dack_timer.timer)) { + if (SCTP_OS_TIMER_PENDING(&stcb->asoc.dack_timer.timer)) { sctp_send_sack(stcb, so_locked); (void)SCTP_OS_TIMER_STOP(&stcb->asoc.dack_timer.timer); } @@ -10458,7 +10468,7 @@ sctp_chunk_output (struct sctp_inpcb *inp, * by peer that carried data. Send cookie-ack only * and then the next call with get the retran's. */ - (void)sctp_med_chunk_output(inp, stcb, asoc, &num_out, &reason_code, 1, + (void)sctp_med_chunk_output(inp, stcb, asoc, &num_out, &reason_code, 1, from_where, &now, &now_filled, frag_point, so_locked); return; @@ -10912,8 +10922,7 @@ sctp_send_sack(struct sctp_tcb *stcb, int so_locked uint8_t type; uint8_t tsn_map; - if ((stcb->asoc.sctp_nr_sack_on_off == 1) && - (stcb->asoc.peer_supports_nr_sack == 1)) { + if (stcb->asoc.nrsack_supported == 1) { type = SCTP_NR_SELECTIVE_ACK; } else { type = SCTP_SELECTIVE_ACK; @@ -11374,7 +11383,8 @@ sctp_send_abort_tcb(struct sctp_tcb *stcb, struct mbuf *operr, int so_locked 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)) { + if ((m_last == NULL) || + (sctp_add_pad_tombuf(m_last, padding_len) == NULL)) { sctp_m_freem(m_out); return; } @@ -11488,7 +11498,7 @@ sctp_send_resp_msg(struct sockaddr *src, struct sockaddr *dst, padding_len = 4 - padding_len; } if (padding_len != 0) { - if (sctp_add_pad_tombuf(m_last, padding_len)) { + if (sctp_add_pad_tombuf(m_last, padding_len) == NULL) { sctp_m_freem(cause); return; } @@ -11512,7 +11522,7 @@ sctp_send_resp_msg(struct sockaddr *src, struct sockaddr *dst, default: break; } -#if defined INET || defined INET6 +#if defined(INET) || defined(INET6) if (port) { len += sizeof(struct udphdr); } @@ -11621,7 +11631,7 @@ sctp_send_resp_msg(struct sockaddr *src, struct sockaddr *dst, shout = mtod(mout, struct sctphdr *); break; } -#if defined INET || defined INET6 +#if defined(INET) || defined(INET6) if (port) { if (htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port)) == 0) { sctp_m_freem(mout); @@ -12066,7 +12076,7 @@ sctp_send_packet_dropped(struct sctp_tcb *stcb, struct sctp_nets *net, } asoc = &stcb->asoc; SCTP_TCB_LOCK_ASSERT(stcb); - if (asoc->peer_supports_pktdrop == 0) { + if (asoc->pktdrop_supported == 0) { /*- * peer must declare support before I send one. */ @@ -12573,6 +12583,9 @@ sctp_send_str_reset_req(struct sctp_tcb *stcb, struct sctp_stream_out *oldstream; struct sctp_stream_queue_pending *sp, *nsp; int i; +#if defined(SCTP_DETAILED_STR_STATS) + int j; +#endif oldstream = stcb->asoc.strmout; /* get some more */ @@ -12617,6 +12630,15 @@ sctp_send_str_reset_req(struct sctp_tcb *stcb, for (i = stcb->asoc.streamoutcnt; i < (stcb->asoc.streamoutcnt + adding_o); i++) { TAILQ_INIT(&stcb->asoc.strmout[i].outqueue); stcb->asoc.strmout[i].chunks_on_queues = 0; +#if defined(SCTP_DETAILED_STR_STATS) + for (j = 0; j < SCTP_PR_SCTP_MAX + 1; j++) { + stcb->asoc.strmout[i].abandoned_sent[j] = 0; + stcb->asoc.strmout[i].abandoned_unsent[j] = 0; + } +#else + stcb->asoc.strmout[i].abandoned_sent[0] = 0; + stcb->asoc.strmout[i].abandoned_unsent[0] = 0; +#endif stcb->asoc.strmout[i].next_sequence_send = 0x0; stcb->asoc.strmout[i].stream_no = i; stcb->asoc.strmout[i].last_msg_incomplete = 0; @@ -13977,7 +13999,7 @@ skip_preblock: continue; } /* PR-SCTP? */ - if ((asoc->peer_supports_prsctp) && (asoc->sent_queue_cnt_removeable > 0)) { + if ((asoc->prsctp_supported) && (asoc->sent_queue_cnt_removeable > 0)) { /* This is ugly but we must assure locking order */ if (hold_tcblock == 0) { SCTP_TCB_LOCK(stcb); @@ -14476,12 +14498,7 @@ sctp_add_auth_chunk(struct mbuf *m, struct mbuf **m_end, (stcb == NULL)) return (m); - /* sysctl disabled auth? */ - if (SCTP_BASE_SYSCTL(sctp_auth_disable)) - return (m); - - /* peer doesn't do auth... */ - if (!stcb->asoc.peer_supports_auth) { + if (stcb->asoc.auth_supported == 0) { return (m); } /* does the requested chunk require auth? */ @@ -14590,7 +14607,7 @@ sctp_v4src_match_nexthop(struct sctp_ifa *sifa, sctp_route_t *ro) } ifa = (struct ifaddr *)sifa->ifa; mask = (struct sockaddr_in *)(ifa->ifa_netmask); - sin = (struct sockaddr_in *)&sifa->address.sin; + sin = &sifa->address.sin; srcnetaddr.s_addr = (sin->sin_addr.s_addr & mask->sin_addr.s_addr); SCTPDBG(SCTP_DEBUG_OUTPUT1, "match_nexthop4: src address is "); SCTPDBG_ADDR(SCTP_DEBUG_OUTPUT2, &sifa->address.sa); diff --git a/netinet/sctp_pcb.c b/netinet/sctp_pcb.c index a7f8b85..ffe8f62 100755 --- a/netinet/sctp_pcb.c +++ b/netinet/sctp_pcb.c @@ -32,7 +32,7 @@ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_pcb.c 267674 2014-06-20 13:26:49Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp_pcb.c 271230 2014-09-07 18:05:37Z tuexen $"); #endif #include <netinet/sctp_os.h> @@ -52,7 +52,7 @@ __FBSDID("$FreeBSD: head/sys/netinet/sctp_pcb.c 267674 2014-06-20 13:26:49Z tuex #if defined(__FreeBSD__) && __FreeBSD_version >= 803000 #include <netinet/sctp_dtrace_define.h> #endif -#if defined INET || defined INET6 +#if defined(INET) || defined(INET6) #if !defined(__Userspace_os_Windows) #include <netinet/udp.h> #endif @@ -224,8 +224,8 @@ sctp_allocate_vrf(int vrf_id) } SCTP_MALLOC(vrf, struct sctp_vrf *, sizeof(struct sctp_vrf), SCTP_M_VRF); - if (vrf == NULL) { - /* No memory */ + if (vrf == NULL) { + /* No memory */ #ifdef INVARIANTS panic("No memory for VRF:%d", vrf_id); #endif @@ -243,7 +243,7 @@ sctp_allocate_vrf(int vrf_id) vrf->vrf_addr_hash = SCTP_HASH_INIT(SCTP_VRF_ADDR_HASH_SIZE, &vrf->vrf_addr_hashmark); if (vrf->vrf_addr_hash == NULL) { - /* No memory */ + /* No memory */ #ifdef INVARIANTS panic("No memory for VRF:%d", vrf_id); #endif @@ -656,7 +656,7 @@ sctp_add_addr_to_vrf(uint32_t vrf_id, void *ifn, uint32_t ifn_index, sctp_remove_ifa_from_ifn(sctp_ifap); /* move the address over to the new ifn */ sctp_add_ifa_to_ifn(sctp_ifnp, sctp_ifap); - goto exit_stage_left; + goto exit_stage_left; } else { /* repair ifnp which was NULL ? */ sctp_ifap->localifa_flags = SCTP_ADDR_VALID; @@ -713,7 +713,7 @@ sctp_add_addr_to_vrf(uint32_t vrf_id, void *ifn, uint32_t ifn_index, { struct sockaddr_in *sin; - sin = (struct sockaddr_in *)&sctp_ifap->address.sin; + sin = &sctp_ifap->address.sin; if (SCTP_IFN_IS_IFT_LOOP(sctp_ifap->ifn_p) || (IN4_ISLOOPBACK_ADDRESS(&sin->sin_addr))) { sctp_ifap->src_is_loop = 1; @@ -733,7 +733,7 @@ sctp_add_addr_to_vrf(uint32_t vrf_id, void *ifn, uint32_t ifn_index, /* ok to use deprecated addresses? */ struct sockaddr_in6 *sin6; - sin6 = (struct sockaddr_in6 *)&sctp_ifap->address.sin6; + sin6 = &sctp_ifap->address.sin6; if (SCTP_IFN_IS_IFT_LOOP(sctp_ifap->ifn_p) || (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr))) { sctp_ifap->src_is_loop = 1; @@ -1097,7 +1097,7 @@ sctp_does_stcb_own_this_addr(struct sctp_tcb *stcb, struct sockaddr *to) { struct sockaddr_in *sin, *rsin; - sin = (struct sockaddr_in *)&laddr->ifa->address.sin; + sin = &laddr->ifa->address.sin; rsin = (struct sockaddr_in *)to; if (sin->sin_addr.s_addr == rsin->sin_addr.s_addr) { SCTP_IPI_ADDR_RUNLOCK(); @@ -1111,7 +1111,7 @@ sctp_does_stcb_own_this_addr(struct sctp_tcb *stcb, struct sockaddr *to) { struct sockaddr_in6 *sin6, *rsin6; - sin6 = (struct sockaddr_in6 *)&laddr->ifa->address.sin6; + sin6 = &laddr->ifa->address.sin6; rsin6 = (struct sockaddr_in6 *)to; if (SCTP6_ARE_ADDR_EQUAL(sin6, rsin6)) { SCTP_IPI_ADDR_RUNLOCK(); @@ -1126,7 +1126,7 @@ sctp_does_stcb_own_this_addr(struct sctp_tcb *stcb, struct sockaddr *to) { struct sockaddr_conn *sconn, *rsconn; - sconn = (struct sockaddr_conn *)&laddr->ifa->address.sconn; + sconn = &laddr->ifa->address.sconn; rsconn = (struct sockaddr_conn *)to; if (sconn->sconn_addr == rsconn->sconn_addr) { SCTP_IPI_ADDR_RUNLOCK(); @@ -2680,7 +2680,7 @@ sctp_findassociation_ep_asconf(struct mbuf *m, int offset, struct sctp_inpcb **inp_p, struct sctp_nets **netp, uint32_t vrf_id) { struct sctp_tcb *stcb; - struct sockaddr_storage remote_store; + union sctp_sockstore remote_store; struct sctp_paramhdr parm_buf, *phdr; int ptype; int zero_address = 0; @@ -2719,7 +2719,7 @@ sctp_findassociation_ep_asconf(struct mbuf *m, int offset, __FUNCTION__); return (NULL); } - sin6 = (struct sockaddr_in6 *)&remote_store; + sin6 = &remote_store.sin6; sin6->sin6_family = AF_INET6; #ifdef HAVE_SIN6_LEN sin6->sin6_len = sizeof(*sin6); @@ -2748,7 +2748,7 @@ sctp_findassociation_ep_asconf(struct mbuf *m, int offset, __FUNCTION__); return (NULL); } - sin = (struct sockaddr_in *)&remote_store; + sin = &remote_store.sin; sin->sin_family = AF_INET; #ifdef HAVE_SIN_LEN sin->sin_len = sizeof(*sin); @@ -2773,7 +2773,7 @@ sctp_findassociation_ep_asconf(struct mbuf *m, int offset, } } else { stcb = sctp_findassociation_ep_addr(inp_p, - (struct sockaddr *)&remote_store, netp, + &remote_store.sa, netp, dst, NULL); } return (stcb); @@ -2841,7 +2841,13 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id) inp->partial_delivery_point = SCTP_SB_LIMIT_RCV(so) >> SCTP_PARTIAL_DELIVERY_SHIFT; inp->sctp_frag_point = SCTP_DEFAULT_MAXSEGMENT; inp->sctp_cmt_on_off = SCTP_BASE_SYSCTL(sctp_cmt_on_off); - inp->sctp_ecn_enable = SCTP_BASE_SYSCTL(sctp_ecn_enable); + inp->ecn_supported = (uint8_t)SCTP_BASE_SYSCTL(sctp_ecn_enable); + inp->prsctp_supported = (uint8_t)SCTP_BASE_SYSCTL(sctp_pr_enable); + inp->auth_supported = (uint8_t)SCTP_BASE_SYSCTL(sctp_auth_enable); + inp->asconf_supported = (uint8_t)SCTP_BASE_SYSCTL(sctp_asconf_enable); + inp->reconfig_supported = (uint8_t)SCTP_BASE_SYSCTL(sctp_reconfig_enable); + inp->nrsack_supported = (uint8_t)SCTP_BASE_SYSCTL(sctp_nrsack_enable); + inp->pktdrop_supported = (uint8_t)SCTP_BASE_SYSCTL(sctp_pktdrop_enable); #if defined(__Userspace__) inp->ulp_info = NULL; inp->recv_callback = NULL; @@ -3090,12 +3096,15 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id) */ m->local_hmacs = sctp_default_supported_hmaclist(); m->local_auth_chunks = sctp_alloc_chunklist(); + if (inp->asconf_supported) { + sctp_auth_add_chunk(SCTP_ASCONF, m->local_auth_chunks); + sctp_auth_add_chunk(SCTP_ASCONF_ACK, m->local_auth_chunks); + } m->default_dscp = 0; #ifdef INET6 m->default_flowlabel = 0; #endif m->port = 0; /* encapsulation disabled by default */ - sctp_auth_set_default_chunks(m->local_auth_chunks); LIST_INIT(&m->shared_keys); /* add default NULL key as key id 0 */ null_key = sctp_alloc_sharedkey(); @@ -3583,8 +3592,8 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr, last = MODULE_GLOBAL(ipport_lowlastauto); } else { #endif - first = MODULE_GLOBAL(ipport_firstauto); - last = MODULE_GLOBAL(ipport_lastauto); + first = MODULE_GLOBAL(ipport_firstauto); + last = MODULE_GLOBAL(ipport_lastauto); #if defined(__FreeBSD__) || defined(__APPLE__) } #endif @@ -3692,42 +3701,27 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr, * too (before adding). */ struct sctp_ifa *ifa; - struct sockaddr_storage store_sa; + union sctp_sockstore store; - memset(&store_sa, 0, sizeof(store_sa)); + memset(&store, 0, sizeof(store)); switch (addr->sa_family) { #ifdef INET case AF_INET: - { - struct sockaddr_in *sin; - - sin = (struct sockaddr_in *)&store_sa; - memcpy(sin, addr, sizeof(struct sockaddr_in)); - sin->sin_port = 0; + memcpy(&store.sin, addr, sizeof(struct sockaddr_in)); + store.sin.sin_port = 0; break; - } #endif #ifdef INET6 case AF_INET6: - { - struct sockaddr_in6 *sin6; - - sin6 = (struct sockaddr_in6 *)&store_sa; - memcpy(sin6, addr, sizeof(struct sockaddr_in6)); - sin6->sin6_port = 0; + memcpy(&store.sin6, addr, sizeof(struct sockaddr_in6)); + store.sin6.sin6_port = 0; break; - } #endif #if defined(__Userspace__) case AF_CONN: - { - struct sockaddr_conn *sconn; - - sconn = (struct sockaddr_conn *)&store_sa; - memcpy(sconn, addr, sizeof(struct sockaddr_conn)); - sconn->sconn_port = 0; + memcpy(&store.sconn, addr, sizeof(struct sockaddr_conn)); + store.sconn.sconn_port = 0; break; - } #endif default: break; @@ -3744,7 +3738,7 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr, * O/S's will pass things in via the * sctp_ifap argument (Panda). */ - ifa = sctp_find_ifa_by_addr((struct sockaddr *)&store_sa, + ifa = sctp_find_ifa_by_addr(&store.sa, vrf_id, SCTP_ADDR_NOT_LOCKED); } if (ifa == NULL) { @@ -4615,7 +4609,7 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr, * this means its an initial value */ net->rto_needed = 1; - net->RTO = 0; + net->RTO = 0; net->RTO_measured = 0; stcb->asoc.numnets++; net->ref_count = 1; @@ -4668,7 +4662,9 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr, #endif SCTP_RTALLOC((sctp_route_t *)&net->ro, stcb->asoc.vrf_id); -#if !defined(__Userspace__) +#if defined(__Userspace__) + net->src_addr_selected = 0; +#else if (SCTP_ROUTE_HAS_VALID_IFN(&net->ro)) { /* Get source address */ net->ro._s_addr = sctp_source_address_selection(stcb->sctp_ep, @@ -4677,9 +4673,14 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr, net, 0, stcb->asoc.vrf_id); - /* Now get the interface MTU */ - if (net->ro._s_addr && net->ro._s_addr->ifn_p) { - net->mtu = SCTP_GATHER_MTU_FROM_INTFC(net->ro._s_addr->ifn_p); + if (net->ro._s_addr != NULL) { + net->src_addr_selected = 1; + /* Now get the interface MTU */ + if (net->ro._s_addr->ifn_p != NULL) { + net->mtu = SCTP_GATHER_MTU_FROM_INTFC(net->ro._s_addr->ifn_p); + } + } else { + net->src_addr_selected = 0; } if (net->mtu > 0) { uint32_t rmtu; @@ -4694,9 +4695,11 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr, * the route may be leading out the loopback, or * a different interface. */ - net->mtu = rmtu; + net->mtu = rmtu; } - } + } + } else { + net->src_addr_selected = 0; } #endif if (net->mtu == 0) { @@ -4720,7 +4723,7 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr, break; } } -#if defined INET || defined INET6 +#if defined(INET) || defined(INET6) if (net->port) { net->mtu -= (uint32_t)sizeof(struct udphdr); } @@ -4756,7 +4759,6 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr, */ net->find_pseudo_cumack = 1; net->find_rtx_pseudo_cumack = 1; - net->src_addr_selected = 0; #if defined(__FreeBSD__) /* Choose an initial flowid. */ net->flowid = stcb->asoc.my_vtag ^ @@ -5191,9 +5193,9 @@ sctp_remove_net(struct sctp_tcb *stcb, struct sctp_nets *net) (by micchie) */ if (sctp_is_mobility_feature_on(stcb->sctp_ep, - SCTP_MOBILITY_BASE) || + SCTP_MOBILITY_BASE) || sctp_is_mobility_feature_on(stcb->sctp_ep, - SCTP_MOBILITY_FASTHANDOFF)) { + SCTP_MOBILITY_FASTHANDOFF)) { SCTPDBG(SCTP_DEBUG_ASCONF1, "remove_net: primary dst is deleting\n"); if (asoc->deleted_primary != NULL) { SCTPDBG(SCTP_DEBUG_ASCONF1, "remove_net: deleted primary may be already stored\n"); @@ -6947,13 +6949,16 @@ sctp_pcb_finish(void) #endif #if !defined(__FreeBSD__) SCTP_IPI_ITERATOR_WQ_DESTROY(); - SCTP_ITERATOR_LOCK_DESTROY(); + SCTP_ITERATOR_LOCK_DESTROY(); #endif SCTP_OS_TIMER_STOP(&SCTP_BASE_INFO(addr_wq_timer.timer)); SCTP_WQ_ADDR_LOCK(); LIST_FOREACH_SAFE(wi, &SCTP_BASE_INFO(addr_wq), sctp_nxt_addr, nwi) { LIST_REMOVE(wi, sctp_nxt_addr); SCTP_DECR_LADDR_COUNT(); + if (wi->action == SCTP_DEL_IP_ADDRESS) { + SCTP_FREE(wi->ifa, SCTP_M_IFA); + } SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_laddr), wi); } SCTP_WQ_ADDR_UNLOCK(); @@ -7098,7 +7103,14 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m, sctp_key_t *new_key; uint32_t keylen; int got_random = 0, got_hmacs = 0, got_chklist = 0; - uint8_t ecn_allowed; + uint8_t peer_supports_ecn; + uint8_t peer_supports_prsctp; + uint8_t peer_supports_auth; + uint8_t peer_supports_asconf; + uint8_t peer_supports_asconf_ack; + uint8_t peer_supports_reconfig; + uint8_t peer_supports_nrsack; + uint8_t peer_supports_pktdrop; #ifdef INET struct sockaddr_in sin; #endif @@ -7128,8 +7140,13 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m, } else { sa = src; } - /* Turn off ECN until we get through all params */ - ecn_allowed = 0; + peer_supports_ecn = 0; + peer_supports_prsctp = 0; + peer_supports_auth = 0; + peer_supports_asconf = 0; + peer_supports_reconfig = 0; + peer_supports_nrsack = 0; + peer_supports_pktdrop = 0; TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { /* mark all addresses that we have currently on the list */ net->dest_state |= SCTP_ADDR_NOT_IN_ASSOC; @@ -7188,12 +7205,6 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m, /* the assoc was freed? */ return (-4); } - /* - * peer must explicitly turn this on. This may have been initialized - * to be "on" in order to allow local addr changes while INIT's are - * in flight. - */ - stcb->asoc.peer_supports_asconf = 0; /* now we must go through each of the params. */ phdr = sctp_get_next_param(m, offset, &parm_buf, sizeof(parm_buf)); while (phdr) { @@ -7379,7 +7390,7 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m, } else #endif if (ptype == SCTP_ECN_CAPABLE) { - ecn_allowed = 1; + peer_supports_ecn = 1; } else if (ptype == SCTP_ULP_ADAPTATION) { if (stcb->asoc.state != SCTP_STATE_OPEN) { struct sctp_adaptation_layer_indication ai, *aip; @@ -7400,7 +7411,9 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m, struct sctp_asconf_addrv4_param *fii; #endif - stcb->asoc.peer_supports_asconf = 1; + if (stcb->asoc.asconf_supported == 0) { + return (-100); + } if (plen > sizeof(lstore)) { return (-23); } @@ -7452,7 +7465,7 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m, stcb->asoc.peer_supports_nat = 1; } else if (ptype == SCTP_PRSCTP_SUPPORTED) { /* Peer supports pr-sctp */ - stcb->asoc.peer_supports_prsctp = 1; + peer_supports_prsctp = 1; } else if (ptype == SCTP_SUPPORTED_CHUNK_EXT) { /* A supported extension chunk */ struct sctp_supported_chunk_types_param *pr_supported; @@ -7464,34 +7477,29 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m, if (phdr == NULL) { return (-25); } - stcb->asoc.peer_supports_asconf = 0; - stcb->asoc.peer_supports_prsctp = 0; - stcb->asoc.peer_supports_pktdrop = 0; - stcb->asoc.peer_supports_strreset = 0; - stcb->asoc.peer_supports_nr_sack = 0; - stcb->asoc.peer_supports_auth = 0; pr_supported = (struct sctp_supported_chunk_types_param *)phdr; num_ent = plen - sizeof(struct sctp_paramhdr); for (i = 0; i < num_ent; i++) { switch (pr_supported->chunk_types[i]) { case SCTP_ASCONF: + peer_supports_asconf = 1; case SCTP_ASCONF_ACK: - stcb->asoc.peer_supports_asconf = 1; + peer_supports_asconf_ack = 1; break; case SCTP_FORWARD_CUM_TSN: - stcb->asoc.peer_supports_prsctp = 1; + peer_supports_prsctp = 1; break; case SCTP_PACKET_DROPPED: - stcb->asoc.peer_supports_pktdrop = 1; + peer_supports_pktdrop = 1; break; case SCTP_NR_SELECTIVE_ACK: - stcb->asoc.peer_supports_nr_sack = 1; + peer_supports_nrsack = 1; break; case SCTP_STREAM_RESET: - stcb->asoc.peer_supports_strreset = 1; + peer_supports_reconfig = 1; break; case SCTP_AUTHENTICATION: - stcb->asoc.peer_supports_auth = 1; + peer_supports_auth = 1; break; default: /* one I have not learned yet */ @@ -7628,24 +7636,47 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m, } } } - if (ecn_allowed == 0) { - stcb->asoc.ecn_allowed = 0; + if ((stcb->asoc.ecn_supported == 1) && + (peer_supports_ecn == 0)) { + stcb->asoc.ecn_supported = 0; } - /* validate authentication required parameters */ - if (got_random && got_hmacs) { - stcb->asoc.peer_supports_auth = 1; - } else { - stcb->asoc.peer_supports_auth = 0; + if ((stcb->asoc.prsctp_supported == 1) && + (peer_supports_prsctp == 0)) { + stcb->asoc.prsctp_supported = 0; + } + if ((stcb->asoc.auth_supported == 1) && + ((peer_supports_auth == 0) || + (got_random == 0) || (got_hmacs == 0))) { + stcb->asoc.auth_supported = 0; + } + if ((stcb->asoc.asconf_supported == 1) && + ((peer_supports_asconf == 0) || (peer_supports_asconf_ack == 0) || + (stcb->asoc.auth_supported == 0) || + (saw_asconf == 0) || (saw_asconf_ack == 0))) { + stcb->asoc.asconf_supported = 0; } - if (!stcb->asoc.peer_supports_auth && got_chklist) { + if ((stcb->asoc.reconfig_supported == 1) && + (peer_supports_reconfig == 0)) { + stcb->asoc.reconfig_supported = 0; + } + if ((stcb->asoc.nrsack_supported == 1) && + (peer_supports_nrsack == 0)) { + stcb->asoc.nrsack_supported = 0; + } + if ((stcb->asoc.pktdrop_supported == 1) && + (peer_supports_pktdrop == 0)){ + stcb->asoc.pktdrop_supported = 0; + } + /* validate authentication required parameters */ + if ((peer_supports_auth == 0) && (got_chklist == 1)) { /* peer does not support auth but sent a chunks list? */ return (-31); } - if (!SCTP_BASE_SYSCTL(sctp_asconf_auth_nochk) && stcb->asoc.peer_supports_asconf && - !stcb->asoc.peer_supports_auth) { + if ((peer_supports_asconf == 1) && (peer_supports_auth == 0)) { /* peer supports asconf but not auth? */ return (-32); - } else if ((stcb->asoc.peer_supports_asconf) && (stcb->asoc.peer_supports_auth) && + } else if ((peer_supports_asconf == 1) && + (peer_supports_auth == 1) && ((saw_asconf == 0) || (saw_asconf_ack == 0))) { return (-33); } diff --git a/netinet/sctp_pcb.h b/netinet/sctp_pcb.h index bcd2864..d09bb59 100755 --- a/netinet/sctp_pcb.h +++ b/netinet/sctp_pcb.h @@ -32,7 +32,7 @@ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_pcb.h 254248 2013-08-12 13:52:15Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp_pcb.h 269858 2014-08-12 11:30:16Z tuexen $"); #endif #ifndef _NETINET_SCTP_PCB_H_ @@ -110,7 +110,7 @@ struct sctp_ifa { */ union sctp_sockstore address; uint32_t refcount; /* number of folks refering to this */ - uint32_t flags; + uint32_t flags; uint32_t localifa_flags; uint32_t vrf_id; /* vrf_id of this addr (for deleting) */ uint8_t src_is_loop; @@ -480,7 +480,13 @@ struct sctp_inpcb { uint32_t sctp_context; uint8_t local_strreset_support; uint32_t sctp_cmt_on_off; - uint32_t sctp_ecn_enable; + uint8_t ecn_supported; + uint8_t prsctp_supported; + uint8_t auth_supported; + uint8_t asconf_supported; + uint8_t reconfig_supported; + uint8_t nrsack_supported; + uint8_t pktdrop_supported; struct sctp_nonpad_sndrcvinfo def_send; /*- * These three are here for the sosend_dgram diff --git a/netinet/sctp_peeloff.c b/netinet/sctp_peeloff.c index bba97f6..beb11fb 100755 --- a/netinet/sctp_peeloff.c +++ b/netinet/sctp_peeloff.c @@ -32,7 +32,7 @@ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_peeloff.c 243565 2012-11-26 16:44:03Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp_peeloff.c 269858 2014-08-12 11:30:16Z tuexen $"); #endif #include <netinet/sctp_os.h> @@ -125,7 +125,13 @@ sctp_do_peeloff(struct socket *head, struct socket *so, sctp_assoc_t assoc_id) n_inp->sctp_mobility_features = inp->sctp_mobility_features; n_inp->sctp_frag_point = inp->sctp_frag_point; n_inp->sctp_cmt_on_off = inp->sctp_cmt_on_off; - n_inp->sctp_ecn_enable = inp->sctp_ecn_enable; + n_inp->ecn_supported = inp->ecn_supported; + n_inp->prsctp_supported = inp->prsctp_supported; + n_inp->auth_supported = inp->auth_supported; + n_inp->asconf_supported = inp->asconf_supported; + n_inp->reconfig_supported = inp->reconfig_supported; + n_inp->nrsack_supported = inp->nrsack_supported; + n_inp->pktdrop_supported = inp->pktdrop_supported; n_inp->partial_delivery_point = inp->partial_delivery_point; n_inp->sctp_context = inp->sctp_context; n_inp->local_strreset_support = inp->local_strreset_support; @@ -234,7 +240,13 @@ sctp_get_peeloff(struct socket *head, sctp_assoc_t assoc_id, int *error) n_inp->sctp_features = inp->sctp_features; n_inp->sctp_frag_point = inp->sctp_frag_point; n_inp->sctp_cmt_on_off = inp->sctp_cmt_on_off; - n_inp->sctp_ecn_enable = inp->sctp_ecn_enable; + n_inp->ecn_supported = inp->ecn_supported; + n_inp->prsctp_supported = inp->prsctp_supported; + n_inp->auth_supported = inp->auth_supported; + n_inp->asconf_supported = inp->asconf_supported; + n_inp->reconfig_supported = inp->reconfig_supported; + n_inp->nrsack_supported = inp->nrsack_supported; + n_inp->pktdrop_supported = inp->pktdrop_supported; n_inp->partial_delivery_point = inp->partial_delivery_point; n_inp->sctp_context = inp->sctp_context; n_inp->local_strreset_support = inp->local_strreset_support; diff --git a/netinet/sctp_structs.h b/netinet/sctp_structs.h index f333ec8..7214d8d 100755 --- a/netinet/sctp_structs.h +++ b/netinet/sctp_structs.h @@ -32,7 +32,7 @@ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_structs.h 255190 2013-09-03 19:31:59Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp_structs.h 269945 2014-08-13 15:50:16Z tuexen $"); #endif #ifndef _NETINET_SCTP_STRUCTS_H_ @@ -636,6 +636,14 @@ struct sctp_stream_out { struct sctp_streamhead outqueue; union scheduling_parameters ss_params; uint32_t chunks_on_queues; +#if defined(SCTP_DETAILED_STR_STATS) + uint32_t abandoned_unsent[SCTP_PR_SCTP_MAX + 1]; + uint32_t abandoned_sent[SCTP_PR_SCTP_MAX + 1]; +#else + /* Only the aggregation */ + uint32_t abandoned_unsent[1]; + uint32_t abandoned_sent[1]; +#endif uint16_t stream_no; uint16_t next_sequence_send; /* next one I expect to send out */ uint8_t last_msg_incomplete; @@ -714,8 +722,8 @@ struct sctp_nonpad_sndrcvinfo { struct sctp_cc_functions { void (*sctp_set_initial_cc_param)(struct sctp_tcb *stcb, struct sctp_nets *net); void (*sctp_cwnd_update_after_sack)(struct sctp_tcb *stcb, - struct sctp_association *asoc, - int accum_moved ,int reneged_all, int will_exit); + struct sctp_association *asoc, + int accum_moved ,int reneged_all, int will_exit); void (*sctp_cwnd_update_exit_pf)(struct sctp_tcb *stcb, struct sctp_nets *net); void (*sctp_cwnd_update_after_fr)(struct sctp_tcb *stcb, struct sctp_association *asoc); @@ -1200,30 +1208,21 @@ struct sctp_association { * sum is updated as well. */ - /* Flag to tell if ECN is allowed */ - uint8_t ecn_allowed; + /* Flags whether an extension is supported or not */ + uint8_t ecn_supported; + uint8_t prsctp_supported; + uint8_t auth_supported; + uint8_t asconf_supported; + uint8_t reconfig_supported; + uint8_t nrsack_supported; + uint8_t pktdrop_supported; /* Did the peer make the stream config (add out) request */ uint8_t peer_req_out; - /* flag to indicate if peer can do asconf */ - uint8_t peer_supports_asconf; - /* EY - flag to indicate if peer can do nr_sack*/ - uint8_t peer_supports_nr_sack; - /* pr-sctp support flag */ - uint8_t peer_supports_prsctp; - /* peer authentication support flag */ - uint8_t peer_supports_auth; - /* stream resets are supported by the peer */ - uint8_t peer_supports_strreset; uint8_t local_strreset_support; - uint8_t peer_supports_nat; - /* - * packet drop's are supported by the peer, we don't really care - * about this but we bookkeep it anyway. - */ - uint8_t peer_supports_pktdrop; + uint8_t peer_supports_nat; struct sctp_scoping scope; /* flags to handle send alternate net tracking */ @@ -1248,8 +1247,6 @@ struct sctp_association { uint8_t sctp_cmt_on_off; uint8_t iam_blocking; uint8_t cookie_how[8]; - /* EY 05/05/08 - NR_SACK variable*/ - uint8_t sctp_nr_sack_on_off; /* JRS 5/21/07 - CMT PF variable */ uint8_t sctp_cmt_pf; uint8_t use_precise_time; @@ -1272,6 +1269,8 @@ struct sctp_association { uint32_t timoshutdownack; struct timeval start_time; struct timeval discontinuity_time; + uint64_t abandoned_unsent[SCTP_PR_SCTP_MAX + 1]; + uint64_t abandoned_sent[SCTP_PR_SCTP_MAX + 1]; }; #endif diff --git a/netinet/sctp_sysctl.c b/netinet/sctp_sysctl.c index 21329f0..5b2a483 100755 --- a/netinet/sctp_sysctl.c +++ b/netinet/sctp_sysctl.c @@ -32,7 +32,7 @@ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_sysctl.c 267674 2014-06-20 13:26:49Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp_sysctl.c 271221 2014-09-07 09:06:26Z tuexen $"); #endif #include <netinet/sctp_os.h> @@ -44,11 +44,16 @@ __FBSDID("$FreeBSD: head/sys/netinet/sctp_sysctl.c 267674 2014-06-20 13:26:49Z t #include <netinet/sctp_output.h> #ifdef __FreeBSD__ #include <sys/smp.h> +#include <sys/sysctl.h> #endif #if defined(__APPLE__) #include <netinet/sctp_bsd_addr.h> #endif +#ifdef __FreeBSD__ +FEATURE(sctp, "Stream Control Transmission Protocol"); +#endif + /* * sysctl tunable variables */ @@ -61,6 +66,12 @@ sctp_init_sysctls() SCTP_BASE_SYSCTL(sctp_auto_asconf) = SCTPCTL_AUTOASCONF_DEFAULT; SCTP_BASE_SYSCTL(sctp_multiple_asconfs) = SCTPCTL_MULTIPLEASCONFS_DEFAULT; SCTP_BASE_SYSCTL(sctp_ecn_enable) = SCTPCTL_ECN_ENABLE_DEFAULT; + SCTP_BASE_SYSCTL(sctp_pr_enable) = SCTPCTL_PR_ENABLE_DEFAULT; + SCTP_BASE_SYSCTL(sctp_auth_enable) = SCTPCTL_AUTH_ENABLE_DEFAULT; + SCTP_BASE_SYSCTL(sctp_asconf_enable) = SCTPCTL_ASCONF_ENABLE_DEFAULT; + SCTP_BASE_SYSCTL(sctp_reconfig_enable) = SCTPCTL_RECONFIG_ENABLE_DEFAULT; + SCTP_BASE_SYSCTL(sctp_nrsack_enable) = SCTPCTL_NRSACK_ENABLE_DEFAULT; + SCTP_BASE_SYSCTL(sctp_pktdrop_enable) = SCTPCTL_PKTDROP_ENABLE_DEFAULT; SCTP_BASE_SYSCTL(sctp_strict_sacks) = SCTPCTL_STRICT_SACKS_DEFAULT; #if !(defined(__FreeBSD__) && __FreeBSD_version >= 800000) #if !defined(SCTP_WITH_NO_CSUM) @@ -96,12 +107,8 @@ sctp_init_sysctls() 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; SCTP_BASE_SYSCTL(sctp_nat_friendly) = SCTPCTL_NAT_FRIENDLY_DEFAULT; SCTP_BASE_SYSCTL(sctp_L2_abc_variable) = SCTPCTL_ABC_L_VAR_DEFAULT; SCTP_BASE_SYSCTL(sctp_mbuf_threshold_count) = SCTPCTL_MAX_CHAINED_MBUFS_DEFAULT; @@ -112,9 +119,7 @@ sctp_init_sysctls() SCTP_BASE_SYSCTL(sctp_min_residual) = SCTPCTL_MIN_RESIDUAL_DEFAULT; SCTP_BASE_SYSCTL(sctp_max_retran_chunk) = SCTPCTL_MAX_RETRAN_CHUNK_DEFAULT; SCTP_BASE_SYSCTL(sctp_logging_level) = SCTPCTL_LOGGING_LEVEL_DEFAULT; - /* JRS - Variable for default congestion control module */ SCTP_BASE_SYSCTL(sctp_default_cc_module) = SCTPCTL_DEFAULT_CC_MODULE_DEFAULT; - /* RS - Variable for default stream scheduling module */ SCTP_BASE_SYSCTL(sctp_default_ss_module) = SCTPCTL_DEFAULT_SS_MODULE_DEFAULT; SCTP_BASE_SYSCTL(sctp_default_frag_interleave) = SCTPCTL_DEFAULT_FRAG_INTERLEAVE_DEFAULT; SCTP_BASE_SYSCTL(sctp_mobility_base) = SCTPCTL_MOBILITY_BASE_DEFAULT; @@ -170,7 +175,7 @@ sctp_finish_sysctls() #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__Windows__) /* It returns an upper limit. No filtering is done here */ static unsigned int -number_of_addresses(struct sctp_inpcb *inp) +sctp_sysctl_number_of_addresses(struct sctp_inpcb *inp) { unsigned int cnt; struct sctp_vrf *vrf; @@ -220,7 +225,7 @@ number_of_addresses(struct sctp_inpcb *inp) } static int -copy_out_local_addresses(struct sctp_inpcb *inp, struct sctp_tcb *stcb, struct sysctl_req *req) +sctp_sysctl_copy_out_local_addresses(struct sctp_inpcb *inp, struct sctp_tcb *stcb, struct sysctl_req *req) { struct sctp_ifn *sctp_ifn; struct sctp_ifa *sctp_ifa; @@ -304,7 +309,7 @@ copy_out_local_addresses(struct sctp_inpcb *inp, struct sctp_tcb *stcb, struct s if (ipv4_addr_legal) { struct sockaddr_in *sin; - sin = (struct sockaddr_in *)&sctp_ifa->address.sa; + sin = &sctp_ifa->address.sin; if (sin->sin_addr.s_addr == 0) continue; #if defined(__FreeBSD__) @@ -328,7 +333,7 @@ copy_out_local_addresses(struct sctp_inpcb *inp, struct sctp_tcb *stcb, struct s #if defined(SCTP_EMBEDDED_V6_SCOPE) && !defined(SCTP_KAME) struct sockaddr_in6 lsa6; #endif - sin6 = (struct sockaddr_in6 *)&sctp_ifa->address.sa; + sin6 = &sctp_ifa->address.sin6; if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) continue; #if defined(__FreeBSD__) @@ -426,12 +431,12 @@ copy_out_local_addresses(struct sctp_inpcb *inp, struct sctp_tcb *stcb, struct s */ #if defined(__APPLE__) static int -sctp_assoclist SYSCTL_HANDLER_ARGS +sctp_sysctl_handle_assoclist SYSCTL_HANDLER_ARGS { #pragma unused(oidp, arg1, arg2) #else static int -sctp_assoclist(SYSCTL_HANDLER_ARGS) +sctp_sysctl_handle_assoclist(SYSCTL_HANDLER_ARGS) { #endif unsigned int number_of_endpoints; @@ -454,18 +459,18 @@ sctp_assoclist(SYSCTL_HANDLER_ARGS) number_of_remote_addresses = 0; SCTP_INP_INFO_RLOCK(); -#if !defined(__Windows__) +#if defined(__APPLE__) if (req->oldptr == USER_ADDR_NULL) { #else - if (req->data == NULL) { + if (req->oldptr == NULL) { #endif LIST_FOREACH(inp, &SCTP_BASE_INFO(listhead), sctp_list) { SCTP_INP_RLOCK(inp); number_of_endpoints++; - number_of_local_addresses += number_of_addresses(inp); + number_of_local_addresses += sctp_sysctl_number_of_addresses(inp); LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) { number_of_associations++; - number_of_local_addresses += number_of_addresses(inp); + number_of_local_addresses += sctp_sysctl_number_of_addresses(inp); TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { number_of_remote_addresses++; } @@ -486,10 +491,10 @@ sctp_assoclist(SYSCTL_HANDLER_ARGS) #endif return (0); } -#if !defined(__Windows__) +#if defined(__APPLE__) if (req->newptr != USER_ADDR_NULL) { #else - if (req->new_data != NULL) { + if (req->newptr != NULL) { #endif SCTP_INP_INFO_RUNLOCK(); SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_SYSCTL, EPERM); @@ -532,7 +537,7 @@ sctp_assoclist(SYSCTL_HANDLER_ARGS) } SCTP_INP_INFO_RLOCK(); SCTP_INP_RLOCK(inp); - error = copy_out_local_addresses(inp, NULL, req); + error = sctp_sysctl_copy_out_local_addresses(inp, NULL, req); if (error) { SCTP_INP_DECR_REF(inp); return (error); @@ -589,7 +594,7 @@ sctp_assoclist(SYSCTL_HANDLER_ARGS) } SCTP_INP_INFO_RLOCK(); SCTP_INP_RLOCK(inp); - error = copy_out_local_addresses(inp, stcb, req); + error = sctp_sysctl_copy_out_local_addresses(inp, stcb, req); if (error) { SCTP_INP_DECR_REF(inp); atomic_subtract_int(&stcb->asoc.refcnt, 1); @@ -664,57 +669,59 @@ skip: return (error); } - -#if !defined(__Windows__) -#define RANGECHK(var, min, max) \ - if ((var) < (min)) { (var) = (min); } \ - else if ((var) > (max)) { (var) = (max); } -#else -#define RANGECHK(var, min, max) \ - if ((var) <= (min)) { (var) = (min); } \ - else if ((var) >= (max)) { (var) = (max); } -#endif - #if defined(__APPLE__) static int -sysctl_sctp_udp_tunneling_check SYSCTL_HANDLER_ARGS +sctp_sysctl_handle_udp_tunneling SYSCTL_HANDLER_ARGS { #pragma unused(arg1, arg2) #else static int -sysctl_sctp_udp_tunneling_check(SYSCTL_HANDLER_ARGS) +sctp_sysctl_handle_udp_tunneling(SYSCTL_HANDLER_ARGS) { #endif int error; - uint32_t old_sctp_udp_tunneling_port; + uint32_t old, new; SCTP_INP_INFO_RLOCK(); - old_sctp_udp_tunneling_port = SCTP_BASE_SYSCTL(sctp_udp_tunneling_port); + old = SCTP_BASE_SYSCTL(sctp_udp_tunneling_port); SCTP_INP_INFO_RUNLOCK(); - error = sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2, req); - if (error == 0) { - RANGECHK(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port), SCTPCTL_UDP_TUNNELING_PORT_MIN, SCTPCTL_UDP_TUNNELING_PORT_MAX); -#if !defined(__Windows__) - if (old_sctp_udp_tunneling_port == SCTP_BASE_SYSCTL(sctp_udp_tunneling_port)) { - error = 0; - goto out; - } - SCTP_INP_INFO_WLOCK(); - if (old_sctp_udp_tunneling_port) { - sctp_over_udp_stop(); - } - if (SCTP_BASE_SYSCTL(sctp_udp_tunneling_port)) { - if (sctp_over_udp_start()) { - SCTP_BASE_SYSCTL(sctp_udp_tunneling_port) = 0; - } - } + new = old; +#if defined(__FreeBSD__) && __FreeBSD_version >= 800056 && __FreeBSD_version < 1000100 +#ifdef VIMAGE + error = vnet_sysctl_handle_int(oidp, &new, 0, req); +#else + error = sysctl_handle_int(oidp, &new, 0, req); +#endif +#else + error = sysctl_handle_int(oidp, &new, 0, req); +#endif + if ((error == 0) && +#if defined (__APPLE__) + (req->newptr != USER_ADDR_NULL)) { #else + (req->newptr != NULL)) { +#endif +#if defined(__Windows__) SCTP_INP_INFO_WLOCK(); sctp_over_udp_restart(); -#endif SCTP_INP_INFO_WUNLOCK(); +#else + if ((new < SCTPCTL_UDP_TUNNELING_PORT_MIN) || + (new > SCTPCTL_UDP_TUNNELING_PORT_MAX)) { + error = EINVAL; + } else { + SCTP_INP_INFO_WLOCK(); + SCTP_BASE_SYSCTL(sctp_udp_tunneling_port) = new; + if (old != 0) { + sctp_over_udp_stop(); + } + if (new != 0) { + error = sctp_over_udp_start(); + } + SCTP_INP_INFO_WUNLOCK(); + } +#endif } -out: return (error); } @@ -722,21 +729,29 @@ out: int sctp_is_vmware_interface(struct ifnet *); static int -sysctl_sctp_vmware_interfaces_check SYSCTL_HANDLER_ARGS +sctp_sysctl_handle_vmware_interfaces SYSCTL_HANDLER_ARGS { #pragma unused(arg1, arg2) int error; - uint32_t old_sctp_ignore_vmware_interfaces; - - old_sctp_ignore_vmware_interfaces = SCTP_BASE_SYSCTL(sctp_ignore_vmware_interfaces); - error = sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2, req); - if (error == 0) { - RANGECHK(SCTP_BASE_SYSCTL(sctp_ignore_vmware_interfaces), SCTPCTL_IGNORE_VMWARE_INTERFACES_MIN, SCTPCTL_IGNORE_VMWARE_INTERFACES_MAX); - if (old_sctp_ignore_vmware_interfaces && !SCTP_BASE_SYSCTL(sctp_ignore_vmware_interfaces)) { - sctp_add_or_del_interfaces(sctp_is_vmware_interface, 1); - } - if (!old_sctp_ignore_vmware_interfaces && SCTP_BASE_SYSCTL(sctp_ignore_vmware_interfaces)) { - sctp_add_or_del_interfaces(sctp_is_vmware_interface, 0); + uint32_t old, new; + + old = SCTP_BASE_SYSCTL(sctp_ignore_vmware_interfaces); + new = old; + error = sysctl_handle_int(oidp, &new, 0, req); + if ((error == 0) && (req->newptr != USER_ADDR_NULL)) { + if ((new < SCTPCTL_IGNORE_VMWARE_INTERFACES_MIN) || + (new > SCTPCTL_IGNORE_VMWARE_INTERFACES_MAX)) { + error = EINVAL; + } else { + if ((old == 1) && (new == 0)) { + sctp_add_or_del_interfaces(sctp_is_vmware_interface, 1); + } + if ((old == 0) && (new == 1)) { + sctp_add_or_del_interfaces(sctp_is_vmware_interface, 0); + } + if (old != new) { + SCTP_BASE_SYSCTL(sctp_ignore_vmware_interfaces) = new; + } } } return (error); @@ -745,143 +760,113 @@ sysctl_sctp_vmware_interfaces_check SYSCTL_HANDLER_ARGS #if defined(__APPLE__) static int -sysctl_sctp_check SYSCTL_HANDLER_ARGS +sctp_sysctl_handle_auth SYSCTL_HANDLER_ARGS { #pragma unused(arg1, arg2) #else static int -sysctl_sctp_check(SYSCTL_HANDLER_ARGS) +sctp_sysctl_handle_auth(SYSCTL_HANDLER_ARGS) { #endif int error; + uint32_t new; + new = SCTP_BASE_SYSCTL(sctp_auth_enable); #if defined(__FreeBSD__) && __FreeBSD_version >= 800056 && __FreeBSD_version < 1000100 #ifdef VIMAGE - error = vnet_sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2, req); + error = vnet_sysctl_handle_int(oidp, &new, 0, req); #else - error = sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2, req); + error = sysctl_handle_int(oidp, &new, 0, req); #endif #else - error = sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2, req); -#endif - if (error == 0) { - RANGECHK(SCTP_BASE_SYSCTL(sctp_sendspace), SCTPCTL_MAXDGRAM_MIN, SCTPCTL_MAXDGRAM_MAX); - RANGECHK(SCTP_BASE_SYSCTL(sctp_recvspace), SCTPCTL_RECVSPACE_MIN, SCTPCTL_RECVSPACE_MAX); -#if defined(__FreeBSD__) - RANGECHK(SCTP_BASE_SYSCTL(sctp_auto_asconf), SCTPCTL_AUTOASCONF_MIN, SCTPCTL_AUTOASCONF_MAX); -#elif defined(SCTP_APPLE_AUTO_ASCONF) - RANGECHK(SCTP_BASE_SYSCTL(sctp_auto_asconf), SCTPCTL_AUTOASCONF_MIN, SCTPCTL_AUTOASCONF_MAX); -#endif - RANGECHK(SCTP_BASE_SYSCTL(sctp_ecn_enable), SCTPCTL_ECN_ENABLE_MIN, SCTPCTL_ECN_ENABLE_MAX); - RANGECHK(SCTP_BASE_SYSCTL(sctp_strict_sacks), SCTPCTL_STRICT_SACKS_MIN, SCTPCTL_STRICT_SACKS_MAX); -#if !(defined(__FreeBSD__) && __FreeBSD_version >= 800000) -#if !defined(SCTP_WITH_NO_CSUM) - RANGECHK(SCTP_BASE_SYSCTL(sctp_no_csum_on_loopback), SCTPCTL_LOOPBACK_NOCSUM_MIN, SCTPCTL_LOOPBACK_NOCSUM_MAX); -#endif + error = sysctl_handle_int(oidp, &new, 0, req); #endif - RANGECHK(SCTP_BASE_SYSCTL(sctp_peer_chunk_oh), SCTPCTL_PEER_CHKOH_MIN, SCTPCTL_PEER_CHKOH_MAX); - RANGECHK(SCTP_BASE_SYSCTL(sctp_max_burst_default), SCTPCTL_MAXBURST_MIN, SCTPCTL_MAXBURST_MAX); - RANGECHK(SCTP_BASE_SYSCTL(sctp_fr_max_burst_default), SCTPCTL_FRMAXBURST_MIN, SCTPCTL_FRMAXBURST_MAX); - RANGECHK(SCTP_BASE_SYSCTL(sctp_max_chunks_on_queue), SCTPCTL_MAXCHUNKS_MIN, SCTPCTL_MAXCHUNKS_MAX); - RANGECHK(SCTP_BASE_SYSCTL(sctp_hashtblsize), SCTPCTL_TCBHASHSIZE_MIN, SCTPCTL_TCBHASHSIZE_MAX); - RANGECHK(SCTP_BASE_SYSCTL(sctp_pcbtblsize), SCTPCTL_PCBHASHSIZE_MIN, SCTPCTL_PCBHASHSIZE_MAX); - RANGECHK(SCTP_BASE_SYSCTL(sctp_min_split_point), SCTPCTL_MIN_SPLIT_POINT_MIN, SCTPCTL_MIN_SPLIT_POINT_MAX); - RANGECHK(SCTP_BASE_SYSCTL(sctp_chunkscale), SCTPCTL_CHUNKSCALE_MIN, SCTPCTL_CHUNKSCALE_MAX); - RANGECHK(SCTP_BASE_SYSCTL(sctp_delayed_sack_time_default), SCTPCTL_DELAYED_SACK_TIME_MIN, SCTPCTL_DELAYED_SACK_TIME_MAX); - RANGECHK(SCTP_BASE_SYSCTL(sctp_sack_freq_default), SCTPCTL_SACK_FREQ_MIN, SCTPCTL_SACK_FREQ_MAX); - RANGECHK(SCTP_BASE_SYSCTL(sctp_system_free_resc_limit), SCTPCTL_SYS_RESOURCE_MIN, SCTPCTL_SYS_RESOURCE_MAX); - RANGECHK(SCTP_BASE_SYSCTL(sctp_asoc_free_resc_limit), SCTPCTL_ASOC_RESOURCE_MIN, SCTPCTL_ASOC_RESOURCE_MAX); - RANGECHK(SCTP_BASE_SYSCTL(sctp_heartbeat_interval_default), SCTPCTL_HEARTBEAT_INTERVAL_MIN, SCTPCTL_HEARTBEAT_INTERVAL_MAX); - RANGECHK(SCTP_BASE_SYSCTL(sctp_pmtu_raise_time_default), SCTPCTL_PMTU_RAISE_TIME_MIN, SCTPCTL_PMTU_RAISE_TIME_MAX); - RANGECHK(SCTP_BASE_SYSCTL(sctp_shutdown_guard_time_default), SCTPCTL_SHUTDOWN_GUARD_TIME_MIN, SCTPCTL_SHUTDOWN_GUARD_TIME_MAX); - RANGECHK(SCTP_BASE_SYSCTL(sctp_secret_lifetime_default), SCTPCTL_SECRET_LIFETIME_MIN, SCTPCTL_SECRET_LIFETIME_MAX); - RANGECHK(SCTP_BASE_SYSCTL(sctp_rto_max_default), SCTPCTL_RTO_MAX_MIN, SCTPCTL_RTO_MAX_MAX); - RANGECHK(SCTP_BASE_SYSCTL(sctp_rto_min_default), SCTPCTL_RTO_MIN_MIN, SCTPCTL_RTO_MIN_MAX); - 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); - RANGECHK(SCTP_BASE_SYSCTL(sctp_nat_friendly), SCTPCTL_NAT_FRIENDLY_MIN, SCTPCTL_NAT_FRIENDLY_MAX); - RANGECHK(SCTP_BASE_SYSCTL(sctp_L2_abc_variable), SCTPCTL_ABC_L_VAR_MIN, SCTPCTL_ABC_L_VAR_MAX); - RANGECHK(SCTP_BASE_SYSCTL(sctp_mbuf_threshold_count), SCTPCTL_MAX_CHAINED_MBUFS_MIN, SCTPCTL_MAX_CHAINED_MBUFS_MAX); - RANGECHK(SCTP_BASE_SYSCTL(sctp_do_drain), SCTPCTL_DO_SCTP_DRAIN_MIN, SCTPCTL_DO_SCTP_DRAIN_MAX); - RANGECHK(SCTP_BASE_SYSCTL(sctp_hb_maxburst), SCTPCTL_HB_MAX_BURST_MIN, SCTPCTL_HB_MAX_BURST_MAX); - RANGECHK(SCTP_BASE_SYSCTL(sctp_abort_if_one_2_one_hits_limit), SCTPCTL_ABORT_AT_LIMIT_MIN, SCTPCTL_ABORT_AT_LIMIT_MAX); - RANGECHK(SCTP_BASE_SYSCTL(sctp_strict_data_order), SCTPCTL_STRICT_DATA_ORDER_MIN, SCTPCTL_STRICT_DATA_ORDER_MAX); - RANGECHK(SCTP_BASE_SYSCTL(sctp_min_residual), SCTPCTL_MIN_RESIDUAL_MIN, SCTPCTL_MIN_RESIDUAL_MAX); - RANGECHK(SCTP_BASE_SYSCTL(sctp_max_retran_chunk), SCTPCTL_MAX_RETRAN_CHUNK_MIN, SCTPCTL_MAX_RETRAN_CHUNK_MAX); - RANGECHK(SCTP_BASE_SYSCTL(sctp_logging_level), SCTPCTL_LOGGING_LEVEL_MIN, SCTPCTL_LOGGING_LEVEL_MAX); - RANGECHK(SCTP_BASE_SYSCTL(sctp_default_cc_module), SCTPCTL_DEFAULT_CC_MODULE_MIN, SCTPCTL_DEFAULT_CC_MODULE_MAX); - RANGECHK(SCTP_BASE_SYSCTL(sctp_default_ss_module), SCTPCTL_DEFAULT_SS_MODULE_MIN, SCTPCTL_DEFAULT_SS_MODULE_MAX); - RANGECHK(SCTP_BASE_SYSCTL(sctp_default_frag_interleave), SCTPCTL_DEFAULT_FRAG_INTERLEAVE_MIN, SCTPCTL_DEFAULT_FRAG_INTERLEAVE_MAX); - RANGECHK(SCTP_BASE_SYSCTL(sctp_vtag_time_wait), SCTPCTL_TIME_WAIT_MIN, SCTPCTL_TIME_WAIT_MAX); - RANGECHK(SCTP_BASE_SYSCTL(sctp_buffer_splitting), SCTPCTL_BUFFER_SPLITTING_MIN, SCTPCTL_BUFFER_SPLITTING_MAX); - RANGECHK(SCTP_BASE_SYSCTL(sctp_initial_cwnd), SCTPCTL_INITIAL_CWND_MIN, SCTPCTL_INITIAL_CWND_MAX); - RANGECHK(SCTP_BASE_SYSCTL(sctp_rttvar_bw), SCTPCTL_RTTVAR_BW_MIN, SCTPCTL_RTTVAR_BW_MAX); - RANGECHK(SCTP_BASE_SYSCTL(sctp_rttvar_rtt), SCTPCTL_RTTVAR_RTT_MIN, SCTPCTL_RTTVAR_RTT_MAX); - RANGECHK(SCTP_BASE_SYSCTL(sctp_rttvar_eqret), SCTPCTL_RTTVAR_EQRET_MIN, SCTPCTL_RTTVAR_EQRET_MAX); - RANGECHK(SCTP_BASE_SYSCTL(sctp_steady_step), SCTPCTL_RTTVAR_STEADYS_MIN, SCTPCTL_RTTVAR_STEADYS_MAX); - RANGECHK(SCTP_BASE_SYSCTL(sctp_use_dccc_ecn), SCTPCTL_RTTVAR_DCCCECN_MIN, SCTPCTL_RTTVAR_DCCCECN_MAX); -#if defined(__FreeBSD__) - RANGECHK(SCTP_BASE_SYSCTL(sctp_mobility_base), SCTPCTL_MOBILITY_BASE_MIN, SCTPCTL_MOBILITY_BASE_MAX); -#elif defined(SCTP_APPLE_MOBILITY_BASE) - RANGECHK(SCTP_BASE_SYSCTL(sctp_mobility_base), SCTPCTL_MOBILITY_BASE_MIN, SCTPCTL_MOBILITY_BASE_MAX); + if ((error == 0) && +#if defined (__APPLE__) + (req->newptr != USER_ADDR_NULL)) { +#else + (req->newptr != NULL)) { #endif -#if defined(__FreeBSD__) - RANGECHK(SCTP_BASE_SYSCTL(sctp_mobility_fasthandoff), SCTPCTL_MOBILITY_FASTHANDOFF_MIN, SCTPCTL_MOBILITY_FASTHANDOFF_MAX); -#elif defined(__FreeBSD__) || defined(SCTP_APPLE_MOBILITY_FASTHANDOFF) - RANGECHK(SCTP_BASE_SYSCTL(sctp_mobility_fasthandoff), SCTPCTL_MOBILITY_FASTHANDOFF_MIN, SCTPCTL_MOBILITY_FASTHANDOFF_MAX); + if ((new < SCTPCTL_AUTH_ENABLE_MIN) || + (new > SCTPCTL_AUTH_ENABLE_MAX) || + ((new == 0) && (SCTP_BASE_SYSCTL(sctp_asconf_enable) == 1))) { + error = EINVAL; + } else { + SCTP_BASE_SYSCTL(sctp_auth_enable) = new; + } + } + return (error); +} + +#if defined(__APPLE__) +static int +sctp_sysctl_handle_asconf SYSCTL_HANDLER_ARGS +{ +#pragma unused(arg1, arg2) +#else +static int +sctp_sysctl_handle_asconf(SYSCTL_HANDLER_ARGS) +{ #endif - RANGECHK(SCTP_BASE_SYSCTL(sctp_enable_sack_immediately), SCTPCTL_SACK_IMMEDIATELY_ENABLE_MIN, SCTPCTL_SACK_IMMEDIATELY_ENABLE_MAX); - RANGECHK(SCTP_BASE_SYSCTL(sctp_inits_include_nat_friendly), SCTPCTL_NAT_FRIENDLY_INITS_MIN, SCTPCTL_NAT_FRIENDLY_INITS_MAX); - RANGECHK(SCTP_BASE_SYSCTL(sctp_blackhole), SCTPCTL_BLACKHOLE_MIN, SCTPCTL_BLACKHOLE_MAX); - RANGECHK(SCTP_BASE_SYSCTL(sctp_diag_info_code), SCTPCTL_DIAG_INFO_CODE_MIN, SCTPCTL_DIAG_INFO_CODE_MAX); + int error; + uint32_t new; -#ifdef SCTP_DEBUG - RANGECHK(SCTP_BASE_SYSCTL(sctp_debug_on), SCTPCTL_DEBUG_MIN, SCTPCTL_DEBUG_MAX); + new = SCTP_BASE_SYSCTL(sctp_asconf_enable); +#if defined(__FreeBSD__) && __FreeBSD_version >= 800056 && __FreeBSD_version < 1000100 +#ifdef VIMAGE + error = vnet_sysctl_handle_int(oidp, &new, 0, req); +#else + error = sysctl_handle_int(oidp, &new, 0, req); #endif -#if defined(__APPLE__) - RANGECHK(SCTP_BASE_SYSCTL(sctp_main_timer), SCTPCTL_MAIN_TIMER_MIN, SCTPCTL_MAIN_TIMER_MAX); - RANGECHK(SCTP_BASE_SYSCTL(sctp_addr_watchdog_limit), SCTPCTL_ADDR_WATCHDOG_LIMIT_MIN, SCTPCTL_ADDR_WATCHDOG_LIMIT_MAX); - RANGECHK(SCTP_BASE_SYSCTL(sctp_vtag_watchdog_limit), SCTPCTL_VTAG_WATCHDOG_LIMIT_MIN, SCTPCTL_VTAG_WATCHDOG_LIMIT_MAX); +#else + error = sysctl_handle_int(oidp, &new, 0, req); #endif -#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) - RANGECHK(SCTP_BASE_SYSCTL(sctp_output_unlocked), SCTPCTL_OUTPUT_UNLOCKED_MIN, SCTPCTL_OUTPUT_UNLOCKED_MAX); + if ((error == 0) && +#if defined (__APPLE__) + (req->newptr != USER_ADDR_NULL)) { +#else + (req->newptr != NULL)) { #endif + if ((new < SCTPCTL_ASCONF_ENABLE_MIN) || + (new > SCTPCTL_ASCONF_ENABLE_MAX) || + ((new == 1) && (SCTP_BASE_SYSCTL(sctp_auth_enable) == 0))) { + error = EINVAL; + } else { + SCTP_BASE_SYSCTL(sctp_asconf_enable) = new; + } } return (error); } -#if defined(__FreeBSD__) && defined(SMP) && defined(SCTP_USE_PERCPU_STAT) +#if defined(__APPLE__) +static int +sctp_sysctl_handle_stats SYSCTL_HANDLER_ARGS +{ +#pragma unused(oidp, arg1, arg2) +#else static int -sysctl_stat_get(SYSCTL_HANDLER_ARGS) +sctp_sysctl_handle_stats(SYSCTL_HANDLER_ARGS) { - int cpu, error; - struct sctpstat sb, *sarry, *cpin = NULL; - - if ((req->newptr) && (req->newlen == sizeof(struct sctpstat))) { - /* User wants us to clear or at least - * reset the counters to the specified values. - */ - cpin = (struct sctpstat *)req->newptr; - } else if (req->newptr) { - /* Must be a stat structure */ +#endif + int error; +#if defined(__FreeBSD__) +#if defined(SMP) && defined(SCTP_USE_PERCPU_STAT) + int cpu; + struct sctpstat sb, *sarry; +#endif +#endif + +#if defined (__APPLE__) + if ((req->newptr != USER_ADDR_NULL) && +#else + if ((req->newptr != NULL) && +#endif + (req->newlen != sizeof(struct sctpstat))) { return (EINVAL); } - memset(&sb, 0, sizeof(sb)); +#if defined(__FreeBSD__) +#if defined(SMP) && defined(SCTP_USE_PERCPU_STAT) + memset(&sb, 0, sizeof(struct sctpstat)); for (cpu = 0; cpu < mp_maxid; cpu++) { sarry = &SCTP_BASE_STATS[cpu]; if (sarry->sctps_discontinuitytime.tv_sec > sb.sctps_discontinuitytime.tv_sec) { @@ -1009,24 +994,49 @@ sysctl_stat_get(SYSCTL_HANDLER_ARGS) sb.sctps_send_burst_avoid += sarry->sctps_send_burst_avoid; sb.sctps_send_cwnd_avoid += sarry->sctps_send_cwnd_avoid; sb.sctps_fwdtsn_map_over += sarry->sctps_fwdtsn_map_over; - if (cpin) { - memcpy(sarry, cpin, sizeof(struct sctpstat)); + if (req->newptr != NULL) { + memcpy(sarry, req->newptr, sizeof(struct sctpstat)); } } - error = SYSCTL_OUT(req, &sb, sizeof(sb)); + error = SYSCTL_OUT(req, &sb, sizeof(struct sctpstat)); +#else + error = SYSCTL_OUT(req, &SCTP_BASE_STATS, sizeof(struct sctpstat)); +#endif +#else + error = SYSCTL_OUT(req, &SCTP_BASE_STATS, sizeof(struct sctpstat)); +#endif return (error); } -#endif #if defined(SCTP_LOCAL_TRACE_BUF) #if defined(__APPLE__) static int -sysctl_sctp_cleartrace SYSCTL_HANDLER_ARGS +sctp_sysctl_handle_trace_log SYSCTL_HANDLER_ARGS +{ +#pragma unused(arg1, arg2, oidp) +#else +static int +sctp_sysctl_handle_trace_log(SYSCTL_HANDLER_ARGS) +{ +#endif + int error; + +#if defined(__Windows__) + error = SYSCTL_OUT(req, SCTP_BASE_SYSCTL(sctp_log), sizeof(struct sctp_log)); +#else + error = SYSCTL_OUT(req, &SCTP_BASE_SYSCTL(sctp_log), sizeof(struct sctp_log)); +#endif + return (error); +} + +#if defined(__APPLE__) +static int +sctp_sysctl_handle_trace_log_clear SYSCTL_HANDLER_ARGS { #pragma unused(arg1, arg2, req, oidp) #else static int -sysctl_sctp_cleartrace(SYSCTL_HANDLER_ARGS) +sctp_sysctl_handle_trace_log_clear(SYSCTL_HANDLER_ARGS) { #endif int error = 0; @@ -1048,591 +1058,542 @@ sysctl_sctp_cleartrace(SYSCTL_HANDLER_ARGS) } #endif - #if defined(__APPLE__) || defined(__FreeBSD__) -#if defined(__APPLE__) +#if defined(__FreeBSD__) +#if __FreeBSD_version >= 800056 && __FreeBSD_version < 1000100 +#ifdef VIMAGE +#define SCTP_UINT_SYSCTL(name, var_name, prefix) \ + static int \ + sctp_sysctl_handle_##mib_name(SYSCTL_HANDLER_ARGS) \ + { \ + int error; \ + uint32_t new; \ + \ + new = SCTP_BASE_SYSCTL(var_name); \ + error = vnet_sysctl_handle_int(oidp, &new, 0, req); \ + if ((error == 0) && (req->newptr != NULL)) { \ + if ((new < prefix##_MIN) || \ + (new > prefix##_MAX)) { \ + error = EINVAL; \ + } else { \ + SCTP_BASE_SYSCTL(var_name) = new; \ + } \ + } \ + return (error); \ + } \ + SYSCTL_PROC(_net_inet_sctp, OID_AUTO, mib_name, \ + CTLTYPE_UINT|CTLFLAG_RW, NULL, 0, \ + sctp_sysctl_handle_##mib_name, "UI", prefix##_DESC); +#else +#define SCTP_UINT_SYSCTL(mib_name, var_name, prefix) \ + static int \ + sctp_sysctl_handle_##mib_name(SYSCTL_HANDLER_ARGS) \ + { \ + int error; \ + uint32_t new; \ + \ + new = SCTP_BASE_SYSCTL(var_name); \ + error = sysctl_handle_int(oidp, &new, 0, req); \ + if ((error == 0) && (req->newptr != NULL)) { \ + if ((new < prefix##_MIN) || \ + (new > prefix##_MAX)) { \ + error = EINVAL; \ + } else { \ + SCTP_BASE_SYSCTL(var_name) = new; \ + } \ + } \ + return (error); \ + } \ + SYSCTL_PROC(_net_inet_sctp, OID_AUTO, mib_name, \ + CTLFLAG_VNET|CTLTYPE_UINT|CTLFLAG_RW, NULL, 0, \ + sctp_sysctl_handle_##mib_name, "UI", prefix##_DESC); +#endif +#else +#define SCTP_UINT_SYSCTL(mib_name, var_name, prefix) \ + static int \ + sctp_sysctl_handle_##mib_name(SYSCTL_HANDLER_ARGS) \ + { \ + int error; \ + uint32_t new; \ + \ + new = SCTP_BASE_SYSCTL(var_name); \ + error = sysctl_handle_int(oidp, &new, 0, req); \ + if ((error == 0) && (req->newptr != NULL)) { \ + if ((new < prefix##_MIN) || \ + (new > prefix##_MAX)) { \ + error = EINVAL; \ + } else { \ + SCTP_BASE_SYSCTL(var_name) = new; \ + } \ + } \ + return (error); \ + } \ + SYSCTL_PROC(_net_inet_sctp, OID_AUTO, mib_name, \ + CTLFLAG_VNET|CTLTYPE_UINT|CTLFLAG_RW, NULL, 0, \ + sctp_sysctl_handle_##mib_name, "UI", prefix##_DESC); +#endif +#else +#define SCTP_UINT_SYSCTL(mib_name, var_name, prefix) \ + static int \ + sctp_sysctl_handle_##mib_name(struct sysctl_oid *oidp, \ + void *arg1 __attribute__((unused)), \ + int arg2 __attribute__((unused)), \ + struct sysctl_req *req) \ + { \ + int error; \ + uint32_t new; \ + \ + new = SCTP_BASE_SYSCTL(var_name); \ + error = sysctl_handle_int(oidp, &new, 0, req); \ + if ((error == 0) && (req->newptr != USER_ADDR_NULL)) { \ + if ((new < prefix##_MIN) || \ + (new > prefix##_MAX)) { \ + error = EINVAL; \ + } else { \ + SCTP_BASE_SYSCTL(var_name) = new; \ + } \ + } \ + return (error); \ + } \ + SYSCTL_PROC(_net_inet_sctp, OID_AUTO, mib_name, \ + CTLTYPE_INT | CTLFLAG_RW, NULL, 0, \ + sctp_sysctl_handle_##mib_name, "I", prefix##_DESC); #define CTLTYPE_UINT CTLTYPE_INT -#define SYSCTL_VNET_PROC(parent, nbr, name, access, ptr, arg, handler, fmt, descr) \ - SYSCTL_PROC(parent, nbr, name, access, ptr, arg, handler, fmt, descr) -#define SYSCTL_VNET_STRUCT(parent, nbr, name, access, ptr, type, descr) \ - SYSCTL_STRUCT(parent, nbr, name, access, ptr, type, descr) +#define CTLFLAG_VNET 0 #endif + /* * sysctl definitions */ -SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, sendspace, CTLTYPE_UINT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_sendspace), 0, sysctl_sctp_check, "IU", - SCTPCTL_MAXDGRAM_DESC); - -SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, recvspace, CTLTYPE_UINT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_recvspace), 0, sysctl_sctp_check, "IU", - SCTPCTL_RECVSPACE_DESC); - -#if defined(__FreeBSD__) -SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, auto_asconf, CTLTYPE_UINT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_auto_asconf), 0, sysctl_sctp_check, "IU", - SCTPCTL_AUTOASCONF_DESC); -#elif defined(SCTP_APPLE_AUTO_ASCONF) -SYSCTL_PROC(_net_inet_sctp, OID_AUTO, auto_asconf, CTLTYPE_UINT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_auto_asconf), 0, sysctl_sctp_check, "IU", - SCTPCTL_AUTOASCONF_DESC); -#endif - -SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, ecn_enable, CTLTYPE_UINT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_ecn_enable), 0, sysctl_sctp_check, "IU", - SCTPCTL_ECN_ENABLE_DESC); - -SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, strict_sacks, CTLTYPE_UINT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_strict_sacks), 0, sysctl_sctp_check, "IU", - SCTPCTL_STRICT_SACKS_DESC); - -#if !(defined(__FreeBSD__) && __FreeBSD_version >= 800000) +SCTP_UINT_SYSCTL(sendspace, sctp_sendspace, SCTPCTL_MAXDGRAM) +SCTP_UINT_SYSCTL(recvspace, sctp_recvspace, SCTPCTL_RECVSPACE) +SCTP_UINT_SYSCTL(auto_asconf, sctp_auto_asconf, SCTPCTL_AUTOASCONF) +SCTP_UINT_SYSCTL(ecn_enable, sctp_ecn_enable, SCTPCTL_ECN_ENABLE) +SCTP_UINT_SYSCTL(pr_enable, sctp_pr_enable, SCTPCTL_PR_ENABLE) +SYSCTL_PROC(_net_inet_sctp, OID_AUTO, auth_enable, CTLFLAG_VNET|CTLTYPE_UINT|CTLFLAG_RW, + NULL, 0, sctp_sysctl_handle_auth, "IU", SCTPCTL_AUTH_ENABLE_DESC); +SYSCTL_PROC(_net_inet_sctp, OID_AUTO, asconf_enable, CTLFLAG_VNET|CTLTYPE_UINT|CTLFLAG_RW, + NULL, 0, sctp_sysctl_handle_asconf, "IU", SCTPCTL_ASCONF_ENABLE_DESC); +SCTP_UINT_SYSCTL(reconfig_enable, sctp_reconfig_enable, SCTPCTL_RECONFIG_ENABLE) +SCTP_UINT_SYSCTL(nrsack_enable, sctp_nrsack_enable, SCTPCTL_NRSACK_ENABLE) +SCTP_UINT_SYSCTL(pktdrop_enable, sctp_pktdrop_enable, SCTPCTL_PKTDROP_ENABLE) +SCTP_UINT_SYSCTL(strict_sacks, sctp_strict_sacks, SCTPCTL_STRICT_SACKS) +#if defined(__APPLE__) #if !defined(SCTP_WITH_NO_CSUM) -SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, loopback_nocsum, CTLTYPE_UINT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_no_csum_on_loopback), 0, sysctl_sctp_check, "IU", - SCTPCTL_LOOPBACK_NOCSUM_DESC); -#endif -#endif - -SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, peer_chkoh, CTLTYPE_UINT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_peer_chunk_oh), 0, sysctl_sctp_check, "IU", - SCTPCTL_PEER_CHKOH_DESC); - -SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, maxburst, CTLTYPE_UINT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_max_burst_default), 0, sysctl_sctp_check, "IU", - SCTPCTL_MAXBURST_DESC); - -SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, fr_maxburst, CTLTYPE_UINT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_fr_max_burst_default), 0, sysctl_sctp_check, "IU", - SCTPCTL_FRMAXBURST_DESC); - -SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, maxchunks, CTLTYPE_UINT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_max_chunks_on_queue), 0, sysctl_sctp_check, "IU", - SCTPCTL_MAXCHUNKS_DESC); - -SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, tcbhashsize, CTLTYPE_UINT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_hashtblsize), 0, sysctl_sctp_check, "IU", - SCTPCTL_TCBHASHSIZE_DESC); - -SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, pcbhashsize, CTLTYPE_UINT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_pcbtblsize), 0, sysctl_sctp_check, "IU", - SCTPCTL_PCBHASHSIZE_DESC); - -SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, min_split_point, CTLTYPE_UINT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_min_split_point), 0, sysctl_sctp_check, "IU", - SCTPCTL_MIN_SPLIT_POINT_DESC); - -SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, chunkscale, CTLTYPE_UINT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_chunkscale), 0, sysctl_sctp_check, "IU", - SCTPCTL_CHUNKSCALE_DESC); - -SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, delayed_sack_time, CTLTYPE_UINT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_delayed_sack_time_default), 0, sysctl_sctp_check, "IU", - SCTPCTL_DELAYED_SACK_TIME_DESC); - -SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, sack_freq, CTLTYPE_UINT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_sack_freq_default), 0, sysctl_sctp_check, "IU", - SCTPCTL_SACK_FREQ_DESC); - -SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, sys_resource, CTLTYPE_UINT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_system_free_resc_limit), 0, sysctl_sctp_check, "IU", - SCTPCTL_SYS_RESOURCE_DESC); - -SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, asoc_resource, CTLTYPE_UINT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_asoc_free_resc_limit), 0, sysctl_sctp_check, "IU", - SCTPCTL_ASOC_RESOURCE_DESC); - -SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, heartbeat_interval, CTLTYPE_UINT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_heartbeat_interval_default), 0, sysctl_sctp_check, "IU", - SCTPCTL_HEARTBEAT_INTERVAL_DESC); - -SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, pmtu_raise_time, CTLTYPE_UINT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_pmtu_raise_time_default), 0, sysctl_sctp_check, "IU", - SCTPCTL_PMTU_RAISE_TIME_DESC); - -SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, shutdown_guard_time, CTLTYPE_UINT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_shutdown_guard_time_default), 0, sysctl_sctp_check, "IU", - SCTPCTL_SHUTDOWN_GUARD_TIME_DESC); - -SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, secret_lifetime, CTLTYPE_UINT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_secret_lifetime_default), 0, sysctl_sctp_check, "IU", - SCTPCTL_SECRET_LIFETIME_DESC); - -SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, rto_max, CTLTYPE_UINT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_rto_max_default), 0, sysctl_sctp_check, "IU", - SCTPCTL_RTO_MAX_DESC); - -SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, rto_min, CTLTYPE_UINT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_rto_min_default), 0, sysctl_sctp_check, "IU", - SCTPCTL_RTO_MIN_DESC); - -SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, rto_initial, CTLTYPE_UINT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_rto_initial_default), 0, sysctl_sctp_check, "IU", - SCTPCTL_RTO_INITIAL_DESC); - -SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, init_rto_max, CTLTYPE_UINT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_init_rto_max_default), 0, sysctl_sctp_check, "IU", - SCTPCTL_INIT_RTO_MAX_DESC); - -SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, valid_cookie_life, CTLTYPE_UINT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_valid_cookie_life_default), 0, sysctl_sctp_check, "IU", - SCTPCTL_VALID_COOKIE_LIFE_DESC); - -SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, init_rtx_max, CTLTYPE_UINT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_init_rtx_max_default), 0, sysctl_sctp_check, "IU", - SCTPCTL_INIT_RTX_MAX_DESC); - -SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, assoc_rtx_max, CTLTYPE_UINT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_assoc_rtx_max_default), 0, sysctl_sctp_check, "IU", - SCTPCTL_ASSOC_RTX_MAX_DESC); - -SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, path_rtx_max, CTLTYPE_UINT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_path_rtx_max_default), 0, sysctl_sctp_check, "IU", - SCTPCTL_PATH_RTX_MAX_DESC); - -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); - -SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, nr_sack_on_off, CTLTYPE_UINT | CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_nr_sack_on_off), 0, sysctl_sctp_check, "IU", - SCTPCTL_NR_SACK_ON_OFF_DESC); - -SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, cmt_use_dac, CTLTYPE_UINT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_cmt_use_dac), 0, sysctl_sctp_check, "IU", - SCTPCTL_CMT_USE_DAC_DESC); - -SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, cwnd_maxburst, CTLTYPE_UINT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_use_cwnd_based_maxburst), 0, sysctl_sctp_check, "IU", - SCTPCTL_CWND_MAXBURST_DESC); - -SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, asconf_auth_nochk, CTLTYPE_UINT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_asconf_auth_nochk), 0, sysctl_sctp_check, "IU", - SCTPCTL_ASCONF_AUTH_NOCHK_DESC); - -SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, auth_disable, CTLTYPE_UINT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_auth_disable), 0, sysctl_sctp_check, "IU", - SCTPCTL_AUTH_DISABLE_DESC); - -SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, nat_friendly, CTLTYPE_UINT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_nat_friendly), 0, sysctl_sctp_check, "IU", - SCTPCTL_NAT_FRIENDLY_DESC); - -SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, abc_l_var, CTLTYPE_UINT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_L2_abc_variable), 0, sysctl_sctp_check, "IU", - SCTPCTL_ABC_L_VAR_DESC); - -SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, max_chained_mbufs, CTLTYPE_UINT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_mbuf_threshold_count), 0, sysctl_sctp_check, "IU", - SCTPCTL_MAX_CHAINED_MBUFS_DESC); - -SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, do_sctp_drain, CTLTYPE_UINT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_do_drain), 0, sysctl_sctp_check, "IU", - SCTPCTL_DO_SCTP_DRAIN_DESC); - -SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, hb_max_burst, CTLTYPE_UINT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_hb_maxburst), 0, sysctl_sctp_check, "IU", - SCTPCTL_HB_MAX_BURST_DESC); - -SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, abort_at_limit, CTLTYPE_UINT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_abort_if_one_2_one_hits_limit), 0, sysctl_sctp_check, "IU", - SCTPCTL_ABORT_AT_LIMIT_DESC); - -SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, strict_data_order, CTLTYPE_UINT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_strict_data_order), 0, sysctl_sctp_check, "IU", - SCTPCTL_STRICT_DATA_ORDER_DESC); - -SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, min_residual, CTLTYPE_UINT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_min_residual), 0, sysctl_sctp_check, "IU", - SCTPCTL_MIN_RESIDUAL_DESC); - -SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, max_retran_chunk, CTLTYPE_UINT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_max_retran_chunk), 0, sysctl_sctp_check, "IU", - SCTPCTL_MAX_RETRAN_CHUNK_DESC); - -SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, log_level, CTLTYPE_UINT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_logging_level), 0, sysctl_sctp_check, "IU", - SCTPCTL_LOGGING_LEVEL_DESC); - -SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, default_cc_module, CTLTYPE_UINT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_default_cc_module), 0, sysctl_sctp_check, "IU", - SCTPCTL_DEFAULT_CC_MODULE_DESC); - -SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, default_ss_module, CTLTYPE_UINT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_default_ss_module), 0, sysctl_sctp_check, "IU", - SCTPCTL_DEFAULT_SS_MODULE_DESC); - -SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, default_frag_interleave, CTLTYPE_UINT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_default_frag_interleave), 0, sysctl_sctp_check, "IU", - SCTPCTL_DEFAULT_FRAG_INTERLEAVE_DESC); - -#if defined(__FreeBSD__) -SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, mobility_base, CTLTYPE_UINT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_mobility_base), 0, sysctl_sctp_check, "IU", - SCTPCTL_MOBILITY_BASE_DESC); -#elif defined(SCTP_APPLE_MOBILITY_BASE) -SYSCTL_PROC(_net_inet_sctp, OID_AUTO, mobility_base, CTLTYPE_UINT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_mobility_base), 0, sysctl_sctp_check, "IU", - SCTPCTL_MOBILITY_BASE_DESC); -#endif - -#if defined(__FreeBSD__) -SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, mobility_fasthandoff, CTLTYPE_UINT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_mobility_fasthandoff), 0, sysctl_sctp_check, "IU", - SCTPCTL_MOBILITY_FASTHANDOFF_DESC); -#elif defined(SCTP_APPLE_MOBILITY_FASTHANDOFF) -SYSCTL_PROC(_net_inet_sctp, OID_AUTO, mobility_fasthandoff, CTLTYPE_UINT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_mobility_fasthandoff), 0, sysctl_sctp_check, "IU", - SCTPCTL_MOBILITY_FASTHANDOFF_DESC); -#endif - +SCTP_UINT_SYSCTL(loopback_nocsum, sctp_no_csum_on_loopback, SCTPCTL_LOOPBACK_NOCSUM) +#endif +#endif +SCTP_UINT_SYSCTL(peer_chkoh, sctp_peer_chunk_oh, SCTPCTL_PEER_CHKOH) +SCTP_UINT_SYSCTL(maxburst, sctp_max_burst_default, SCTPCTL_MAXBURST) +SCTP_UINT_SYSCTL(fr_maxburst, sctp_fr_max_burst_default, SCTPCTL_FRMAXBURST) +SCTP_UINT_SYSCTL(maxchunks, sctp_max_chunks_on_queue, SCTPCTL_MAXCHUNKS) +SCTP_UINT_SYSCTL(tcbhashsize, sctp_hashtblsize, SCTPCTL_TCBHASHSIZE) +SCTP_UINT_SYSCTL(pcbhashsize, sctp_pcbtblsize, SCTPCTL_PCBHASHSIZE) +SCTP_UINT_SYSCTL(min_split_point, sctp_min_split_point, SCTPCTL_MIN_SPLIT_POINT) +SCTP_UINT_SYSCTL(chunkscale, sctp_chunkscale, SCTPCTL_CHUNKSCALE) +SCTP_UINT_SYSCTL(delayed_sack_time, sctp_delayed_sack_time_default, SCTPCTL_DELAYED_SACK_TIME) +SCTP_UINT_SYSCTL(sack_freq, sctp_sack_freq_default, SCTPCTL_SACK_FREQ) +SCTP_UINT_SYSCTL(sys_resource, sctp_system_free_resc_limit, SCTPCTL_SYS_RESOURCE) +SCTP_UINT_SYSCTL(asoc_resource, sctp_asoc_free_resc_limit, SCTPCTL_ASOC_RESOURCE) +SCTP_UINT_SYSCTL(heartbeat_interval, sctp_heartbeat_interval_default, SCTPCTL_HEARTBEAT_INTERVAL) +SCTP_UINT_SYSCTL(pmtu_raise_time, sctp_pmtu_raise_time_default, SCTPCTL_PMTU_RAISE_TIME) +SCTP_UINT_SYSCTL(shutdown_guard_time, sctp_shutdown_guard_time_default, SCTPCTL_SHUTDOWN_GUARD_TIME) +SCTP_UINT_SYSCTL(secret_lifetime, sctp_secret_lifetime_default, SCTPCTL_SECRET_LIFETIME) +SCTP_UINT_SYSCTL(rto_max, sctp_rto_max_default, SCTPCTL_RTO_MAX) +SCTP_UINT_SYSCTL(rto_min, sctp_rto_min_default, SCTPCTL_RTO_MIN) +SCTP_UINT_SYSCTL(rto_initial, sctp_rto_initial_default, SCTPCTL_RTO_INITIAL) +SCTP_UINT_SYSCTL(init_rto_max, sctp_init_rto_max_default, SCTPCTL_INIT_RTO_MAX) +SCTP_UINT_SYSCTL(valid_cookie_life, sctp_valid_cookie_life_default, SCTPCTL_VALID_COOKIE_LIFE) +SCTP_UINT_SYSCTL(init_rtx_max, sctp_init_rtx_max_default, SCTPCTL_INIT_RTX_MAX) +SCTP_UINT_SYSCTL(assoc_rtx_max, sctp_assoc_rtx_max_default, SCTPCTL_ASSOC_RTX_MAX) +SCTP_UINT_SYSCTL(path_rtx_max, sctp_path_rtx_max_default, SCTPCTL_PATH_RTX_MAX) +SCTP_UINT_SYSCTL(path_pf_threshold, sctp_path_pf_threshold, SCTPCTL_PATH_PF_THRESHOLD) +SCTP_UINT_SYSCTL(add_more_on_output, sctp_add_more_threshold, SCTPCTL_ADD_MORE_ON_OUTPUT) +SCTP_UINT_SYSCTL(incoming_streams, sctp_nr_incoming_streams_default, SCTPCTL_INCOMING_STREAMS) +SCTP_UINT_SYSCTL(outgoing_streams, sctp_nr_outgoing_streams_default, SCTPCTL_OUTGOING_STREAMS) +SCTP_UINT_SYSCTL(cmt_on_off, sctp_cmt_on_off, SCTPCTL_CMT_ON_OFF) +SCTP_UINT_SYSCTL(cmt_use_dac, sctp_cmt_use_dac, SCTPCTL_CMT_USE_DAC) +SCTP_UINT_SYSCTL(cwnd_maxburst, sctp_use_cwnd_based_maxburst, SCTPCTL_CWND_MAXBURST) +SCTP_UINT_SYSCTL(nat_friendly, sctp_nat_friendly, SCTPCTL_NAT_FRIENDLY) +SCTP_UINT_SYSCTL(abc_l_var, sctp_L2_abc_variable, SCTPCTL_ABC_L_VAR) +SCTP_UINT_SYSCTL(max_chained_mbufs, sctp_mbuf_threshold_count, SCTPCTL_MAX_CHAINED_MBUFS) +SCTP_UINT_SYSCTL(do_sctp_drain, sctp_do_drain, SCTPCTL_DO_SCTP_DRAIN) +SCTP_UINT_SYSCTL(hb_max_burst, sctp_hb_maxburst, SCTPCTL_HB_MAX_BURST) +SCTP_UINT_SYSCTL(abort_at_limit, sctp_abort_if_one_2_one_hits_limit, SCTPCTL_ABORT_AT_LIMIT) +SCTP_UINT_SYSCTL(strict_data_order, sctp_strict_data_order, SCTPCTL_STRICT_DATA_ORDER) +SCTP_UINT_SYSCTL(min_residual, sctp_min_residual, SCTPCTL_MIN_RESIDUAL) +SCTP_UINT_SYSCTL(max_retran_chunk, sctp_max_retran_chunk, SCTPCTL_MAX_RETRAN_CHUNK) +SCTP_UINT_SYSCTL(log_level, sctp_logging_level, SCTPCTL_LOGGING_LEVEL) +SCTP_UINT_SYSCTL(default_cc_module, sctp_default_cc_module, SCTPCTL_DEFAULT_CC_MODULE) +SCTP_UINT_SYSCTL(default_ss_module, sctp_default_ss_module, SCTPCTL_DEFAULT_SS_MODULE) +SCTP_UINT_SYSCTL(default_frag_interleave, sctp_default_frag_interleave, SCTPCTL_DEFAULT_FRAG_INTERLEAVE) +SCTP_UINT_SYSCTL(mobility_base, sctp_mobility_base, SCTPCTL_MOBILITY_BASE) +SCTP_UINT_SYSCTL(mobility_fasthandoff, sctp_mobility_fasthandoff, SCTPCTL_MOBILITY_FASTHANDOFF) #if defined(SCTP_LOCAL_TRACE_BUF) -SYSCTL_VNET_STRUCT(_net_inet_sctp, OID_AUTO, log, CTLFLAG_RD, - &SCTP_BASE_SYSCTL(sctp_log), sctp_log, - "SCTP logging (struct sctp_log)"); - -SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, clear_trace, CTLTYPE_UINT | CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_log), 0, sysctl_sctp_cleartrace, "IU", - "Clear SCTP Logging buffer"); -#endif - -SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, udp_tunneling_port, CTLTYPE_UINT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_udp_tunneling_port), 0, sysctl_sctp_udp_tunneling_check, "IU", - SCTPCTL_UDP_TUNNELING_PORT_DESC); - -SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, enable_sack_immediately, CTLTYPE_UINT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_enable_sack_immediately), 0, sysctl_sctp_check, "IU", - SCTPCTL_SACK_IMMEDIATELY_ENABLE_DESC); - -SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, nat_friendly_init, CTLTYPE_UINT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_inits_include_nat_friendly), 0, sysctl_sctp_check, "IU", - SCTPCTL_NAT_FRIENDLY_INITS_DESC); - -SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, vtag_time_wait, CTLTYPE_UINT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_vtag_time_wait), 0, sysctl_sctp_check, "IU", - SCTPCTL_TIME_WAIT_DESC); - -SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, buffer_splitting, CTLTYPE_UINT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_buffer_splitting), 0, sysctl_sctp_check, "IU", - SCTPCTL_BUFFER_SPLITTING_DESC); - -SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, initial_cwnd, CTLTYPE_UINT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_initial_cwnd), 0, sysctl_sctp_check, "IU", - SCTPCTL_INITIAL_CWND_DESC); - -SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, rttvar_bw, CTLTYPE_UINT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_rttvar_bw), 0, sysctl_sctp_check, "IU", - SCTPCTL_RTTVAR_BW_DESC); - -SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, rttvar_rtt, CTLTYPE_UINT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_rttvar_rtt), 0, sysctl_sctp_check, "IU", - SCTPCTL_RTTVAR_RTT_DESC); - -SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, rttvar_eqret, CTLTYPE_UINT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_rttvar_eqret), 0, sysctl_sctp_check, "IU", - SCTPCTL_RTTVAR_EQRET_DESC); - -SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, rttvar_steady_step, CTLTYPE_UINT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_steady_step), 0, sysctl_sctp_check, "IU", - SCTPCTL_RTTVAR_STEADYS_DESC); - -SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, use_dcccecn, CTLTYPE_UINT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_use_dccc_ecn), 0, sysctl_sctp_check, "IU", - SCTPCTL_RTTVAR_DCCCECN_DESC); - -SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, blackhole, CTLTYPE_UINT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_blackhole), 0, sysctl_sctp_check, "IU", - SCTPCTL_BLACKHOLE_DESC); - -SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, diag_info_code, CTLTYPE_UINT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_diag_info_code), 0, sysctl_sctp_check, "IU", - SCTPCTL_DIAG_INFO_CODE_DESC); - +SYSCTL_PROC(_net_inet_sctp, OID_AUTO, log, CTLFLAG_VNET|CTLTYPE_STRUCT|CTLFLAG_RD, + NULL, 0, sctp_sysctl_handle_trace_log, "S,sctplog", "SCTP logging (struct sctp_log)"); +SYSCTL_PROC(_net_inet_sctp, OID_AUTO, clear_trace, CTLFLAG_VNET|CTLTYPE_UINT | CTLFLAG_RW, + NULL, 0, sctp_sysctl_handle_trace_log_clear, "IU", "Clear SCTP Logging buffer"); +#endif +SYSCTL_PROC(_net_inet_sctp, OID_AUTO, udp_tunneling_port, CTLFLAG_VNET|CTLTYPE_UINT|CTLFLAG_RW, + NULL, 0, sctp_sysctl_handle_udp_tunneling, "IU", SCTPCTL_UDP_TUNNELING_PORT_DESC); +SCTP_UINT_SYSCTL(enable_sack_immediately, sctp_enable_sack_immediately, SCTPCTL_SACK_IMMEDIATELY_ENABLE) +SCTP_UINT_SYSCTL(nat_friendly_init, sctp_inits_include_nat_friendly, SCTPCTL_NAT_FRIENDLY_INITS) +SCTP_UINT_SYSCTL(vtag_time_wait, sctp_vtag_time_wait, SCTPCTL_TIME_WAIT) +SCTP_UINT_SYSCTL(buffer_splitting, sctp_buffer_splitting, SCTPCTL_BUFFER_SPLITTING) +SCTP_UINT_SYSCTL(initial_cwnd, sctp_initial_cwnd, SCTPCTL_INITIAL_CWND) +SCTP_UINT_SYSCTL(rttvar_bw, sctp_rttvar_bw, SCTPCTL_RTTVAR_BW) +SCTP_UINT_SYSCTL(rttvar_rtt, sctp_rttvar_rtt, SCTPCTL_RTTVAR_RTT) +SCTP_UINT_SYSCTL(rttvar_eqret, sctp_rttvar_eqret, SCTPCTL_RTTVAR_EQRET) +SCTP_UINT_SYSCTL(rttvar_steady_step, sctp_steady_step, SCTPCTL_RTTVAR_STEADYS) +SCTP_UINT_SYSCTL(use_dcccecn, sctp_use_dccc_ecn, SCTPCTL_RTTVAR_DCCCECN) +SCTP_UINT_SYSCTL(blackhole, sctp_blackhole, SCTPCTL_BLACKHOLE) +SCTP_UINT_SYSCTL(diag_info_code, sctp_diag_info_code, SCTPCTL_DIAG_INFO_CODE) #ifdef SCTP_DEBUG -SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, debug, CTLTYPE_UINT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_debug_on), 0, sysctl_sctp_check, "IU", - SCTPCTL_DEBUG_DESC); +SCTP_UINT_SYSCTL(debug, sctp_debug_on, SCTPCTL_DEBUG) #endif - #if defined(__APPLE__) -SYSCTL_INT(_net_inet_sctp, OID_AUTO, main_timer, CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_main_timer), 0, "Main timer interval in ms"); - +SCTP_UINT_SYSCTL(main_timer, sctp_main_timer, SCTPCTL_MAIN_TIMER) SYSCTL_PROC(_net_inet_sctp, OID_AUTO, ignore_vmware_interfaces, CTLTYPE_UINT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_ignore_vmware_interfaces), 0, sysctl_sctp_vmware_interfaces_check, "IU", - SCTPCTL_IGNORE_VMWARE_INTERFACES_DESC); - -SYSCTL_INT(_net_inet_sctp, OID_AUTO, addr_watchdog_limit, CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_addr_watchdog_limit), 0, "Addr watchdog intervall"); - -SYSCTL_INT(_net_inet_sctp, OID_AUTO, vtag_watchdog_limit, CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_vtag_watchdog_limit), 0, "Vtag watchdog intervall"); + NULL, 0, sctp_sysctl_handle_vmware_interfaces, "IU", SCTPCTL_IGNORE_VMWARE_INTERFACES_DESC); +SCTP_UINT_SYSCTL(addr_watchdog_limit, sctp_addr_watchdog_limit, SCTPCTL_ADDR_WATCHDOG_LIMIT) +SCTP_UINT_SYSCTL(vtag_watchdog_limit, sctp_vtag_watchdog_limit, SCTPCTL_VTAG_WATCHDOG_LIMIT) #endif - #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) -SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, output_unlocked, CTLTYPE_UINT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_output_unlocked), 0, sysctl_sctp_check, "IU", - SCTPCTL_OUTPUT_UNLOCKED_DESC); +SCTP_UINT_SYSCTL(output_unlocked, sctp_output_unlocked, SCTPCTL_OUTPUT_UNLOCKED) #endif +SYSCTL_PROC(_net_inet_sctp, OID_AUTO, stats, CTLFLAG_VNET|CTLTYPE_STRUCT|CTLFLAG_RW, + NULL, 0, sctp_sysctl_handle_stats, "S,sctpstat", "SCTP statistics (struct sctp_stat)"); +SYSCTL_PROC(_net_inet_sctp, OID_AUTO, assoclist, CTLFLAG_VNET|CTLTYPE_OPAQUE|CTLFLAG_RD, + NULL, 0, sctp_sysctl_handle_assoclist, "S,xassoc", "List of active SCTP associations"); -#if defined(__FreeBSD__) && defined(SMP) && defined(SCTP_USE_PERCPU_STAT) -SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, stats, - CTLTYPE_STRUCT|CTLFLAG_RW, - 0, 0, sysctl_stat_get, "S,sctpstat", - "SCTP statistics (struct sctp_stat)"); -#else -SYSCTL_VNET_STRUCT(_net_inet_sctp, OID_AUTO, stats, CTLFLAG_RW, - &SCTP_BASE_STATS_SYSCTL, sctpstat, - "SCTP statistics (struct sctp_stat)"); -#endif +#elif defined(__Windows__) + +#define RANGECHK(var, min, max) \ + if ((var) < (min)) { (var) = (min); } \ + else if ((var) > (max)) { (var) = (max); } -SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, assoclist, CTLTYPE_OPAQUE | CTLFLAG_RD, - 0, 0, sctp_assoclist, - "S,xassoc", "List of active SCTP associations"); +static int +sctp_sysctl_handle_int(SYSCTL_HANDLER_ARGS) +{ + int error; -#elif defined(__Windows__) -void sysctl_setup_sctp(void) + error = sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2, req); + if (error == 0) { + RANGECHK(SCTP_BASE_SYSCTL(sctp_sendspace), SCTPCTL_MAXDGRAM_MIN, SCTPCTL_MAXDGRAM_MAX); + RANGECHK(SCTP_BASE_SYSCTL(sctp_recvspace), SCTPCTL_RECVSPACE_MIN, SCTPCTL_RECVSPACE_MAX); + RANGECHK(SCTP_BASE_SYSCTL(sctp_auto_asconf), SCTPCTL_AUTOASCONF_MIN, SCTPCTL_AUTOASCONF_MAX); + RANGECHK(SCTP_BASE_SYSCTL(sctp_auto_asconf), SCTPCTL_AUTOASCONF_MIN, SCTPCTL_AUTOASCONF_MAX); + RANGECHK(SCTP_BASE_SYSCTL(sctp_ecn_enable), SCTPCTL_ECN_ENABLE_MIN, SCTPCTL_ECN_ENABLE_MAX); + RANGECHK(SCTP_BASE_SYSCTL(sctp_pr_enable), SCTPCTL_PR_ENABLE_MIN, SCTPCTL_PR_ENABLE_MAX); + RANGECHK(SCTP_BASE_SYSCTL(sctp_reconfig_enable), SCTPCTL_RECONFIG_ENABLE_MIN, SCTPCTL_RECONFIG_ENABLE_MAX); + RANGECHK(SCTP_BASE_SYSCTL(sctp_nrsack_enable), SCTPCTL_NRSACK_ENABLE_MIN, SCTPCTL_NRSACK_ENABLE_MAX); + RANGECHK(SCTP_BASE_SYSCTL(sctp_pktdrop_enable), SCTPCTL_PKTDROP_ENABLE_MIN, SCTPCTL_PKTDROP_ENABLE_MAX); + RANGECHK(SCTP_BASE_SYSCTL(sctp_strict_sacks), SCTPCTL_STRICT_SACKS_MIN, SCTPCTL_STRICT_SACKS_MAX); +#if !defined(SCTP_WITH_NO_CSUM) + RANGECHK(SCTP_BASE_SYSCTL(sctp_no_csum_on_loopback), SCTPCTL_LOOPBACK_NOCSUM_MIN, SCTPCTL_LOOPBACK_NOCSUM_MAX); +#endif + RANGECHK(SCTP_BASE_SYSCTL(sctp_peer_chunk_oh), SCTPCTL_PEER_CHKOH_MIN, SCTPCTL_PEER_CHKOH_MAX); + RANGECHK(SCTP_BASE_SYSCTL(sctp_max_burst_default), SCTPCTL_MAXBURST_MIN, SCTPCTL_MAXBURST_MAX); + RANGECHK(SCTP_BASE_SYSCTL(sctp_fr_max_burst_default), SCTPCTL_FRMAXBURST_MIN, SCTPCTL_FRMAXBURST_MAX); + RANGECHK(SCTP_BASE_SYSCTL(sctp_max_chunks_on_queue), SCTPCTL_MAXCHUNKS_MIN, SCTPCTL_MAXCHUNKS_MAX); + RANGECHK(SCTP_BASE_SYSCTL(sctp_hashtblsize), SCTPCTL_TCBHASHSIZE_MIN, SCTPCTL_TCBHASHSIZE_MAX); + RANGECHK(SCTP_BASE_SYSCTL(sctp_pcbtblsize), SCTPCTL_PCBHASHSIZE_MIN, SCTPCTL_PCBHASHSIZE_MAX); + RANGECHK(SCTP_BASE_SYSCTL(sctp_min_split_point), SCTPCTL_MIN_SPLIT_POINT_MIN, SCTPCTL_MIN_SPLIT_POINT_MAX); + RANGECHK(SCTP_BASE_SYSCTL(sctp_chunkscale), SCTPCTL_CHUNKSCALE_MIN, SCTPCTL_CHUNKSCALE_MAX); + RANGECHK(SCTP_BASE_SYSCTL(sctp_delayed_sack_time_default), SCTPCTL_DELAYED_SACK_TIME_MIN, SCTPCTL_DELAYED_SACK_TIME_MAX); + RANGECHK(SCTP_BASE_SYSCTL(sctp_sack_freq_default), SCTPCTL_SACK_FREQ_MIN, SCTPCTL_SACK_FREQ_MAX); + RANGECHK(SCTP_BASE_SYSCTL(sctp_system_free_resc_limit), SCTPCTL_SYS_RESOURCE_MIN, SCTPCTL_SYS_RESOURCE_MAX); + RANGECHK(SCTP_BASE_SYSCTL(sctp_asoc_free_resc_limit), SCTPCTL_ASOC_RESOURCE_MIN, SCTPCTL_ASOC_RESOURCE_MAX); + RANGECHK(SCTP_BASE_SYSCTL(sctp_heartbeat_interval_default), SCTPCTL_HEARTBEAT_INTERVAL_MIN, SCTPCTL_HEARTBEAT_INTERVAL_MAX); + RANGECHK(SCTP_BASE_SYSCTL(sctp_pmtu_raise_time_default), SCTPCTL_PMTU_RAISE_TIME_MIN, SCTPCTL_PMTU_RAISE_TIME_MAX); + RANGECHK(SCTP_BASE_SYSCTL(sctp_shutdown_guard_time_default), SCTPCTL_SHUTDOWN_GUARD_TIME_MIN, SCTPCTL_SHUTDOWN_GUARD_TIME_MAX); + RANGECHK(SCTP_BASE_SYSCTL(sctp_secret_lifetime_default), SCTPCTL_SECRET_LIFETIME_MIN, SCTPCTL_SECRET_LIFETIME_MAX); + RANGECHK(SCTP_BASE_SYSCTL(sctp_rto_max_default), SCTPCTL_RTO_MAX_MIN, SCTPCTL_RTO_MAX_MAX); + RANGECHK(SCTP_BASE_SYSCTL(sctp_rto_min_default), SCTPCTL_RTO_MIN_MIN, SCTPCTL_RTO_MIN_MAX); + 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); + 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_nat_friendly), SCTPCTL_NAT_FRIENDLY_MIN, SCTPCTL_NAT_FRIENDLY_MAX); + RANGECHK(SCTP_BASE_SYSCTL(sctp_L2_abc_variable), SCTPCTL_ABC_L_VAR_MIN, SCTPCTL_ABC_L_VAR_MAX); + RANGECHK(SCTP_BASE_SYSCTL(sctp_mbuf_threshold_count), SCTPCTL_MAX_CHAINED_MBUFS_MIN, SCTPCTL_MAX_CHAINED_MBUFS_MAX); + RANGECHK(SCTP_BASE_SYSCTL(sctp_do_drain), SCTPCTL_DO_SCTP_DRAIN_MIN, SCTPCTL_DO_SCTP_DRAIN_MAX); + RANGECHK(SCTP_BASE_SYSCTL(sctp_hb_maxburst), SCTPCTL_HB_MAX_BURST_MIN, SCTPCTL_HB_MAX_BURST_MAX); + RANGECHK(SCTP_BASE_SYSCTL(sctp_abort_if_one_2_one_hits_limit), SCTPCTL_ABORT_AT_LIMIT_MIN, SCTPCTL_ABORT_AT_LIMIT_MAX); + RANGECHK(SCTP_BASE_SYSCTL(sctp_strict_data_order), SCTPCTL_STRICT_DATA_ORDER_MIN, SCTPCTL_STRICT_DATA_ORDER_MAX); + RANGECHK(SCTP_BASE_SYSCTL(sctp_min_residual), SCTPCTL_MIN_RESIDUAL_MIN, SCTPCTL_MIN_RESIDUAL_MAX); + RANGECHK(SCTP_BASE_SYSCTL(sctp_max_retran_chunk), SCTPCTL_MAX_RETRAN_CHUNK_MIN, SCTPCTL_MAX_RETRAN_CHUNK_MAX); + RANGECHK(SCTP_BASE_SYSCTL(sctp_logging_level), SCTPCTL_LOGGING_LEVEL_MIN, SCTPCTL_LOGGING_LEVEL_MAX); + RANGECHK(SCTP_BASE_SYSCTL(sctp_default_cc_module), SCTPCTL_DEFAULT_CC_MODULE_MIN, SCTPCTL_DEFAULT_CC_MODULE_MAX); + RANGECHK(SCTP_BASE_SYSCTL(sctp_default_ss_module), SCTPCTL_DEFAULT_SS_MODULE_MIN, SCTPCTL_DEFAULT_SS_MODULE_MAX); + RANGECHK(SCTP_BASE_SYSCTL(sctp_default_frag_interleave), SCTPCTL_DEFAULT_FRAG_INTERLEAVE_MIN, SCTPCTL_DEFAULT_FRAG_INTERLEAVE_MAX); + RANGECHK(SCTP_BASE_SYSCTL(sctp_vtag_time_wait), SCTPCTL_TIME_WAIT_MIN, SCTPCTL_TIME_WAIT_MAX); + RANGECHK(SCTP_BASE_SYSCTL(sctp_buffer_splitting), SCTPCTL_BUFFER_SPLITTING_MIN, SCTPCTL_BUFFER_SPLITTING_MAX); + RANGECHK(SCTP_BASE_SYSCTL(sctp_initial_cwnd), SCTPCTL_INITIAL_CWND_MIN, SCTPCTL_INITIAL_CWND_MAX); + RANGECHK(SCTP_BASE_SYSCTL(sctp_rttvar_bw), SCTPCTL_RTTVAR_BW_MIN, SCTPCTL_RTTVAR_BW_MAX); + RANGECHK(SCTP_BASE_SYSCTL(sctp_rttvar_rtt), SCTPCTL_RTTVAR_RTT_MIN, SCTPCTL_RTTVAR_RTT_MAX); + RANGECHK(SCTP_BASE_SYSCTL(sctp_rttvar_eqret), SCTPCTL_RTTVAR_EQRET_MIN, SCTPCTL_RTTVAR_EQRET_MAX); + RANGECHK(SCTP_BASE_SYSCTL(sctp_steady_step), SCTPCTL_RTTVAR_STEADYS_MIN, SCTPCTL_RTTVAR_STEADYS_MAX); + RANGECHK(SCTP_BASE_SYSCTL(sctp_use_dccc_ecn), SCTPCTL_RTTVAR_DCCCECN_MIN, SCTPCTL_RTTVAR_DCCCECN_MAX); + RANGECHK(SCTP_BASE_SYSCTL(sctp_mobility_base), SCTPCTL_MOBILITY_BASE_MIN, SCTPCTL_MOBILITY_BASE_MAX); + RANGECHK(SCTP_BASE_SYSCTL(sctp_mobility_fasthandoff), SCTPCTL_MOBILITY_FASTHANDOFF_MIN, SCTPCTL_MOBILITY_FASTHANDOFF_MAX); + RANGECHK(SCTP_BASE_SYSCTL(sctp_enable_sack_immediately), SCTPCTL_SACK_IMMEDIATELY_ENABLE_MIN, SCTPCTL_SACK_IMMEDIATELY_ENABLE_MAX); + RANGECHK(SCTP_BASE_SYSCTL(sctp_inits_include_nat_friendly), SCTPCTL_NAT_FRIENDLY_INITS_MIN, SCTPCTL_NAT_FRIENDLY_INITS_MAX); + RANGECHK(SCTP_BASE_SYSCTL(sctp_blackhole), SCTPCTL_BLACKHOLE_MIN, SCTPCTL_BLACKHOLE_MAX); + RANGECHK(SCTP_BASE_SYSCTL(sctp_diag_info_code), SCTPCTL_DIAG_INFO_CODE_MIN, SCTPCTL_DIAG_INFO_CODE_MAX); +#ifdef SCTP_DEBUG + RANGECHK(SCTP_BASE_SYSCTL(sctp_debug_on), SCTPCTL_DEBUG_MIN, SCTPCTL_DEBUG_MAX); +#endif + } + return (error); +} + +void +sysctl_setup_sctp(void) { sysctl_add_oid(&sysctl_oid_top, "sendspace", CTLTYPE_INT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_sendspace), 0, sysctl_sctp_check, + &SCTP_BASE_SYSCTL(sctp_sendspace), 0, sctp_sysctl_handle_int, SCTPCTL_MAXDGRAM_DESC); sysctl_add_oid(&sysctl_oid_top, "recvspace", CTLTYPE_INT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_recvspace), 0, sysctl_sctp_check, + &SCTP_BASE_SYSCTL(sctp_recvspace), 0, sctp_sysctl_handle_int, SCTPCTL_RECVSPACE_DESC); sysctl_add_oid(&sysctl_oid_top, "auto_asconf", CTLTYPE_INT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_auto_asconf), 0, sysctl_sctp_check, + &SCTP_BASE_SYSCTL(sctp_auto_asconf), 0, sctp_sysctl_handle_int, SCTPCTL_AUTOASCONF_DESC); sysctl_add_oid(&sysctl_oid_top, "ecn_enable", CTLTYPE_INT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_ecn_enable), 0, sysctl_sctp_check, + &SCTP_BASE_SYSCTL(sctp_ecn_enable), 0, sctp_sysctl_handle_int, SCTPCTL_ECN_ENABLE_DESC); + sysctl_add_oid(&sysctl_oid_top, "pr_enable", CTLTYPE_INT|CTLFLAG_RW, + &SCTP_BASE_SYSCTL(sctp_pr_enable), 0, sctp_sysctl_handle_int, + SCTPCTL_PR_ENABLE_DESC); + + sysctl_add_oid(&sysctl_oid_top, "auth_enable", CTLTYPE_INT|CTLFLAG_RW, + &SCTP_BASE_SYSCTL(sctp_auth_enable), 0, sctp_sysctl_handle_auth, + SCTPCTL_AUTH_ENABLE_DESC); + + sysctl_add_oid(&sysctl_oid_top, "asconf_enable", CTLTYPE_INT|CTLFLAG_RW, + &SCTP_BASE_SYSCTL(sctp_asconf_enable), 0, sctp_sysctl_handle_asconf, + SCTPCTL_ASCONF_ENABLE_DESC); + + sysctl_add_oid(&sysctl_oid_top, "reconfig_enable", CTLTYPE_INT|CTLFLAG_RW, + &SCTP_BASE_SYSCTL(sctp_reconfig_enable), 0, sctp_sysctl_handle_int, + SCTPCTL_RECONFIG_ENABLE_DESC); + + sysctl_add_oid(&sysctl_oid_top, "nrsack_enable", CTLTYPE_INT|CTLFLAG_RW, + &SCTP_BASE_SYSCTL(sctp_nrsack_enable), 0, sctp_sysctl_handle_int, + SCTPCTL_NRSACK_ENABLE_DESC); + + sysctl_add_oid(&sysctl_oid_top, "pktdrop_enable", CTLTYPE_INT|CTLFLAG_RW, + &SCTP_BASE_SYSCTL(sctp_pktdrop_enable), 0, sctp_sysctl_handle_int, + SCTPCTL_PKTDROP_ENABLE_DESC); + sysctl_add_oid(&sysctl_oid_top, "strict_sacks", CTLTYPE_INT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_strict_sacks), 0, sysctl_sctp_check, + &SCTP_BASE_SYSCTL(sctp_strict_sacks), 0, sctp_sysctl_handle_int, SCTPCTL_STRICT_SACKS_DESC); -#if !(defined(__FreeBSD__) && __FreeBSD_version >= 800000) #if !defined(SCTP_WITH_NO_CSUM) sysctl_add_oid(&sysctl_oid_top, "loopback_nocsum", CTLTYPE_INT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_no_csum_on_loopback), 0, sysctl_sctp_check, + &SCTP_BASE_SYSCTL(sctp_no_csum_on_loopback), 0, sctp_sysctl_handle_int, SCTPCTL_LOOPBACK_NOCSUM_DESC); #endif -#endif sysctl_add_oid(&sysctl_oid_top, "peer_chkoh", CTLTYPE_INT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_peer_chunk_oh), 0, sysctl_sctp_check, + &SCTP_BASE_SYSCTL(sctp_peer_chunk_oh), 0, sctp_sysctl_handle_int, SCTPCTL_PEER_CHKOH_DESC); sysctl_add_oid(&sysctl_oid_top, "maxburst", CTLTYPE_INT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_max_burst_default), 0, sysctl_sctp_check, + &SCTP_BASE_SYSCTL(sctp_max_burst_default), 0, sctp_sysctl_handle_int, SCTPCTL_MAXBURST_DESC); sysctl_add_oid(&sysctl_oid_top, "fr_maxburst", CTLTYPE_INT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_fr_max_burst_default), 0, sysctl_sctp_check, + &SCTP_BASE_SYSCTL(sctp_fr_max_burst_default), 0, sctp_sysctl_handle_int, SCTPCTL_FRMAXBURST_DESC); sysctl_add_oid(&sysctl_oid_top, "maxchunks", CTLTYPE_INT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_max_chunks_on_queue), 0, sysctl_sctp_check, + &SCTP_BASE_SYSCTL(sctp_max_chunks_on_queue), 0, sctp_sysctl_handle_int, SCTPCTL_MAXCHUNKS_DESC); sysctl_add_oid(&sysctl_oid_top, "tcbhashsize", CTLTYPE_INT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_hashtblsize), 0, sysctl_sctp_check, + &SCTP_BASE_SYSCTL(sctp_hashtblsize), 0, sctp_sysctl_handle_int, SCTPCTL_TCBHASHSIZE_DESC); sysctl_add_oid(&sysctl_oid_top, "pcbhashsize", CTLTYPE_INT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_pcbtblsize), 0, sysctl_sctp_check, + &SCTP_BASE_SYSCTL(sctp_pcbtblsize), 0, sctp_sysctl_handle_int, SCTPCTL_PCBHASHSIZE_DESC); sysctl_add_oid(&sysctl_oid_top, "min_split_point", CTLTYPE_INT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_min_split_point), 0, sysctl_sctp_check, + &SCTP_BASE_SYSCTL(sctp_min_split_point), 0, sctp_sysctl_handle_int, SCTPCTL_MIN_SPLIT_POINT_DESC); sysctl_add_oid(&sysctl_oid_top, "chunkscale", CTLTYPE_INT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_chunkscale), 0, sysctl_sctp_check, + &SCTP_BASE_SYSCTL(sctp_chunkscale), 0, sctp_sysctl_handle_int, SCTPCTL_CHUNKSCALE_DESC); sysctl_add_oid(&sysctl_oid_top, "delayed_sack_time", CTLTYPE_INT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_delayed_sack_time_default), 0, sysctl_sctp_check, + &SCTP_BASE_SYSCTL(sctp_delayed_sack_time_default), 0, sctp_sysctl_handle_int, SCTPCTL_DELAYED_SACK_TIME_DESC); sysctl_add_oid(&sysctl_oid_top, "sack_freq", CTLTYPE_INT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_sack_freq_default), 0, sysctl_sctp_check, + &SCTP_BASE_SYSCTL(sctp_sack_freq_default), 0, sctp_sysctl_handle_int, SCTPCTL_SACK_FREQ_DESC); sysctl_add_oid(&sysctl_oid_top, "sys_resource", CTLTYPE_INT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_system_free_resc_limit), 0, sysctl_sctp_check, + &SCTP_BASE_SYSCTL(sctp_system_free_resc_limit), 0, sctp_sysctl_handle_int, SCTPCTL_SYS_RESOURCE_DESC); sysctl_add_oid(&sysctl_oid_top, "asoc_resource", CTLTYPE_INT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_asoc_free_resc_limit), 0, sysctl_sctp_check, + &SCTP_BASE_SYSCTL(sctp_asoc_free_resc_limit), 0, sctp_sysctl_handle_int, SCTPCTL_ASOC_RESOURCE_DESC); sysctl_add_oid(&sysctl_oid_top, "heartbeat_interval", CTLTYPE_INT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_heartbeat_interval_default), 0, sysctl_sctp_check, + &SCTP_BASE_SYSCTL(sctp_heartbeat_interval_default), 0, sctp_sysctl_handle_int, SCTPCTL_HEARTBEAT_INTERVAL_DESC); sysctl_add_oid(&sysctl_oid_top, "pmtu_raise_time", CTLTYPE_INT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_pmtu_raise_time_default), 0, sysctl_sctp_check, + &SCTP_BASE_SYSCTL(sctp_pmtu_raise_time_default), 0, sctp_sysctl_handle_int, SCTPCTL_PMTU_RAISE_TIME_DESC); sysctl_add_oid(&sysctl_oid_top, "shutdown_guard_time", CTLTYPE_INT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_shutdown_guard_time_default), 0, sysctl_sctp_check, + &SCTP_BASE_SYSCTL(sctp_shutdown_guard_time_default), 0, sctp_sysctl_handle_int, SCTPCTL_SHUTDOWN_GUARD_TIME_DESC); sysctl_add_oid(&sysctl_oid_top, "secret_lifetime", CTLTYPE_INT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_secret_lifetime_default), 0, sysctl_sctp_check, + &SCTP_BASE_SYSCTL(sctp_secret_lifetime_default), 0, sctp_sysctl_handle_int, SCTPCTL_SECRET_LIFETIME_DESC); sysctl_add_oid(&sysctl_oid_top, "rto_max", CTLTYPE_INT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_rto_max_default), 0, sysctl_sctp_check, + &SCTP_BASE_SYSCTL(sctp_rto_max_default), 0, sctp_sysctl_handle_int, SCTPCTL_RTO_MAX_DESC); sysctl_add_oid(&sysctl_oid_top, "rto_min", CTLTYPE_INT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_rto_min_default), 0, sysctl_sctp_check, + &SCTP_BASE_SYSCTL(sctp_rto_min_default), 0, sctp_sysctl_handle_int, SCTPCTL_RTO_MIN_DESC); sysctl_add_oid(&sysctl_oid_top, "rto_initial", CTLTYPE_INT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_rto_initial_default), 0, sysctl_sctp_check, + &SCTP_BASE_SYSCTL(sctp_rto_initial_default), 0, sctp_sysctl_handle_int, SCTPCTL_RTO_INITIAL_DESC); sysctl_add_oid(&sysctl_oid_top, "init_rto_max", CTLTYPE_INT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_init_rto_max_default), 0, sysctl_sctp_check, + &SCTP_BASE_SYSCTL(sctp_init_rto_max_default), 0, sctp_sysctl_handle_int, SCTPCTL_INIT_RTO_MAX_DESC); sysctl_add_oid(&sysctl_oid_top, "valid_cookie_life", CTLTYPE_INT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_valid_cookie_life_default), 0, sysctl_sctp_check, + &SCTP_BASE_SYSCTL(sctp_valid_cookie_life_default), 0, sctp_sysctl_handle_int, SCTPCTL_VALID_COOKIE_LIFE_DESC); sysctl_add_oid(&sysctl_oid_top, "init_rtx_max", CTLTYPE_INT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_init_rtx_max_default), 0, sysctl_sctp_check, + &SCTP_BASE_SYSCTL(sctp_init_rtx_max_default), 0, sctp_sysctl_handle_int, SCTPCTL_INIT_RTX_MAX_DESC); sysctl_add_oid(&sysctl_oid_top, "assoc_rtx_max", CTLTYPE_INT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_assoc_rtx_max_default), 0, sysctl_sctp_check, + &SCTP_BASE_SYSCTL(sctp_assoc_rtx_max_default), 0, sctp_sysctl_handle_int, SCTPCTL_ASSOC_RTX_MAX_DESC); sysctl_add_oid(&sysctl_oid_top, "path_rtx_max", CTLTYPE_INT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_path_rtx_max_default), 0, sysctl_sctp_check, + &SCTP_BASE_SYSCTL(sctp_path_rtx_max_default), 0, sctp_sysctl_handle_int, SCTPCTL_PATH_RTX_MAX_DESC); sysctl_add_oid(&sysctl_oid_top, "path_pf_threshold", CTLTYPE_INT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_path_pf_threshold), 0, sysctl_sctp_check, + &SCTP_BASE_SYSCTL(sctp_path_pf_threshold), 0, sctp_sysctl_handle_int, 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, + &SCTP_BASE_SYSCTL(sctp_add_more_threshold), 0, sctp_sysctl_handle_int, 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, + &SCTP_BASE_SYSCTL(sctp_nr_incoming_streams_default), 0, sctp_sysctl_handle_int, 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, + &SCTP_BASE_SYSCTL(sctp_nr_outgoing_streams_default), 0, sctp_sysctl_handle_int, 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, + &SCTP_BASE_SYSCTL(sctp_cmt_on_off), 0, sctp_sysctl_handle_int, SCTPCTL_CMT_ON_OFF_DESC); - /* EY */ - sysctl_add_oid(&sysctl_oid_top, "nr_sack_on_off", CTLTYPE_INT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_nr_sack_on_off), 0, sysctl_sctp_check, - SCTPCTL_NR_SACK_ON_OFF_DESC); - sysctl_add_oid(&sysctl_oid_top, "cmt_use_dac", CTLTYPE_INT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_cmt_use_dac), 0, sysctl_sctp_check, + &SCTP_BASE_SYSCTL(sctp_cmt_use_dac), 0, sctp_sysctl_handle_int, SCTPCTL_CMT_USE_DAC_DESC); sysctl_add_oid(&sysctl_oid_top, "cwnd_maxburst", CTLTYPE_INT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_use_cwnd_based_maxburst), 0, sysctl_sctp_check, + &SCTP_BASE_SYSCTL(sctp_use_cwnd_based_maxburst), 0, sctp_sysctl_handle_int, SCTPCTL_CWND_MAXBURST_DESC); - sysctl_add_oid(&sysctl_oid_top, "asconf_auth_nochk", CTLTYPE_INT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_asconf_auth_nochk), 0, sysctl_sctp_check, - SCTPCTL_ASCONF_AUTH_NOCHK_DESC); - - sysctl_add_oid(&sysctl_oid_top, "auth_disable", CTLTYPE_INT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_auth_disable), 0, sysctl_sctp_check, - SCTPCTL_AUTH_DISABLE_DESC); - sysctl_add_oid(&sysctl_oid_top, "nat_friendly", CTLTYPE_INT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_nat_friendly), 0, sysctl_sctp_check, + &SCTP_BASE_SYSCTL(sctp_nat_friendly), 0, sctp_sysctl_handle_int, SCTPCTL_NAT_FRIENDLY_DESC); sysctl_add_oid(&sysctl_oid_top, "abc_l_var", CTLTYPE_INT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_L2_abc_variable), 0, sysctl_sctp_check, + &SCTP_BASE_SYSCTL(sctp_L2_abc_variable), 0, sctp_sysctl_handle_int, SCTPCTL_ABC_L_VAR_DESC); sysctl_add_oid(&sysctl_oid_top, "max_chained_mbufs", CTLTYPE_INT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_mbuf_threshold_count), 0, sysctl_sctp_check, + &SCTP_BASE_SYSCTL(sctp_mbuf_threshold_count), 0, sctp_sysctl_handle_int, SCTPCTL_MAX_CHAINED_MBUFS_DESC); sysctl_add_oid(&sysctl_oid_top, "do_sctp_drain", CTLTYPE_INT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_do_drain), 0, sysctl_sctp_check, + &SCTP_BASE_SYSCTL(sctp_do_drain), 0, sctp_sysctl_handle_int, SCTPCTL_DO_SCTP_DRAIN_DESC); sysctl_add_oid(&sysctl_oid_top, "hb_max_burst", CTLTYPE_INT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_hb_maxburst), 0, sysctl_sctp_check, + &SCTP_BASE_SYSCTL(sctp_hb_maxburst), 0, sctp_sysctl_handle_int, SCTPCTL_HB_MAX_BURST_DESC); sysctl_add_oid(&sysctl_oid_top, "abort_at_limit", CTLTYPE_INT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_abort_if_one_2_one_hits_limit), 0, sysctl_sctp_check, + &SCTP_BASE_SYSCTL(sctp_abort_if_one_2_one_hits_limit), 0, sctp_sysctl_handle_int, SCTPCTL_ABORT_AT_LIMIT_DESC); sysctl_add_oid(&sysctl_oid_top, "strict_data_order", CTLTYPE_INT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_strict_data_order), 0, sysctl_sctp_check, + &SCTP_BASE_SYSCTL(sctp_strict_data_order), 0, sctp_sysctl_handle_int, SCTPCTL_STRICT_DATA_ORDER_DESC); sysctl_add_oid(&sysctl_oid_top, "min_residual", CTLTYPE_INT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_min_residual), 0, sysctl_sctp_check, + &SCTP_BASE_SYSCTL(sctp_min_residual), 0, sctp_sysctl_handle_int, SCTPCTL_MIN_RESIDUAL_DESC); sysctl_add_oid(&sysctl_oid_top, "max_retran_chunk", CTLTYPE_INT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_max_retran_chunk), 0, sysctl_sctp_check, + &SCTP_BASE_SYSCTL(sctp_max_retran_chunk), 0, sctp_sysctl_handle_int, SCTPCTL_MAX_RETRAN_CHUNK_DESC); sysctl_add_oid(&sysctl_oid_top, "log_level", CTLTYPE_INT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_logging_level), 0, sysctl_sctp_check, + &SCTP_BASE_SYSCTL(sctp_logging_level), 0, sctp_sysctl_handle_int, SCTPCTL_LOGGING_LEVEL_DESC); sysctl_add_oid(&sysctl_oid_top, "default_cc_module", CTLTYPE_INT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_default_cc_module), 0, sysctl_sctp_check, + &SCTP_BASE_SYSCTL(sctp_default_cc_module), 0, sctp_sysctl_handle_int, SCTPCTL_DEFAULT_CC_MODULE_DESC); sysctl_add_oid(&sysctl_oid_top, "default_ss_module", CTLTYPE_INT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_default_ss_module), 0, sysctl_sctp_check, + &SCTP_BASE_SYSCTL(sctp_default_ss_module), 0, sctp_sysctl_handle_int, SCTPCTL_DEFAULT_SS_MODULE_DESC); sysctl_add_oid(&sysctl_oid_top, "default_frag_interleave", CTLTYPE_INT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_default_frag_interleave), 0, sysctl_sctp_check, + &SCTP_BASE_SYSCTL(sctp_default_frag_interleave), 0, sctp_sysctl_handle_int, SCTPCTL_DEFAULT_FRAG_INTERLEAVE_DESC); sysctl_add_oid(&sysctl_oid_top, "mobility_base", CTLTYPE_INT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_mobility_base), 0, sysctl_sctp_check, + &SCTP_BASE_SYSCTL(sctp_mobility_base), 0, sctp_sysctl_handle_int, SCTPCTL_MOBILITY_BASE_DESC); sysctl_add_oid(&sysctl_oid_top, "mobility_fasthandoff", CTLTYPE_INT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_mobility_fasthandoff), 0, sysctl_sctp_check, + &SCTP_BASE_SYSCTL(sctp_mobility_fasthandoff), 0, sctp_sysctl_handle_int, SCTPCTL_MOBILITY_FASTHANDOFF_DESC); #if defined(SCTP_LOCAL_TRACE_BUF) @@ -1641,67 +1602,67 @@ void sysctl_setup_sctp(void) "SCTP logging (struct sctp_log)"); sysctl_add_oid(&sysctl_oid_top, "clear_trace", CTLTYPE_INT|CTLFLAG_WR, - NULL, 0, sysctl_sctp_cleartrace, + NULL, 0, sctp_sysctl_handle_trace_log_clear, "Clear SCTP Logging buffer"); #endif sysctl_add_oid(&sysctl_oid_top, "udp_tunneling_port", CTLTYPE_INT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_udp_tunneling_port), 0, sysctl_sctp_udp_tunneling_check, + &SCTP_BASE_SYSCTL(sctp_udp_tunneling_port), 0, sctp_sysctl_handle_udp_tunneling, SCTPCTL_UDP_TUNNELING_PORT_DESC); sysctl_add_oid(&sysctl_oid_top, "enable_sack_immediately", CTLTYPE_INT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_enable_sack_immediately), 0, sysctl_sctp_check, + &SCTP_BASE_SYSCTL(sctp_enable_sack_immediately), 0, sctp_sysctl_handle_int, SCTPCTL_SACK_IMMEDIATELY_ENABLE_DESC); sysctl_add_oid(&sysctl_oid_top, "nat_friendly_init", CTLTYPE_INT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_inits_include_nat_friendly), 0, sysctl_sctp_check, + &SCTP_BASE_SYSCTL(sctp_inits_include_nat_friendly), 0, sctp_sysctl_handle_int, SCTPCTL_NAT_FRIENDLY_DESC); sysctl_add_oid(&sysctl_oid_top, "vtag_time_wait", CTLTYPE_INT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_vtag_time_wait), 0, sysctl_sctp_check, + &SCTP_BASE_SYSCTL(sctp_vtag_time_wait), 0, sctp_sysctl_handle_int, SCTPCTL_TIME_WAIT_DESC); sysctl_add_oid(&sysctl_oid_top, "buffer_splitting", CTLTYPE_INT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_buffer_splitting), 0, sysctl_sctp_check, + &SCTP_BASE_SYSCTL(sctp_buffer_splitting), 0, sctp_sysctl_handle_int, SCTPCTL_BUFFER_SPLITTING_DESC); sysctl_add_oid(&sysctl_oid_top, "initial_cwnd", CTLTYPE_INT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_initial_cwnd), 0, sysctl_sctp_check, + &SCTP_BASE_SYSCTL(sctp_initial_cwnd), 0, sctp_sysctl_handle_int, SCTPCTL_INITIAL_CWND_DESC); sysctl_add_oid(&sysctl_oid_top, "rttvar_bw", CTLTYPE_INT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_rttvar_bw), 0, sysctl_sctp_check, + &SCTP_BASE_SYSCTL(sctp_rttvar_bw), 0, sctp_sysctl_handle_int, SCTPCTL_RTTVAR_BW_DESC); sysctl_add_oid(&sysctl_oid_top, "rttvar_rtt", CTLTYPE_INT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_rttvar_rtt), 0, sysctl_sctp_check, + &SCTP_BASE_SYSCTL(sctp_rttvar_rtt), 0, sctp_sysctl_handle_int, SCTPCTL_RTTVAR_RTT_DESC); sysctl_add_oid(&sysctl_oid_top, "rttvar_eqret", CTLTYPE_INT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_rttvar_eqret), 0, sysctl_sctp_check, + &SCTP_BASE_SYSCTL(sctp_rttvar_eqret), 0, sctp_sysctl_handle_int, SCTPCTL_RTTVAR_EQRET_DESC); sysctl_add_oid(&sysctl_oid_top, "rttvar_steady_step", CTLTYPE_INT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_steady_step), 0, sysctl_sctp_check, + &SCTP_BASE_SYSCTL(sctp_steady_step), 0, sctp_sysctl_handle_int, SCTPCTL_RTTVAR_STEADYS_DESC); sysctl_add_oid(&sysctl_oid_top, "use_dcccecn", CTLTYPE_INT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_use_dccc_ecn), 0, sysctl_sctp_check, + &SCTP_BASE_SYSCTL(sctp_use_dccc_ecn), 0, sctp_sysctl_handle_int, SCTPCTL_RTTVAR_DCCCECN_DESC); sysctl_add_oid(&sysctl_oid_top, "blackhole", CTLTYPE_INT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_blackhole), 0, sysctl_sctp_check, - SCTPCTL_BLACKHOLE_DESC); + &SCTP_BASE_SYSCTL(sctp_blackhole), 0, sctp_sysctl_handle_int, + SCTPCTL_BLACKHOLE_DESC); sysctl_add_oid(&sysctl_oid_top, "diag_info_code", CTLTYPE_INT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_diag_info_code), 0, sysctl_sctp_check, - SCTPCTL_DIAG_INFO_CODE_DESC); + &SCTP_BASE_SYSCTL(sctp_diag_info_code), 0, sctp_sysctl_handle_int, + SCTPCTL_DIAG_INFO_CODE_DESC); #ifdef SCTP_DEBUG sysctl_add_oid(&sysctl_oid_top, "debug", CTLTYPE_INT|CTLFLAG_RW, - &SCTP_BASE_SYSCTL(sctp_debug_on), sizeof(SCTP_BASE_SYSCTL(sctp_debug_on)), NULL, + &SCTP_BASE_SYSCTL(sctp_debug_on), 0, sctp_sysctl_handle_int, SCTPCTL_DEBUG_DESC); -#endif /* SCTP_DEBUG */ +#endif sysctl_add_oid(&sysctl_oid_top, "stats", CTLTYPE_STRUCT|CTLFLAG_RW, &SCTP_BASE_STATS, sizeof(SCTP_BASE_STATS), NULL, diff --git a/netinet/sctp_sysctl.h b/netinet/sctp_sysctl.h index 0b6cb16..3a33b71 100755 --- a/netinet/sctp_sysctl.h +++ b/netinet/sctp_sysctl.h @@ -32,7 +32,7 @@ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_sysctl.h 263921 2014-03-29 20:21:36Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp_sysctl.h 271204 2014-09-06 19:12:14Z tuexen $"); #endif #ifndef _NETINET_SCTP_SYSCTL_H_ @@ -47,6 +47,12 @@ struct sctp_sysctl { uint32_t sctp_auto_asconf; uint32_t sctp_multiple_asconfs; uint32_t sctp_ecn_enable; + uint32_t sctp_pr_enable; + uint32_t sctp_auth_enable; + uint32_t sctp_asconf_enable; + uint32_t sctp_reconfig_enable; + uint32_t sctp_nrsack_enable; + uint32_t sctp_pktdrop_enable; uint32_t sctp_fr_max_burst_default; uint32_t sctp_strict_sacks; #if !(defined(__FreeBSD__) && __FreeBSD_version >= 800000) @@ -83,11 +89,7 @@ struct sctp_sysctl { uint32_t sctp_nr_outgoing_streams_default; uint32_t sctp_cmt_on_off; uint32_t sctp_cmt_use_dac; - /* EY 5/5/08 - nr_sack flag variable */ - uint32_t sctp_nr_sack_on_off; uint32_t sctp_use_cwnd_based_maxburst; - uint32_t sctp_asconf_auth_nochk; - uint32_t sctp_auth_disable; uint32_t sctp_nat_friendly; uint32_t sctp_L2_abc_variable; uint32_t sctp_mbuf_threshold_count; @@ -158,7 +160,7 @@ struct sctp_sysctl { #define SCTPCTL_AUTOASCONF_DESC "Enable SCTP Auto-ASCONF" #define SCTPCTL_AUTOASCONF_MIN 0 #define SCTPCTL_AUTOASCONF_MAX 1 -#define SCTPCTL_AUTOASCONF_DEFAULT SCTP_DEFAULT_AUTO_ASCONF +#define SCTPCTL_AUTOASCONF_DEFAULT 1 /* autoasconf: Enable SCTP Auto-ASCONF */ #define SCTPCTL_MULTIPLEASCONFS_DESC "Enable SCTP Muliple-ASCONFs" @@ -172,6 +174,42 @@ struct sctp_sysctl { #define SCTPCTL_ECN_ENABLE_MAX 1 #define SCTPCTL_ECN_ENABLE_DEFAULT 1 +/* pr_enable: Enable PR-SCTP */ +#define SCTPCTL_PR_ENABLE_DESC "Enable PR-SCTP" +#define SCTPCTL_PR_ENABLE_MIN 0 +#define SCTPCTL_PR_ENABLE_MAX 1 +#define SCTPCTL_PR_ENABLE_DEFAULT 1 + +/* auth_enable: Enable SCTP AUTH function */ +#define SCTPCTL_AUTH_ENABLE_DESC "Enable SCTP AUTH function" +#define SCTPCTL_AUTH_ENABLE_MIN 0 +#define SCTPCTL_AUTH_ENABLE_MAX 1 +#define SCTPCTL_AUTH_ENABLE_DEFAULT 1 + +/* asconf_enable: Enable SCTP ASCONF */ +#define SCTPCTL_ASCONF_ENABLE_DESC "Enable SCTP ASCONF" +#define SCTPCTL_ASCONF_ENABLE_MIN 0 +#define SCTPCTL_ASCONF_ENABLE_MAX 1 +#define SCTPCTL_ASCONF_ENABLE_DEFAULT 1 + +/* reconfig_enable: Enable SCTP RE-CONFIG */ +#define SCTPCTL_RECONFIG_ENABLE_DESC "Enable SCTP RE-CONFIG" +#define SCTPCTL_RECONFIG_ENABLE_MIN 0 +#define SCTPCTL_RECONFIG_ENABLE_MAX 1 +#define SCTPCTL_RECONFIG_ENABLE_DEFAULT 1 + +/* nrsack_enable: Enable NR_SACK */ +#define SCTPCTL_NRSACK_ENABLE_DESC "Enable SCTP NR-SACK" +#define SCTPCTL_NRSACK_ENABLE_MIN 0 +#define SCTPCTL_NRSACK_ENABLE_MAX 1 +#define SCTPCTL_NRSACK_ENABLE_DEFAULT 0 + +/* pktdrop_enable: Enable SCTP Packet Drop Reports */ +#define SCTPCTL_PKTDROP_ENABLE_DESC "Enable SCTP PKTDROP" +#define SCTPCTL_PKTDROP_ENABLE_MIN 0 +#define SCTPCTL_PKTDROP_ENABLE_MAX 1 +#define SCTPCTL_PKTDROP_ENABLE_DEFAULT 0 + /* strict_sacks: Enable SCTP Strict SACK checking */ #define SCTPCTL_STRICT_SACKS_DESC "Enable SCTP Strict SACK checking" #define SCTPCTL_STRICT_SACKS_MIN 0 @@ -359,12 +397,6 @@ struct sctp_sysctl { #define SCTPCTL_CMT_ON_OFF_MAX SCTP_CMT_MAX #define SCTPCTL_CMT_ON_OFF_DEFAULT SCTP_CMT_OFF -/* EY - nr_sack_on_off: NR_SACK on/off flag */ -#define SCTPCTL_NR_SACK_ON_OFF_DESC "NR_SACK on/off flag" -#define SCTPCTL_NR_SACK_ON_OFF_MIN 0 -#define SCTPCTL_NR_SACK_ON_OFF_MAX 1 -#define SCTPCTL_NR_SACK_ON_OFF_DEFAULT 0 - /* cmt_use_dac: CMT DAC on/off flag */ #define SCTPCTL_CMT_USE_DAC_DESC "CMT DAC on/off flag" #define SCTPCTL_CMT_USE_DAC_MIN 0 @@ -377,18 +409,6 @@ struct sctp_sysctl { #define SCTPCTL_CWND_MAXBURST_MAX 1 #define SCTPCTL_CWND_MAXBURST_DEFAULT 1 -/* asconf_auth_nochk: Disable SCTP ASCONF AUTH requirement */ -#define SCTPCTL_ASCONF_AUTH_NOCHK_DESC "Disable SCTP ASCONF AUTH requirement" -#define SCTPCTL_ASCONF_AUTH_NOCHK_MIN 0 -#define SCTPCTL_ASCONF_AUTH_NOCHK_MAX 1 -#define SCTPCTL_ASCONF_AUTH_NOCHK_DEFAULT 0 - -/* auth_disable: Disable SCTP AUTH function */ -#define SCTPCTL_AUTH_DISABLE_DESC "Disable SCTP AUTH function" -#define SCTPCTL_AUTH_DISABLE_MIN 0 -#define SCTPCTL_AUTH_DISABLE_MAX 1 -#define SCTPCTL_AUTH_DISABLE_DEFAULT 0 - /* nat_friendly: SCTP NAT friendly operation */ #define SCTPCTL_NAT_FRIENDLY_DESC "SCTP NAT friendly operation" #define SCTPCTL_NAT_FRIENDLY_MIN 0 @@ -471,13 +491,13 @@ struct sctp_sysctl { #define SCTPCTL_MOBILITY_BASE_DESC "Enable SCTP base mobility" #define SCTPCTL_MOBILITY_BASE_MIN 0 #define SCTPCTL_MOBILITY_BASE_MAX 1 -#define SCTPCTL_MOBILITY_BASE_DEFAULT SCTP_DEFAULT_MOBILITY_BASE +#define SCTPCTL_MOBILITY_BASE_DEFAULT 0 /* mobility_fasthandoff: Enable SCTP fast handoff support */ #define SCTPCTL_MOBILITY_FASTHANDOFF_DESC "Enable SCTP fast handoff" #define SCTPCTL_MOBILITY_FASTHANDOFF_MIN 0 #define SCTPCTL_MOBILITY_FASTHANDOFF_MAX 1 -#define SCTPCTL_MOBILITY_FASTHANDOFF_DEFAULT SCTP_DEFAULT_MOBILITY_FASTHANDOFF +#define SCTPCTL_MOBILITY_FASTHANDOFF_DEFAULT 0 /* Enable SCTP/UDP tunneling port */ #define SCTPCTL_UDP_TUNNELING_PORT_DESC "Set the SCTP/UDP tunneling port" @@ -584,12 +604,14 @@ struct sctp_sysctl { #endif #if defined(__APPLE__) -#define SCTPCTL_ADDR_WATCHDOG_LIMIT_MIN 0 -#define SCTPCTL_ADDR_WATCHDOG_LIMIT_MAX 0xFFFFFFFF +#define SCTPCTL_ADDR_WATCHDOG_LIMIT_DESC "Address watchdog limit" +#define SCTPCTL_ADDR_WATCHDOG_LIMIT_MIN 0 +#define SCTPCTL_ADDR_WATCHDOG_LIMIT_MAX 0xFFFFFFFF #define SCTPCTL_ADDR_WATCHDOG_LIMIT_DEFAULT SCTPCTL_ADDR_WATCHDOG_LIMIT_MIN -#define SCTPCTL_VTAG_WATCHDOG_LIMIT_MIN 0 -#define SCTPCTL_VTAG_WATCHDOG_LIMIT_MAX 0xFFFFFFFF +#define SCTPCTL_VTAG_WATCHDOG_LIMIT_DESC "VTag watchdog limit" +#define SCTPCTL_VTAG_WATCHDOG_LIMIT_MIN 0 +#define SCTPCTL_VTAG_WATCHDOG_LIMIT_MAX 0xFFFFFFFF #define SCTPCTL_VTAG_WATCHDOG_LIMIT_DEFAULT SCTPCTL_VTAG_WATCHDOG_LIMIT_MIN #endif diff --git a/netinet/sctp_timer.c b/netinet/sctp_timer.c index 9627dc5..574a213 100755 --- a/netinet/sctp_timer.c +++ b/netinet/sctp_timer.c @@ -32,7 +32,7 @@ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_timer.c 263237 2014-03-16 12:32:16Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp_timer.c 269448 2014-08-02 21:36:40Z tuexen $"); #endif #define _IP_VHL @@ -54,7 +54,7 @@ __FBSDID("$FreeBSD: head/sys/netinet/sctp_timer.c 263237 2014-03-16 12:32:16Z tu #include <netinet/sctp_input.h> #include <netinet/sctp.h> #include <netinet/sctp_uio.h> -#if defined INET || defined INET6 +#if defined(INET) || defined(INET6) #if !defined(__Userspace_os_Windows) #include <netinet/udp.h> #endif @@ -218,7 +218,7 @@ sctp_find_alternate_net(struct sctp_tcb *stcb, * t3 handler. */ if (mnet == net) { - if (min_errors == -1) { + if (min_errors == -1) { min_errors = mnet->error_count + 1; min_errors_net = mnet; } else if (mnet->error_count + 1 < min_errors) { @@ -231,7 +231,7 @@ sctp_find_alternate_net(struct sctp_tcb *stcb, } continue; } else { - if (min_errors == -1) { + if (min_errors == -1) { min_errors = mnet->error_count; min_errors_net = mnet; } else if (mnet->error_count < min_errors) { @@ -335,7 +335,7 @@ sctp_find_alternate_net(struct sctp_tcb *stcb, do { alt = TAILQ_NEXT(mnet, sctp_next); if (alt == NULL) - { + { once++; if (once > 1) { break; @@ -441,7 +441,7 @@ sctp_recover_sent_list(struct sctp_tcb *stcb) sctp_free_bufspace(stcb, asoc, chk, 1); sctp_m_freem(chk->data); chk->data = NULL; - if (asoc->peer_supports_prsctp && PR_SCTP_BUF_ENABLED(chk->flags)) { + if (asoc->prsctp_supported && PR_SCTP_BUF_ENABLED(chk->flags)) { asoc->sent_queue_cnt_removeable--; } } @@ -599,7 +599,7 @@ sctp_mark_all_for_resend(struct sctp_tcb *stcb, continue; } } - if (stcb->asoc.peer_supports_prsctp && PR_SCTP_TTL_ENABLED(chk->flags)) { + if (stcb->asoc.prsctp_supported && PR_SCTP_TTL_ENABLED(chk->flags)) { /* Is it expired? */ #ifndef __FreeBSD__ if (timercmp(&now, &chk->rec.data.timetodrop, >)) { @@ -617,7 +617,7 @@ sctp_mark_all_for_resend(struct sctp_tcb *stcb, continue; } } - if (stcb->asoc.peer_supports_prsctp && PR_SCTP_RTX_ENABLED(chk->flags)) { + if (stcb->asoc.prsctp_supported && PR_SCTP_RTX_ENABLED(chk->flags)) { /* Has it been retransmitted tv_sec times? */ if (chk->snd_count > chk->rec.data.timetodrop.tv_sec) { if (chk->data) { @@ -926,9 +926,9 @@ sctp_t3rxt_timer(struct sctp_inpcb *inp, */ if (net->ro._s_addr) { sctp_free_ifa(net->ro._s_addr); - net->ro._s_addr = NULL; + net->ro._s_addr = NULL; } - net->src_addr_selected = 0; + net->src_addr_selected = 0; /* Force a route allocation too */ if (net->ro.ro_rt) { @@ -964,7 +964,7 @@ sctp_t3rxt_timer(struct sctp_inpcb *inp, sctp_timer_start(SCTP_TIMER_TYPE_SEND, inp, stcb, net); return (0); } - if (stcb->asoc.peer_supports_prsctp) { + if (stcb->asoc.prsctp_supported) { struct sctp_tmit_chunk *lchk; lchk = sctp_try_advance_peer_ack_point(stcb, &stcb->asoc); @@ -1479,7 +1479,7 @@ sctp_pathmtu_timer(struct sctp_inpcb *inp, #elif defined(SCTP_KAME) (void)sa6_embedscope(sin6, MODULE_GLOBAL(ip6_use_defzone)); #else - (void)in6_embedscope(&sin6->sin6_addr, sin6); + (void)in6_embedscope(&sin6->sin6_addr, sin6); #endif } #endif @@ -1504,7 +1504,7 @@ sctp_pathmtu_timer(struct sctp_inpcb *inp, } if (net->ro._s_addr) { mtu = SCTP_GATHER_MTU_FROM_ROUTE(net->ro._s_addr, &net->ro._s_addr.sa, net->ro.ro_rt); -#if defined INET || defined INET6 +#if defined(INET) || defined(INET6) if (net->port) { mtu -= sizeof(struct udphdr); } diff --git a/netinet/sctp_uio.h b/netinet/sctp_uio.h index 7d84313..7cf02ed 100755 --- a/netinet/sctp_uio.h +++ b/netinet/sctp_uio.h @@ -32,7 +32,7 @@ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_uio.h 255160 2013-09-02 22:48:41Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp_uio.h 269945 2014-08-13 15:50:16Z tuexen $"); #endif #ifndef _NETINET_SCTP_UIO_H_ @@ -279,18 +279,23 @@ struct sctp_snd_all_completes { SCTP_SACK_IMMEDIATELY)) != 0) /* for the endpoint */ -/* The lower byte is an enumeration of PR-SCTP policies */ +/* The lower four bits is an enumeration of PR-SCTP policies */ #define SCTP_PR_SCTP_NONE 0x0000 /* Reliable transfer */ #define SCTP_PR_SCTP_TTL 0x0001 /* Time based PR-SCTP */ #define SCTP_PR_SCTP_BUF 0x0002 /* Buffer based PR-SCTP */ #define SCTP_PR_SCTP_RTX 0x0003 /* Number of retransmissions based PR-SCTP */ +#define SCTP_PR_SCTP_MAX SCTP_PR_SCTP_RTX +#define SCTP_PR_SCTP_ALL 0x000f /* Used for aggregated stats */ #define PR_SCTP_POLICY(x) ((x) & 0x0f) -#define PR_SCTP_ENABLED(x) (PR_SCTP_POLICY(x) != SCTP_PR_SCTP_NONE) +#define PR_SCTP_ENABLED(x) ((PR_SCTP_POLICY(x) != SCTP_PR_SCTP_NONE) && \ + (PR_SCTP_POLICY(x) != SCTP_PR_SCTP_ALL)) #define PR_SCTP_TTL_ENABLED(x) (PR_SCTP_POLICY(x) == SCTP_PR_SCTP_TTL) #define PR_SCTP_BUF_ENABLED(x) (PR_SCTP_POLICY(x) == SCTP_PR_SCTP_BUF) #define PR_SCTP_RTX_ENABLED(x) (PR_SCTP_POLICY(x) == SCTP_PR_SCTP_RTX) -#define PR_SCTP_INVALID_POLICY(x) (PR_SCTP_POLICY(x) > SCTP_PR_SCTP_RTX) +#define PR_SCTP_INVALID_POLICY(x) (PR_SCTP_POLICY(x) > SCTP_PR_SCTP_MAX) +#define PR_SCTP_VALID_POLICY(x) (PR_SCTP_POLICY(x) <= SCTP_PR_SCTP_MAX) + /* Stat's */ struct sctp_pcbinfo { uint32_t ep_count; @@ -353,7 +358,6 @@ struct sctp_paddr_change { uint32_t spc_state; uint32_t spc_error; sctp_assoc_t spc_assoc_id; - uint8_t spc_padding[4]; }; /* paddr state values */ @@ -376,7 +380,7 @@ struct sctp_remote_error { uint32_t sre_length; uint16_t sre_error; sctp_assoc_t sre_assoc_id; - uint8_t sre_data[4]; + uint8_t sre_data[]; }; /* data send failure event (deprecated) */ @@ -749,6 +753,14 @@ struct sctp_udpencaps { uint16_t sue_port; }; +struct sctp_prstatus { + sctp_assoc_t sprstat_assoc_id; + uint16_t sprstat_sid; + uint16_t sprstat_policy; + uint64_t sprstat_abandoned_unsent; + uint64_t sprstat_abandoned_sent; +}; + struct sctp_cwnd_args { struct sctp_nets *net; /* network to */ /* FIXME: LP64 issue */ uint32_t cwnd_new_value;/* cwnd in k */ diff --git a/netinet/sctp_usrreq.c b/netinet/sctp_usrreq.c index 796fd16..296b9f3 100755 --- a/netinet/sctp_usrreq.c +++ b/netinet/sctp_usrreq.c @@ -32,7 +32,7 @@ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_usrreq.c 267688 2014-06-20 20:17:39Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp_usrreq.c 271221 2014-09-07 09:06:26Z tuexen $"); #endif #include <netinet/sctp_os.h> @@ -1676,7 +1676,7 @@ sctp_fill_up_addresses_vrf(struct sctp_inpcb *inp, if (ipv4_addr_legal) { struct sockaddr_in *sin; - sin = (struct sockaddr_in *)&sctp_ifa->address.sa; + sin = &sctp_ifa->address.sin; if (sin->sin_addr.s_addr == 0) { /* * we skip unspecifed @@ -1725,7 +1725,7 @@ sctp_fill_up_addresses_vrf(struct sctp_inpcb *inp, #if defined(SCTP_EMBEDDED_V6_SCOPE) && !defined(SCTP_KAME) struct sockaddr_in6 lsa6; #endif - sin6 = (struct sockaddr_in6 *)&sctp_ifa->address.sa; + sin6 = &sctp_ifa->address.sin6; if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { /* * we skip unspecifed @@ -4002,6 +4002,195 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize, } break; } + case SCTP_ECN_SUPPORTED: + { + struct sctp_assoc_value *av; + + SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize); + SCTP_FIND_STCB(inp, stcb, av->assoc_id); + + if (stcb) { + av->assoc_value = stcb->asoc.ecn_supported; + SCTP_TCB_UNLOCK(stcb); + } else { + if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || + (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) || + (av->assoc_id == SCTP_FUTURE_ASSOC)) { + SCTP_INP_RLOCK(inp); + av->assoc_value = inp->ecn_supported; + 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_assoc_value); + } + break; + } + case SCTP_PR_SUPPORTED: + { + struct sctp_assoc_value *av; + + SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize); + SCTP_FIND_STCB(inp, stcb, av->assoc_id); + + if (stcb) { + av->assoc_value = stcb->asoc.prsctp_supported; + SCTP_TCB_UNLOCK(stcb); + } else { + if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || + (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) || + (av->assoc_id == SCTP_FUTURE_ASSOC)) { + SCTP_INP_RLOCK(inp); + av->assoc_value = inp->prsctp_supported; + 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_assoc_value); + } + break; + } + case SCTP_AUTH_SUPPORTED: + { + struct sctp_assoc_value *av; + + SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize); + SCTP_FIND_STCB(inp, stcb, av->assoc_id); + + if (stcb) { + av->assoc_value = stcb->asoc.auth_supported; + SCTP_TCB_UNLOCK(stcb); + } else { + if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || + (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) || + (av->assoc_id == SCTP_FUTURE_ASSOC)) { + SCTP_INP_RLOCK(inp); + av->assoc_value = inp->auth_supported; + 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_assoc_value); + } + break; + } + case SCTP_ASCONF_SUPPORTED: + { + struct sctp_assoc_value *av; + + SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize); + SCTP_FIND_STCB(inp, stcb, av->assoc_id); + + if (stcb) { + av->assoc_value = stcb->asoc.asconf_supported; + SCTP_TCB_UNLOCK(stcb); + } else { + if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || + (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) || + (av->assoc_id == SCTP_FUTURE_ASSOC)) { + SCTP_INP_RLOCK(inp); + av->assoc_value = inp->asconf_supported; + 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_assoc_value); + } + break; + } + case SCTP_RECONFIG_SUPPORTED: + { + struct sctp_assoc_value *av; + + SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize); + SCTP_FIND_STCB(inp, stcb, av->assoc_id); + + if (stcb) { + av->assoc_value = stcb->asoc.reconfig_supported; + SCTP_TCB_UNLOCK(stcb); + } else { + if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || + (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) || + (av->assoc_id == SCTP_FUTURE_ASSOC)) { + SCTP_INP_RLOCK(inp); + av->assoc_value = inp->reconfig_supported; + 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_assoc_value); + } + break; + } + case SCTP_NRSACK_SUPPORTED: + { + struct sctp_assoc_value *av; + + SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize); + SCTP_FIND_STCB(inp, stcb, av->assoc_id); + + if (stcb) { + av->assoc_value = stcb->asoc.nrsack_supported; + SCTP_TCB_UNLOCK(stcb); + } else { + if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || + (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) || + (av->assoc_id == SCTP_FUTURE_ASSOC)) { + SCTP_INP_RLOCK(inp); + av->assoc_value = inp->nrsack_supported; + 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_assoc_value); + } + break; + } + case SCTP_PKTDROP_SUPPORTED: + { + struct sctp_assoc_value *av; + + SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize); + SCTP_FIND_STCB(inp, stcb, av->assoc_id); + + if (stcb) { + av->assoc_value = stcb->asoc.pktdrop_supported; + SCTP_TCB_UNLOCK(stcb); + } else { + if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || + (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) || + (av->assoc_id == SCTP_FUTURE_ASSOC)) { + SCTP_INP_RLOCK(inp); + av->assoc_value = inp->pktdrop_supported; + 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_assoc_value); + } + break; + } case SCTP_ENABLE_STREAM_RESET: { struct sctp_assoc_value *av; @@ -4029,6 +4218,72 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize, } break; } + case SCTP_PR_STREAM_STATUS: + { + struct sctp_prstatus *sprstat; + uint16_t sid; + uint16_t policy; + + SCTP_CHECK_AND_CAST(sprstat, optval, struct sctp_prstatus, *optsize); + SCTP_FIND_STCB(inp, stcb, sprstat->sprstat_assoc_id); + + sid = sprstat->sprstat_sid; + policy = sprstat->sprstat_policy; +#if defined(SCTP_DETAILED_STR_STATS) + if ((stcb != NULL) && + (policy != SCTP_PR_SCTP_NONE) && + (sid < stcb->asoc.streamoutcnt) && + ((policy == SCTP_PR_SCTP_ALL) || + (PR_SCTP_VALID_POLICY(policy)))) { +#else + if ((stcb != NULL) && + (policy != SCTP_PR_SCTP_NONE) && + (sid < stcb->asoc.streamoutcnt) && + (policy == SCTP_PR_SCTP_ALL)) { +#endif + if (policy == SCTP_PR_SCTP_ALL) { + sprstat->sprstat_abandoned_unsent = stcb->asoc.strmout[sid].abandoned_unsent[0]; + sprstat->sprstat_abandoned_sent = stcb->asoc.strmout[sid].abandoned_sent[0]; + } else { + sprstat->sprstat_abandoned_unsent = stcb->asoc.strmout[sid].abandoned_unsent[policy]; + sprstat->sprstat_abandoned_sent = stcb->asoc.strmout[sid].abandoned_sent[policy]; + } + SCTP_TCB_UNLOCK(stcb); + *optsize = sizeof(struct sctp_prstatus); + } else { + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); + error = EINVAL; + } + break; + } + case SCTP_PR_ASSOC_STATUS: + { + struct sctp_prstatus *sprstat; + uint16_t policy; + + SCTP_CHECK_AND_CAST(sprstat, optval, struct sctp_prstatus, *optsize); + SCTP_FIND_STCB(inp, stcb, sprstat->sprstat_assoc_id); + + policy = sprstat->sprstat_policy; + if ((stcb != NULL) && + (policy != SCTP_PR_SCTP_NONE) && + ((policy == SCTP_PR_SCTP_ALL) || + (PR_SCTP_VALID_POLICY(policy)))) { + if (policy == SCTP_PR_SCTP_ALL) { + sprstat->sprstat_abandoned_unsent = stcb->asoc.abandoned_unsent[0]; + sprstat->sprstat_abandoned_sent = stcb->asoc.abandoned_sent[0]; + } else { + sprstat->sprstat_abandoned_unsent = stcb->asoc.abandoned_unsent[policy]; + sprstat->sprstat_abandoned_sent = stcb->asoc.abandoned_sent[policy]; + } + SCTP_TCB_UNLOCK(stcb); + *optsize = sizeof(struct sctp_prstatus); + } else { + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); + error = EINVAL; + } + break; + } default: SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT); error = ENOPROTOOPT; @@ -4452,7 +4707,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, /* The VRF must be in the VRF list */ if (*default_vrfid == inp->m_vrf_ids[i]) { SCTP_INP_WLOCK(inp); - inp->def_vrf_id = *default_vrfid; + inp->def_vrf_id = *default_vrfid; SCTP_INP_WUNLOCK(inp); goto sctp_done; } @@ -4571,7 +4826,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP); error = EOPNOTSUPP; #endif - break; + break; } case SCTP_DELAYED_SACK: { @@ -4987,7 +5242,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, error = ENOENT; break; } - if (stcb->asoc.peer_supports_strreset == 0) { + if (stcb->asoc.reconfig_supported == 0) { /* * Peer does not support the chunk type. */ @@ -5054,7 +5309,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, error = ENOENT; break; } - if (stcb->asoc.peer_supports_strreset == 0) { + if (stcb->asoc.reconfig_supported == 0) { /* * Peer does not support the chunk type. */ @@ -5120,7 +5375,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, error = ENOENT; break; } - if (stcb->asoc.peer_supports_strreset == 0) { + if (stcb->asoc.reconfig_supported == 0) { /* * Peer does not support the chunk type. */ @@ -5662,7 +5917,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, } if (net->dest_state & SCTP_ADDR_REACHABLE) { if (net->error_count > paddrp->spp_pathmaxrxt) { - net->dest_state &= ~SCTP_ADDR_REACHABLE; + net->dest_state &= ~SCTP_ADDR_REACHABLE; sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED); } } else { @@ -5705,7 +5960,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, } if (net->dest_state & SCTP_ADDR_REACHABLE) { if (net->error_count > paddrp->spp_pathmaxrxt) { - net->dest_state &= ~SCTP_ADDR_REACHABLE; + net->dest_state &= ~SCTP_ADDR_REACHABLE; sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED); } } else { @@ -6204,7 +6459,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, #endif { error = EAFNOSUPPORT; - break; + break; } sctp_bindx_add_address(so, inp, addrs->addr, addrs->sget_assoc_id, vrf_id, @@ -6602,7 +6857,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, } else { if ((net->failure_threshold > thlds->spt_pathpfthld) && (net->failure_threshold <= thlds->spt_pathmaxrxt)) { - net->dest_state |= SCTP_ADDR_PF; + net->dest_state |= SCTP_ADDR_PF; sctp_send_hb(stcb, net, SCTP_SO_LOCKED); sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3); sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net); @@ -6631,7 +6886,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, } else { if ((net->failure_threshold > thlds->spt_pathpfthld) && (net->failure_threshold <= thlds->spt_pathmaxrxt)) { - net->dest_state |= SCTP_ADDR_PF; + net->dest_state |= SCTP_ADDR_PF; sctp_send_hb(stcb, net, SCTP_SO_LOCKED); sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3); sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net); @@ -6762,6 +7017,231 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, } break; } + case SCTP_ECN_SUPPORTED: + { + struct sctp_assoc_value *av; + + SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize); + SCTP_FIND_STCB(inp, stcb, av->assoc_id); + + if (stcb) { + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); + error = EINVAL; + SCTP_TCB_UNLOCK(stcb); + } else { + if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || + (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) || + (av->assoc_id == SCTP_FUTURE_ASSOC)) { + SCTP_INP_WLOCK(inp); + if (av->assoc_value == 0) { + inp->ecn_supported = 0; + } else { + inp->ecn_supported = 1; + } + SCTP_INP_WUNLOCK(inp); + } else { + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); + error = EINVAL; + } + } + break; + } + case SCTP_PR_SUPPORTED: + { + struct sctp_assoc_value *av; + + SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize); + SCTP_FIND_STCB(inp, stcb, av->assoc_id); + + if (stcb) { + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); + error = EINVAL; + SCTP_TCB_UNLOCK(stcb); + } else { + if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || + (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) || + (av->assoc_id == SCTP_FUTURE_ASSOC)) { + SCTP_INP_WLOCK(inp); + if (av->assoc_value == 0) { + inp->prsctp_supported = 0; + } else { + inp->prsctp_supported = 1; + } + SCTP_INP_WUNLOCK(inp); + } else { + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); + error = EINVAL; + } + } + break; + } + case SCTP_AUTH_SUPPORTED: + { + struct sctp_assoc_value *av; + + SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize); + SCTP_FIND_STCB(inp, stcb, av->assoc_id); + + if (stcb) { + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); + error = EINVAL; + SCTP_TCB_UNLOCK(stcb); + } else { + if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || + (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) || + (av->assoc_id == SCTP_FUTURE_ASSOC)) { + if ((av->assoc_value == 0) && + (inp->asconf_supported == 1)) { + /* AUTH is required for ASCONF */ + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); + error = EINVAL; + } else { + SCTP_INP_WLOCK(inp); + if (av->assoc_value == 0) { + inp->auth_supported = 0; + } else { + inp->auth_supported = 1; + } + SCTP_INP_WUNLOCK(inp); + } + } else { + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); + error = EINVAL; + } + } + break; + } + case SCTP_ASCONF_SUPPORTED: + { + struct sctp_assoc_value *av; + + SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize); + SCTP_FIND_STCB(inp, stcb, av->assoc_id); + + if (stcb) { + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); + error = EINVAL; + SCTP_TCB_UNLOCK(stcb); + } else { + if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || + (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) || + (av->assoc_id == SCTP_FUTURE_ASSOC)) { + if ((av->assoc_value != 0) && + (inp->auth_supported == 0)) { + /* AUTH is required for ASCONF */ + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); + error = EINVAL; + } else { + SCTP_INP_WLOCK(inp); + if (av->assoc_value == 0) { + inp->asconf_supported = 0; + sctp_auth_delete_chunk(SCTP_ASCONF, + inp->sctp_ep.local_auth_chunks); + sctp_auth_delete_chunk(SCTP_ASCONF_ACK, + inp->sctp_ep.local_auth_chunks); + } else { + inp->asconf_supported = 1; + sctp_auth_add_chunk(SCTP_ASCONF, + inp->sctp_ep.local_auth_chunks); + sctp_auth_add_chunk(SCTP_ASCONF_ACK, + inp->sctp_ep.local_auth_chunks); + } + SCTP_INP_WUNLOCK(inp); + } + } else { + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); + error = EINVAL; + } + } + break; + } + case SCTP_RECONFIG_SUPPORTED: + { + struct sctp_assoc_value *av; + + SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize); + SCTP_FIND_STCB(inp, stcb, av->assoc_id); + + if (stcb) { + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); + error = EINVAL; + SCTP_TCB_UNLOCK(stcb); + } else { + if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || + (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) || + (av->assoc_id == SCTP_FUTURE_ASSOC)) { + SCTP_INP_WLOCK(inp); + if (av->assoc_value == 0) { + inp->reconfig_supported = 0; + } else { + inp->reconfig_supported = 1; + } + SCTP_INP_WUNLOCK(inp); + } else { + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); + error = EINVAL; + } + } + break; + } + case SCTP_NRSACK_SUPPORTED: + { + struct sctp_assoc_value *av; + + SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize); + SCTP_FIND_STCB(inp, stcb, av->assoc_id); + + if (stcb) { + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); + error = EINVAL; + SCTP_TCB_UNLOCK(stcb); + } else { + if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || + (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) || + (av->assoc_id == SCTP_FUTURE_ASSOC)) { + SCTP_INP_WLOCK(inp); + if (av->assoc_value == 0) { + inp->nrsack_supported = 0; + } else { + inp->nrsack_supported = 1; + } + SCTP_INP_WUNLOCK(inp); + } else { + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); + error = EINVAL; + } + } + break; + } + case SCTP_PKTDROP_SUPPORTED: + { + struct sctp_assoc_value *av; + + SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize); + SCTP_FIND_STCB(inp, stcb, av->assoc_id); + + if (stcb) { + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); + error = EINVAL; + SCTP_TCB_UNLOCK(stcb); + } else { + if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || + (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) || + (av->assoc_id == SCTP_FUTURE_ASSOC)) { + SCTP_INP_WLOCK(inp); + if (av->assoc_value == 0) { + inp->pktdrop_supported = 0; + } else { + inp->pktdrop_supported = 1; + } + SCTP_INP_WUNLOCK(inp); + } else { + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); + error = EINVAL; + } + } + break; + } default: SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT); error = ENOPROTOOPT; @@ -6928,7 +7408,7 @@ sctp_connect(struct socket *so, struct mbuf *nam, struct proc *p) #endif default: SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EAFNOSUPPORT); - return (EAFNOSUPPORT); + return (EAFNOSUPPORT); } #endif SCTP_INP_INCR_REF(inp); @@ -7103,7 +7583,7 @@ sctpconn_connect(struct socket *so, struct sockaddr *addr) break; default: SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EAFNOSUPPORT); - return (EAFNOSUPPORT); + return (EAFNOSUPPORT); } SCTP_INP_INCR_REF(inp); SCTP_ASOC_CREATE_LOCK(inp); @@ -7735,7 +8215,7 @@ sctp_ingetaddr(struct socket *so, struct mbuf *nam) if (laddr->ifa->address.sa.sa_family == AF_INET) { struct sockaddr_in *sin_a; - sin_a = (struct sockaddr_in *)&laddr->ifa->address.sa; + sin_a = &laddr->ifa->address.sin; sin->sin_addr = sin_a->sin_addr; fnd = 1; break; diff --git a/netinet/sctp_var.h b/netinet/sctp_var.h index f2a0316..be2f2b9 100755 --- a/netinet/sctp_var.h +++ b/netinet/sctp_var.h @@ -32,7 +32,7 @@ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_var.h 242327 2012-10-29 20:47:32Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp_var.h 269699 2014-08-08 01:57:15Z kevlo $"); #endif #ifndef _NETINET_SCTP_VAR_H_ @@ -76,7 +76,7 @@ extern struct pr_usrreqs sctp_usrreqs; ((stcb->asoc.sctp_features & feature) == 0)) || \ ((stcb == NULL) && (inp != NULL) && \ ((inp->sctp_features & feature) == 0)) || \ - ((stcb == NULL) && (inp == NULL))) + ((stcb == NULL) && (inp == NULL))) /* managing mobility_feature in inpcb (by micchie) */ #define sctp_mobility_feature_on(inp, feature) (inp->sctp_mobility_features |= feature) @@ -110,7 +110,7 @@ extern struct pr_usrreqs sctp_usrreqs; #define sctp_alloc_a_readq(_stcb, _readq) { \ (_readq) = SCTP_ZONE_GET(SCTP_BASE_INFO(ipi_zone_readq), struct sctp_queued_to_read); \ if ((_readq)) { \ - SCTP_INCR_READQ_COUNT(); \ + SCTP_INCR_READQ_COUNT(); \ } \ } @@ -125,11 +125,11 @@ extern struct pr_usrreqs sctp_usrreqs; #define sctp_alloc_a_strmoq(_stcb, _strmoq) { \ (_strmoq) = SCTP_ZONE_GET(SCTP_BASE_INFO(ipi_zone_strmoq), struct sctp_stream_queue_pending); \ - if ((_strmoq)) { \ + if ((_strmoq)) { \ memset(_strmoq, 0, sizeof(struct sctp_stream_queue_pending)); \ SCTP_INCR_STRMOQ_COUNT(); \ (_strmoq)->holds_key_ref = 0; \ - } \ + } \ } #define sctp_free_a_chunk(_stcb, _chk, _so_locked) { \ @@ -137,22 +137,22 @@ extern struct pr_usrreqs sctp_usrreqs; sctp_auth_key_release((_stcb), (_chk)->auth_keyid, _so_locked); \ (_chk)->holds_key_ref = 0; \ } \ - if (_stcb) { \ - SCTP_TCB_LOCK_ASSERT((_stcb)); \ - if ((_chk)->whoTo) { \ - sctp_free_remote_addr((_chk)->whoTo); \ - (_chk)->whoTo = NULL; \ - } \ - if (((_stcb)->asoc.free_chunk_cnt > SCTP_BASE_SYSCTL(sctp_asoc_free_resc_limit)) || \ - (SCTP_BASE_INFO(ipi_free_chunks) > SCTP_BASE_SYSCTL(sctp_system_free_resc_limit))) { \ - SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_chunk), (_chk)); \ - SCTP_DECR_CHK_COUNT(); \ - } else { \ - TAILQ_INSERT_TAIL(&(_stcb)->asoc.free_chunks, (_chk), sctp_next); \ - (_stcb)->asoc.free_chunk_cnt++; \ - atomic_add_int(&SCTP_BASE_INFO(ipi_free_chunks), 1); \ - } \ - } else { \ + if (_stcb) { \ + SCTP_TCB_LOCK_ASSERT((_stcb)); \ + if ((_chk)->whoTo) { \ + sctp_free_remote_addr((_chk)->whoTo); \ + (_chk)->whoTo = NULL; \ + } \ + if (((_stcb)->asoc.free_chunk_cnt > SCTP_BASE_SYSCTL(sctp_asoc_free_resc_limit)) || \ + (SCTP_BASE_INFO(ipi_free_chunks) > SCTP_BASE_SYSCTL(sctp_system_free_resc_limit))) { \ + SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_chunk), (_chk)); \ + SCTP_DECR_CHK_COUNT(); \ + } else { \ + TAILQ_INSERT_TAIL(&(_stcb)->asoc.free_chunks, (_chk), sctp_next); \ + (_stcb)->asoc.free_chunk_cnt++; \ + atomic_add_int(&SCTP_BASE_INFO(ipi_free_chunks), 1); \ + } \ + } else { \ SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_chunk), (_chk)); \ SCTP_DECR_CHK_COUNT(); \ } \ @@ -163,7 +163,7 @@ extern struct pr_usrreqs sctp_usrreqs; (_chk) = SCTP_ZONE_GET(SCTP_BASE_INFO(ipi_zone_chunk), struct sctp_tmit_chunk); \ if ((_chk)) { \ SCTP_INCR_CHK_COUNT(); \ - (_chk)->whoTo = NULL; \ + (_chk)->whoTo = NULL; \ (_chk)->holds_key_ref = 0; \ } \ } else { \ @@ -171,7 +171,7 @@ extern struct pr_usrreqs sctp_usrreqs; TAILQ_REMOVE(&(_stcb)->asoc.free_chunks, (_chk), sctp_next); \ atomic_subtract_int(&SCTP_BASE_INFO(ipi_free_chunks), 1); \ (_chk)->holds_key_ref = 0; \ - SCTP_STAT_INCR(sctps_cached_chk); \ + SCTP_STAT_INCR(sctps_cached_chk); \ (_stcb)->asoc.free_chunk_cnt--; \ } \ } @@ -183,15 +183,15 @@ extern struct pr_usrreqs sctp_usrreqs; if (SCTP_DECREMENT_AND_CHECK_REFCOUNT(&(__net)->ref_count)) { \ (void)SCTP_OS_TIMER_STOP(&(__net)->rxt_timer.timer); \ (void)SCTP_OS_TIMER_STOP(&(__net)->pmtu_timer.timer); \ - if ((__net)->ro.ro_rt) { \ + if ((__net)->ro.ro_rt) { \ RTFREE((__net)->ro.ro_rt); \ (__net)->ro.ro_rt = NULL; \ - } \ + } \ if ((__net)->src_addr_selected) { \ sctp_free_ifa((__net)->ro._s_addr); \ (__net)->ro._s_addr = NULL; \ } \ - (__net)->src_addr_selected = 0; \ + (__net)->src_addr_selected = 0; \ (__net)->dest_state &= ~SCTP_ADDR_REACHABLE; \ SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_net), (__net)); \ SCTP_DECR_RADDR_COUNT(); \ @@ -231,15 +231,15 @@ extern struct pr_usrreqs sctp_usrreqs; (void)SCTP_OS_TIMER_STOP(&(__net)->rxt_timer.timer); \ (void)SCTP_OS_TIMER_STOP(&(__net)->pmtu_timer.timer); \ (void)SCTP_OS_TIMER_STOP(&(__net)->hb_timer.timer); \ - if ((__net)->ro.ro_rt) { \ + if ((__net)->ro.ro_rt) { \ RTFREE((__net)->ro.ro_rt); \ (__net)->ro.ro_rt = NULL; \ - } \ + } \ if ((__net)->src_addr_selected) { \ sctp_free_ifa((__net)->ro._s_addr); \ (__net)->ro._s_addr = NULL; \ } \ - (__net)->src_addr_selected = 0; \ + (__net)->src_addr_selected = 0; \ (__net)->dest_state &=~SCTP_ADDR_REACHABLE; \ SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_net), (__net)); \ SCTP_DECR_RADDR_COUNT(); \ @@ -323,12 +323,12 @@ extern struct pr_usrreqs sctp_usrreqs; } while (0) #define sctp_flight_size_increase(tp1) do { \ - (tp1)->whoTo->flight_size += (tp1)->book_size; \ + (tp1)->whoTo->flight_size += (tp1)->book_size; \ } while (0) #ifdef SCTP_FS_SPEC_LOG #define sctp_total_flight_decrease(stcb, tp1) do { \ - if (stcb->asoc.fs_index > SCTP_FS_SPEC_LOG_SIZE) \ + if (stcb->asoc.fs_index > SCTP_FS_SPEC_LOG_SIZE) \ stcb->asoc.fs_index = 0;\ stcb->asoc.fslog[stcb->asoc.fs_index].total_flight = stcb->asoc.total_flight; \ stcb->asoc.fslog[stcb->asoc.fs_index].tsn = tp1->rec.data.TSN_seq; \ @@ -337,7 +337,7 @@ extern struct pr_usrreqs sctp_usrreqs; stcb->asoc.fslog[stcb->asoc.fs_index].incr = 0; \ stcb->asoc.fslog[stcb->asoc.fs_index].decr = 1; \ stcb->asoc.fs_index++; \ - tp1->window_probe = 0; \ + tp1->window_probe = 0; \ if (stcb->asoc.total_flight >= tp1->book_size) { \ stcb->asoc.total_flight -= tp1->book_size; \ if (stcb->asoc.total_flight_count > 0) \ @@ -349,7 +349,7 @@ extern struct pr_usrreqs sctp_usrreqs; } while (0) #define sctp_total_flight_increase(stcb, tp1) do { \ - if (stcb->asoc.fs_index > SCTP_FS_SPEC_LOG_SIZE) \ + if (stcb->asoc.fs_index > SCTP_FS_SPEC_LOG_SIZE) \ stcb->asoc.fs_index = 0;\ stcb->asoc.fslog[stcb->asoc.fs_index].total_flight = stcb->asoc.total_flight; \ stcb->asoc.fslog[stcb->asoc.fs_index].tsn = tp1->rec.data.TSN_seq; \ @@ -358,14 +358,14 @@ extern struct pr_usrreqs sctp_usrreqs; stcb->asoc.fslog[stcb->asoc.fs_index].incr = 1; \ stcb->asoc.fslog[stcb->asoc.fs_index].decr = 0; \ stcb->asoc.fs_index++; \ - (stcb)->asoc.total_flight_count++; \ - (stcb)->asoc.total_flight += (tp1)->book_size; \ + (stcb)->asoc.total_flight_count++; \ + (stcb)->asoc.total_flight += (tp1)->book_size; \ } while (0) #else #define sctp_total_flight_decrease(stcb, tp1) do { \ - tp1->window_probe = 0; \ + tp1->window_probe = 0; \ if (stcb->asoc.total_flight >= tp1->book_size) { \ stcb->asoc.total_flight -= tp1->book_size; \ if (stcb->asoc.total_flight_count > 0) \ @@ -377,8 +377,8 @@ extern struct pr_usrreqs sctp_usrreqs; } while (0) #define sctp_total_flight_increase(stcb, tp1) do { \ - (stcb)->asoc.total_flight_count++; \ - (stcb)->asoc.total_flight += (tp1)->book_size; \ + (stcb)->asoc.total_flight_count++; \ + (stcb)->asoc.total_flight += (tp1)->book_size; \ } while (0) #endif @@ -412,8 +412,12 @@ void sctp_ctlinput(int, struct sockaddr *, void *); int sctp_ctloutput(struct socket *, struct sockopt *); #ifdef INET void sctp_input_with_port(struct mbuf *, int, uint16_t); +#if defined(__FreeBSD__) && __FreeBSD_version >= 1100020 +int sctp_input(struct mbuf **, int *, int); +#else void sctp_input(struct mbuf *, int); #endif +#endif void sctp_pathmtu_adjustment(struct sctp_tcb *, uint16_t); #endif #else diff --git a/netinet/sctputil.c b/netinet/sctputil.c index 73cf3ab..87e770d 100755 --- a/netinet/sctputil.c +++ b/netinet/sctputil.c @@ -32,7 +32,7 @@ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctputil.c 267674 2014-06-20 13:26:49Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctputil.c 271221 2014-09-07 09:06:26Z tuexen $"); #endif #include <netinet/sctp_os.h> @@ -963,6 +963,9 @@ sctp_init_asoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, * caller in the sctp_aloc_assoc() function. */ int i; +#if defined(SCTP_DETAILED_STR_STATS) + int j; +#endif asoc = &stcb->asoc; /* init all variables to a known value. */ @@ -972,8 +975,13 @@ sctp_init_asoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, asoc->heart_beat_delay = TICKS_TO_MSEC(inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT]); asoc->cookie_life = inp->sctp_ep.def_cookie_life; asoc->sctp_cmt_on_off = inp->sctp_cmt_on_off; - asoc->ecn_allowed = inp->sctp_ecn_enable; - asoc->sctp_nr_sack_on_off = (uint8_t)SCTP_BASE_SYSCTL(sctp_nr_sack_on_off); + asoc->ecn_supported = inp->ecn_supported; + asoc->prsctp_supported = inp->prsctp_supported; + asoc->auth_supported = inp->auth_supported; + asoc->asconf_supported = inp->asconf_supported; + asoc->reconfig_supported = inp->reconfig_supported; + asoc->nrsack_supported = inp->nrsack_supported; + asoc->pktdrop_supported = inp->pktdrop_supported; asoc->sctp_cmt_pf = (uint8_t)0; asoc->sctp_frag_point = inp->sctp_frag_point; asoc->sctp_features = inp->sctp_features; @@ -1004,7 +1012,7 @@ sctp_init_asoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, #ifdef SCTP_ASOCLOG_OF_TSNS asoc->tsn_in_at = 0; - asoc->tsn_out_at = 0; + asoc->tsn_out_at = 0; asoc->tsn_in_wrapped = 0; asoc->tsn_out_wrapped = 0; asoc->cumack_log_at = 0; @@ -1019,7 +1027,6 @@ sctp_init_asoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, sctp_select_initial_TSN(&inp->sctp_ep); asoc->asconf_seq_out_acked = asoc->asconf_seq_out - 1; /* we are optimisitic here */ - asoc->peer_supports_pktdrop = 1; asoc->peer_supports_nat = 0; asoc->sent_queue_retran_cnt = 0; @@ -1133,6 +1140,15 @@ sctp_init_asoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, asoc->strmout[i].next_sequence_send = 0x0; TAILQ_INIT(&asoc->strmout[i].outqueue); asoc->strmout[i].chunks_on_queues = 0; +#if defined(SCTP_DETAILED_STR_STATS) + for (j = 0; j < SCTP_PR_SCTP_MAX + 1; j++) { + asoc->strmout[i].abandoned_sent[j] = 0; + asoc->strmout[i].abandoned_unsent[j] = 0; + } +#else + asoc->strmout[i].abandoned_sent[0] = 0; + asoc->strmout[i].abandoned_unsent[0] = 0; +#endif asoc->strmout[i].stream_no = i; asoc->strmout[i].last_msg_incomplete = 0; asoc->ss_functions.sctp_ss_init_stream(&asoc->strmout[i], NULL); @@ -1188,6 +1204,10 @@ sctp_init_asoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, asoc->timoshutdownack = 0; (void)SCTP_GETTIME_TIMEVAL(&asoc->start_time); asoc->discontinuity_time = asoc->start_time; + for (i = 0; i < SCTP_PR_SCTP_MAX + 1; i++) { + asoc->abandoned_unsent[i] = 0; + asoc->abandoned_sent[i] = 0; + } /* sa_ignore MEMLEAK {memory is put in the assoc mapping array and freed later when * the association is freed. */ @@ -1273,7 +1293,7 @@ sctp_iterator_work(struct sctp_iterator *it) SCTP_INP_INFO_RLOCK(); SCTP_ITERATOR_LOCK(); - if (it->inp) { + if (it->inp) { SCTP_INP_RLOCK(it->inp); SCTP_INP_DECR_REF(it->inp); } @@ -1816,7 +1836,7 @@ sctp_timeout_handler(void *t) goto out_decr; } SCTP_STAT_INCR(sctps_timoshutdownack); - stcb->asoc.timoshutdownack++; + stcb->asoc.timoshutdownack++; #ifdef SCTP_AUDITING_ENABLED sctp_auditing(4, inp, stcb, net); #endif @@ -2566,15 +2586,15 @@ sctp_calculate_rto(struct sctp_tcb *stcb, stcb->asoc.sat_network = 0; stcb->asoc.sat_network_lockout = 1; } - /* bound it, per C6/C7 in Section 5.3.1 */ - if (new_rto < stcb->asoc.minrto) { + /* bound it, per C6/C7 in Section 5.3.1 */ + if (new_rto < stcb->asoc.minrto) { new_rto = stcb->asoc.minrto; } if (new_rto > stcb->asoc.maxrto) { new_rto = stcb->asoc.maxrto; } /* we are now returning the RTO */ - return (new_rto); + return (new_rto); } /* @@ -2637,58 +2657,44 @@ sctp_get_next_param(struct mbuf *m, } -int +struct mbuf * sctp_add_pad_tombuf(struct mbuf *m, int padlen) { - /* - * add padlen bytes of 0 filled padding to the end of the mbuf. If - * padlen is > 3 this routine will fail. - */ - uint8_t *dp; - int i; + struct mbuf *m_last; + caddr_t dp; if (padlen > 3) { - SCTP_LTRACE_ERR_RET_PKT(m, NULL, NULL, NULL, SCTP_FROM_SCTPUTIL, ENOBUFS); - return (ENOBUFS); + return (NULL); } if (padlen <= M_TRAILINGSPACE(m)) { /* * The easy way. We hope the majority of the time we hit * here :) */ - dp = (uint8_t *) (mtod(m, caddr_t) + SCTP_BUF_LEN(m)); - SCTP_BUF_LEN(m) += padlen; + m_last = m; } else { - /* Hard way we must grow the mbuf */ - struct mbuf *tmp; - - tmp = sctp_get_mbuf_for_msg(padlen, 0, M_NOWAIT, 1, MT_DATA); - if (tmp == NULL) { - /* Out of space GAK! we are in big trouble. */ - SCTP_LTRACE_ERR_RET_PKT(m, NULL, NULL, NULL, SCTP_FROM_SCTPUTIL, ENOBUFS); - return (ENOBUFS); - } - /* setup and insert in middle */ - SCTP_BUF_LEN(tmp) = padlen; - SCTP_BUF_NEXT(tmp) = NULL; - SCTP_BUF_NEXT(m) = tmp; - dp = mtod(tmp, uint8_t *); - } - /* zero out the pad */ - for (i = 0; i < padlen; i++) { - *dp = 0; - dp++; + /* Hard way we must grow the mbuf chain */ + m_last = sctp_get_mbuf_for_msg(padlen, 0, M_NOWAIT, 1, MT_DATA); + if (m_last == NULL) { + return (NULL); + } + SCTP_BUF_LEN(m_last) = 0; + SCTP_BUF_NEXT(m_last) = NULL; + SCTP_BUF_NEXT(m) = m_last; } - return (0); + dp = mtod(m_last, caddr_t) + SCTP_BUF_LEN(m_last); + SCTP_BUF_LEN(m_last) += padlen; + memset(dp, 0, padlen); + return (m_last); } -int +struct mbuf * sctp_pad_lastmbuf(struct mbuf *m, int padval, struct mbuf *last_mbuf) { /* find the last mbuf in chain and pad it */ struct mbuf *m_at; - if (last_mbuf) { + if (last_mbuf != NULL) { return (sctp_add_pad_tombuf(last_mbuf, padval)); } else { for (m_at = m; m_at; m_at = SCTP_BUF_NEXT(m_at)) { @@ -2697,8 +2703,7 @@ sctp_pad_lastmbuf(struct mbuf *m, int padval, struct mbuf *last_mbuf) } } } - SCTP_LTRACE_ERR_RET_PKT(m, NULL, NULL, NULL, SCTP_FROM_SCTPUTIL, EFAULT); - return (EFAULT); + return (NULL); } static void @@ -2741,6 +2746,7 @@ sctp_notify_assoc_change(uint16_t state, struct sctp_tcb *stcb, } SCTP_BUF_NEXT(m_notify) = NULL; sac = mtod(m_notify, struct sctp_assoc_change *); + memset(sac, 0, notif_len); sac->sac_type = SCTP_ASSOC_CHANGE; sac->sac_flags = 0; sac->sac_length = sizeof(struct sctp_assoc_change); @@ -2753,17 +2759,17 @@ sctp_notify_assoc_change(uint16_t state, struct sctp_tcb *stcb, if (notif_len > sizeof(struct sctp_assoc_change)) { if ((state == SCTP_COMM_UP) || (state == SCTP_RESTART)) { i = 0; - if (stcb->asoc.peer_supports_prsctp) { + if (stcb->asoc.prsctp_supported == 1) { sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_PR; } - if (stcb->asoc.peer_supports_auth) { + if (stcb->asoc.auth_supported == 1) { sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_AUTH; } - if (stcb->asoc.peer_supports_asconf) { + if (stcb->asoc.asconf_supported == 1) { sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_ASCONF; } sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_MULTIBUF; - if (stcb->asoc.peer_supports_strreset) { + if (stcb->asoc.reconfig_supported == 1) { sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_RE_CONFIG; } sac->sac_length += i; @@ -2868,6 +2874,7 @@ sctp_notify_peer_addr_change(struct sctp_tcb *stcb, uint32_t state, return; SCTP_BUF_LEN(m_notify) = 0; spc = mtod(m_notify, struct sctp_paddr_change *); + memset(spc, 0, sizeof(struct sctp_paddr_change)); spc->spc_type = SCTP_PEER_ADDR_CHANGE; spc->spc_flags = 0; spc->spc_length = sizeof(struct sctp_paddr_change); @@ -2891,7 +2898,7 @@ sctp_notify_peer_addr_change(struct sctp_tcb *stcb, uint32_t state, if (sin6->sin6_scope_id == 0) { /* recover scope_id for user */ #ifdef SCTP_KAME - (void)sa6_recoverscope(sin6); + (void)sa6_recoverscope(sin6); #else (void)in6_recoverscope(sin6, &sin6->sin6_addr, NULL); @@ -2972,21 +2979,21 @@ sctp_notify_send_failed(struct sctp_tcb *stcb, uint8_t sent, uint32_t error, if (m_notify == NULL) /* no space left */ return; - length += chk->send_size; - length -= sizeof(struct sctp_data_chunk); SCTP_BUF_LEN(m_notify) = 0; if (sctp_stcb_is_feature_on(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVNSENDFAILEVNT)) { ssfe = mtod(m_notify, struct sctp_send_failed_event *); + memset(ssfe, 0, length); ssfe->ssfe_type = SCTP_SEND_FAILED_EVENT; if (sent) { ssfe->ssfe_flags = SCTP_DATA_SENT; } else { ssfe->ssfe_flags = SCTP_DATA_UNSENT; } + length += chk->send_size; + length -= sizeof(struct sctp_data_chunk); ssfe->ssfe_length = length; ssfe->ssfe_error = error; /* not exactly what the user sent in, but should be close :) */ - bzero(&ssfe->ssfe_info, sizeof(ssfe->ssfe_info)); ssfe->ssfe_info.snd_sid = chk->rec.data.stream_number; ssfe->ssfe_info.snd_flags = chk->rec.data.rcv_flags; ssfe->ssfe_info.snd_ppid = chk->rec.data.payloadtype; @@ -2996,12 +3003,15 @@ sctp_notify_send_failed(struct sctp_tcb *stcb, uint8_t sent, uint32_t error, SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_send_failed_event); } else { ssf = mtod(m_notify, struct sctp_send_failed *); + memset(ssf, 0, length); ssf->ssf_type = SCTP_SEND_FAILED; if (sent) { ssf->ssf_flags = SCTP_DATA_SENT; } else { ssf->ssf_flags = SCTP_DATA_UNSENT; } + length += chk->send_size; + length -= sizeof(struct sctp_data_chunk); ssf->ssf_length = length; ssf->ssf_error = error; /* not exactly what the user sent in, but should be close :) */ @@ -3086,16 +3096,16 @@ sctp_notify_send_failed2(struct sctp_tcb *stcb, uint32_t error, /* no space left */ return; } - length += sp->length; SCTP_BUF_LEN(m_notify) = 0; if (sctp_stcb_is_feature_on(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVNSENDFAILEVNT)) { ssfe = mtod(m_notify, struct sctp_send_failed_event *); + memset(ssfe, 0, length); ssfe->ssfe_type = SCTP_SEND_FAILED_EVENT; ssfe->ssfe_flags = SCTP_DATA_UNSENT; + length += sp->length; ssfe->ssfe_length = length; ssfe->ssfe_error = error; /* not exactly what the user sent in, but should be close :) */ - bzero(&ssfe->ssfe_info, sizeof(ssfe->ssfe_info)); ssfe->ssfe_info.snd_sid = sp->stream; if (sp->some_taken) { ssfe->ssfe_info.snd_flags = SCTP_DATA_LAST_FRAG; @@ -3109,12 +3119,13 @@ sctp_notify_send_failed2(struct sctp_tcb *stcb, uint32_t error, SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_send_failed_event); } else { ssf = mtod(m_notify, struct sctp_send_failed *); + memset(ssf, 0, length); ssf->ssf_type = SCTP_SEND_FAILED; ssf->ssf_flags = SCTP_DATA_UNSENT; + length += sp->length; ssf->ssf_length = length; ssf->ssf_error = error; /* not exactly what the user sent in, but should be close :) */ - bzero(&ssf->ssf_info, sizeof(ssf->ssf_info)); ssf->ssf_info.sinfo_stream = sp->stream; ssf->ssf_info.sinfo_ssn = 0; if (sp->some_taken) { @@ -3177,6 +3188,7 @@ sctp_notify_adaptation_layer(struct sctp_tcb *stcb) return; SCTP_BUF_LEN(m_notify) = 0; sai = mtod(m_notify, struct sctp_adaptation_event *); + memset(sai, 0, sizeof(struct sctp_adaptation_event)); sai->sai_type = SCTP_ADAPTATION_INDICATION; sai->sai_flags = 0; sai->sai_length = sizeof(struct sctp_adaptation_event); @@ -3233,6 +3245,7 @@ sctp_notify_partial_delivery_indication(struct sctp_tcb *stcb, uint32_t error, return; SCTP_BUF_LEN(m_notify) = 0; pdapi = mtod(m_notify, struct sctp_pdapi_event *); + memset(pdapi, 0, sizeof(struct sctp_pdapi_event)); pdapi->pdapi_type = SCTP_PARTIAL_DELIVERY_EVENT; pdapi->pdapi_flags = 0; pdapi->pdapi_length = sizeof(struct sctp_pdapi_event); @@ -3343,6 +3356,7 @@ sctp_notify_shutdown_event(struct sctp_tcb *stcb) /* no space left */ return; sse = mtod(m_notify, struct sctp_shutdown_event *); + memset(sse, 0, sizeof(struct sctp_shutdown_event)); sse->sse_type = SCTP_SHUTDOWN_EVENT; sse->sse_flags = 0; sse->sse_length = sizeof(struct sctp_shutdown_event); @@ -3394,6 +3408,7 @@ sctp_notify_sender_dry_event(struct sctp_tcb *stcb, } SCTP_BUF_LEN(m_notify) = 0; event = mtod(m_notify, struct sctp_sender_dry_event *); + memset(event, 0, sizeof(struct sctp_sender_dry_event)); event->sender_dry_type = SCTP_SENDER_DRY_EVENT; event->sender_dry_flags = 0; event->sender_dry_length = sizeof(struct sctp_sender_dry_event); @@ -3426,7 +3441,6 @@ sctp_notify_stream_reset_add(struct sctp_tcb *stcb, uint16_t numberin, uint16_t struct mbuf *m_notify; struct sctp_queued_to_read *control; struct sctp_stream_change_event *stradd; - int len; if ((stcb == NULL) || (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_STREAM_CHANGEEVNT))) { @@ -3439,25 +3453,20 @@ sctp_notify_stream_reset_add(struct sctp_tcb *stcb, uint16_t numberin, uint16_t return; } stcb->asoc.peer_req_out = 0; - m_notify = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_NOWAIT, 1, MT_DATA); + m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_stream_change_event), 0, M_NOWAIT, 1, MT_DATA); if (m_notify == NULL) /* no space left */ return; SCTP_BUF_LEN(m_notify) = 0; - len = sizeof(struct sctp_stream_change_event); - if (len > M_TRAILINGSPACE(m_notify)) { - /* never enough room */ - sctp_m_freem(m_notify); - return; - } stradd = mtod(m_notify, struct sctp_stream_change_event *); + memset(stradd, 0, sizeof(struct sctp_stream_change_event)); stradd->strchange_type = SCTP_STREAM_CHANGE_EVENT; stradd->strchange_flags = flag; - stradd->strchange_length = len; + stradd->strchange_length = sizeof(struct sctp_stream_change_event); stradd->strchange_assoc_id = sctp_get_associd(stcb); stradd->strchange_instrms = numberin; stradd->strchange_outstrms = numberout; - SCTP_BUF_LEN(m_notify) = len; + SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_stream_change_event); SCTP_BUF_NEXT(m_notify) = NULL; if (sctp_sbspace(&stcb->asoc, &stcb->sctp_socket->so_rcv) < SCTP_BUF_LEN(m_notify)) { /* no space */ @@ -3488,32 +3497,26 @@ sctp_notify_stream_reset_tsn(struct sctp_tcb *stcb, uint32_t sending_tsn, uint32 struct mbuf *m_notify; struct sctp_queued_to_read *control; struct sctp_assoc_reset_event *strasoc; - int len; if ((stcb == NULL) || (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_ASSOC_RESETEVNT))) { /* event not enabled */ return; } - m_notify = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_NOWAIT, 1, MT_DATA); + m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_assoc_reset_event), 0, M_NOWAIT, 1, MT_DATA); if (m_notify == NULL) /* no space left */ return; SCTP_BUF_LEN(m_notify) = 0; - len = sizeof(struct sctp_assoc_reset_event); - if (len > M_TRAILINGSPACE(m_notify)) { - /* never enough room */ - sctp_m_freem(m_notify); - return; - } strasoc = mtod(m_notify, struct sctp_assoc_reset_event *); + memset(strasoc, 0, sizeof(struct sctp_assoc_reset_event)); strasoc->assocreset_type = SCTP_ASSOC_RESET_EVENT; strasoc->assocreset_flags = flag; - strasoc->assocreset_length = len; + strasoc->assocreset_length = sizeof(struct sctp_assoc_reset_event); strasoc->assocreset_assoc_id= sctp_get_associd(stcb); strasoc->assocreset_local_tsn = sending_tsn; strasoc->assocreset_remote_tsn = recv_tsn; - SCTP_BUF_LEN(m_notify) = len; + SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_assoc_reset_event); SCTP_BUF_NEXT(m_notify) = NULL; if (sctp_sbspace(&stcb->asoc, &stcb->sctp_socket->so_rcv) < SCTP_BUF_LEN(m_notify)) { /* no space */ @@ -3567,6 +3570,7 @@ sctp_notify_stream_reset(struct sctp_tcb *stcb, return; } strreset = mtod(m_notify, struct sctp_stream_reset_event *); + memset(strreset, 0, len); strreset->strreset_type = SCTP_STREAM_RESET_EVENT; strreset->strreset_flags = flag; strreset->strreset_length = len; @@ -3633,6 +3637,7 @@ sctp_notify_remote_error(struct sctp_tcb *stcb, uint16_t error, struct sctp_erro } SCTP_BUF_NEXT(m_notify) = NULL; sre = mtod(m_notify, struct sctp_remote_error *); + memset(sre, 0, notif_len); sre->sre_type = SCTP_REMOTE_ERROR; sre->sre_flags = 0; sre->sre_length = sizeof(struct sctp_remote_error); @@ -3708,7 +3713,7 @@ sctp_ulp_notify(uint32_t notification, struct sctp_tcb *stcb, if (stcb->asoc.adaptation_needed && (stcb->asoc.adaptation_sent == 0)) { sctp_notify_adaptation_layer(stcb); } - if (stcb->asoc.peer_supports_auth == 0) { + if (stcb->asoc.auth_supported == 0) { sctp_ulp_notify(SCTP_NOTIFY_NO_PEER_AUTH, stcb, 0, NULL, so_locked); } @@ -3797,7 +3802,7 @@ sctp_ulp_notify(uint32_t notification, struct sctp_tcb *stcb, break; case SCTP_NOTIFY_ASSOC_RESTART: sctp_notify_assoc_change(SCTP_RESTART, stcb, error, NULL, 0, so_locked); - if (stcb->asoc.peer_supports_auth == 0) { + if (stcb->asoc.auth_supported == 0) { sctp_ulp_notify(SCTP_NOTIFY_NO_PEER_AUTH, stcb, 0, NULL, so_locked); } @@ -5173,6 +5178,7 @@ sctp_release_pr_sctp_chunk(struct sctp_tcb *stcb, struct sctp_tmit_chunk *tp1, int ret_sz = 0; int notdone; int do_wakeup_routine = 0; + #if defined(__APPLE__) if (so_locked) { sctp_lock_assert(SCTP_INP_SO(stcb->sctp_ep)); @@ -5182,6 +5188,21 @@ sctp_release_pr_sctp_chunk(struct sctp_tcb *stcb, struct sctp_tmit_chunk *tp1, #endif stream = tp1->rec.data.stream_number; seq = tp1->rec.data.stream_seq; + if (sent || !(tp1->rec.data.rcv_flags & SCTP_DATA_FIRST_FRAG)) { + stcb->asoc.abandoned_sent[0]++; + stcb->asoc.abandoned_sent[PR_SCTP_POLICY(tp1->flags)]++; + stcb->asoc.strmout[stream].abandoned_sent[0]++; +#if defined(SCTP_DETAILED_STR_STATS) + stcb->asoc.strmout[stream].abandoned_sent[PR_SCTP_POLICY(tp1->flags)]++; +#endif + } else { + stcb->asoc.abandoned_unsent[0]++; + stcb->asoc.abandoned_unsent[PR_SCTP_POLICY(tp1->flags)]++; + stcb->asoc.strmout[stream].abandoned_unsent[0]++; +#if defined(SCTP_DETAILED_STR_STATS) + stcb->asoc.strmout[stream].abandoned_unsent[PR_SCTP_POLICY(tp1->flags)]++; +#endif + } do { ret_sz += tp1->book_size; if (tp1->data != NULL) { @@ -5232,7 +5253,7 @@ sctp_release_pr_sctp_chunk(struct sctp_tcb *stcb, struct sctp_tmit_chunk *tp1, */ TAILQ_FOREACH_SAFE(tp1, &stcb->asoc.send_queue, sctp_next, tp2) { if ((tp1->rec.data.stream_number != stream) || - (tp1->rec.data.stream_seq != seq)) { + (tp1->rec.data.stream_seq != seq)) { break; } /* save to chk in case we have some on stream out @@ -6904,9 +6925,12 @@ sctp_soreceive( struct socket *so, #if defined(__APPLE__) SCTP_SOCKET_LOCK(so, 1); #endif + if (filling_sinfo) { + memset(&sinfo, 0, sizeof(struct sctp_extrcvinfo)); + } error = sctp_sorecvmsg(so, uio, mp0, from, fromlen, flagsp, (struct sctp_sndrcvinfo *)&sinfo, filling_sinfo); - if ((controlp) && (filling_sinfo)) { + if (controlp != NULL) { /* copy back the sinfo in a CMSG format */ if (filling_sinfo) *controlp = sctp_build_ctl_nchunk(inp, @@ -7561,7 +7585,7 @@ sctp_local_addr_count(struct sctp_tcb *stcb) if (ipv4_addr_legal) { struct sockaddr_in *sin; - sin = (struct sockaddr_in *)&sctp_ifa->address.sa; + sin = &sctp_ifa->address.sin; if (sin->sin_addr.s_addr == 0) { /* skip unspecified addrs */ continue; @@ -7591,7 +7615,7 @@ sctp_local_addr_count(struct sctp_tcb *stcb) #if defined(SCTP_EMBEDDED_V6_SCOPE) && !defined(SCTP_KAME) struct sockaddr_in6 lsa6; #endif - sin6 = (struct sockaddr_in6 *)&sctp_ifa->address.sa; + sin6 = &sctp_ifa->address.sin6; if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { continue; } diff --git a/netinet/sctputil.h b/netinet/sctputil.h index eec6c80..c807c66 100755 --- a/netinet/sctputil.h +++ b/netinet/sctputil.h @@ -32,7 +32,7 @@ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctputil.h 264679 2014-04-19 19:21:06Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctputil.h 269376 2014-08-01 12:42:37Z tuexen $"); #endif #ifndef _NETINET_SCTP_UTIL_H_ @@ -146,9 +146,11 @@ struct sctp_paramhdr * sctp_get_next_param(struct mbuf *, int, struct sctp_paramhdr *, int); -int sctp_add_pad_tombuf(struct mbuf *, int); +struct mbuf * +sctp_add_pad_tombuf(struct mbuf *, int); -int sctp_pad_lastmbuf(struct mbuf *, int, struct mbuf *); +struct mbuf * +sctp_pad_lastmbuf(struct mbuf *, int, struct mbuf *); void sctp_ulp_notify(uint32_t, struct sctp_tcb *, uint32_t, void *, int #if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING) @@ -240,10 +242,10 @@ sctp_recover_scope(struct sockaddr_in6 *, struct sockaddr_in6 *); } while (0) #else #define sctp_recover_scope_mac(addr, store) do { \ - if ((addr->sin6_family == AF_INET6) && \ - (IN6_IS_SCOPE_LINKLOCAL(&addr->sin6_addr))) { \ + if ((addr->sin6_family == AF_INET6) && \ + (IN6_IS_SCOPE_LINKLOCAL(&addr->sin6_addr))) { \ *store = *addr; \ - if (addr->sin6_scope_id == 0) { \ + if (addr->sin6_scope_id == 0) { \ if (!in6_recoverscope(store, &store->sin6_addr, \ NULL)) { \ addr = store; \ @@ -252,7 +254,7 @@ sctp_recover_scope(struct sockaddr_in6 *, struct sockaddr_in6 *); in6_clearscope(&addr->sin6_addr); \ addr = store; \ } \ - } \ + } \ } while (0) #endif #endif @@ -291,42 +293,42 @@ sctp_free_bufspace(struct sctp_tcb *, struct sctp_association *, #define sctp_free_bufspace(stcb, asoc, tp1, chk_cnt) \ do { \ if (tp1->data != NULL) { \ - atomic_subtract_int(&((asoc)->chunks_on_out_queue), chk_cnt); \ + atomic_subtract_int(&((asoc)->chunks_on_out_queue), chk_cnt); \ if ((asoc)->total_output_queue_size >= tp1->book_size) { \ atomic_subtract_int(&((asoc)->total_output_queue_size), tp1->book_size); \ } else { \ (asoc)->total_output_queue_size = 0; \ } \ - if (stcb->sctp_socket && ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || \ - (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL))) { \ + if (stcb->sctp_socket && ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || \ + (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL))) { \ if (stcb->sctp_socket->so_snd.sb_cc >= tp1->book_size) { \ atomic_subtract_int(&((stcb)->sctp_socket->so_snd.sb_cc), tp1->book_size); \ } else { \ stcb->sctp_socket->so_snd.sb_cc = 0; \ } \ } \ - } \ + } \ } while (0) #endif #define sctp_free_spbufspace(stcb, asoc, sp) \ do { \ - if (sp->data != NULL) { \ + if (sp->data != NULL) { \ if ((asoc)->total_output_queue_size >= sp->length) { \ atomic_subtract_int(&(asoc)->total_output_queue_size, sp->length); \ } else { \ (asoc)->total_output_queue_size = 0; \ } \ - if (stcb->sctp_socket && ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || \ - (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL))) { \ + if (stcb->sctp_socket && ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || \ + (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL))) { \ if (stcb->sctp_socket->so_snd.sb_cc >= sp->length) { \ atomic_subtract_int(&stcb->sctp_socket->so_snd.sb_cc,sp->length); \ } else { \ stcb->sctp_socket->so_snd.sb_cc = 0; \ } \ } \ - } \ + } \ } while (0) #define sctp_snd_sb_alloc(stcb, sz) \ diff --git a/netinet6/sctp6_usrreq.c b/netinet6/sctp6_usrreq.c index 45a3196..3874794 100644 --- a/netinet6/sctp6_usrreq.c +++ b/netinet6/sctp6_usrreq.c @@ -32,7 +32,7 @@ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet6/sctp6_usrreq.c 257555 2013-11-02 20:12:19Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet6/sctp6_usrreq.c 271221 2014-09-07 09:06:26Z tuexen $"); #endif #include <netinet/sctp_os.h> @@ -246,7 +246,7 @@ sctp6_input(struct mbuf **i_pak, int *offp, int proto) #if defined(__APPLE__) /* XXX: This code should also be used on Apple */ #endif - if (in6_setscope(&src.sin6_addr, m->m_pkthdr.rcvif, NULL) != 0) { + if (in6_setscope(&src.sin6_addr, m->m_pkthdr.rcvif, NULL) != 0) { goto out; } #endif @@ -261,7 +261,7 @@ sctp6_input(struct mbuf **i_pak, int *offp, int proto) #if defined(__APPLE__) /* XXX: This code should also be used on Apple */ #endif - if (in6_setscope(&dst.sin6_addr, m->m_pkthdr.rcvif, NULL) != 0) { + if (in6_setscope(&dst.sin6_addr, m->m_pkthdr.rcvif, NULL) != 0) { goto out; } #endif @@ -1184,7 +1184,7 @@ sctp6_connect(struct socket *so, struct mbuf *nam, struct proc *p) #ifdef INET struct in6pcb *inp6; struct sockaddr_in6 *sin6; - struct sockaddr_storage ss; + union sctp_sockstore store; #endif #ifdef INET @@ -1273,8 +1273,8 @@ sctp6_connect(struct socket *so, struct mbuf *nam, struct proc *p) } if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { /* convert v4-mapped into v4 addr */ - in6_sin6_2_sin((struct sockaddr_in *)&ss, sin6); - addr = (struct sockaddr *)&ss; + in6_sin6_2_sin(&store.sin, sin6); + addr = &store.sa; } #endif /* INET */ /* Now do we connect? */ @@ -1424,7 +1424,7 @@ sctp6_getaddr(struct socket *so, struct mbuf *nam) if (laddr->ifa->address.sa.sa_family == AF_INET6) { struct sockaddr_in6 *sin_a; - sin_a = (struct sockaddr_in6 *)&laddr->ifa->address.sin6; + sin_a = &laddr->ifa->address.sin6; sin6->sin6_addr = sin_a->sin6_addr; fnd = 1; break; @@ -1729,7 +1729,7 @@ struct pr_usrreqs sctp6_usrreqs = { .pru_sockaddr = sctp6_in6getaddr, .pru_sosend = sctp_sosend, .pru_soreceive = sctp_soreceive, - .pru_sopoll = sopoll + .pru_sopoll = sopoll #elif defined(__Windows__) sctp6_abort, sctp_accept, diff --git a/user_socket.c b/user_socket.c index 1b44f11..9a0e0c7 100755 --- a/user_socket.c +++ b/user_socket.c @@ -710,6 +710,7 @@ userspace_sctp_sendmsg(struct socket *so, struct uio auio; struct iovec iov[1]; + memset(sinfo, 0, sizeof(struct sctp_sndrcvinfo)); sinfo->sinfo_ppid = ppid; sinfo->sinfo_flags = flags; sinfo->sinfo_stream = stream_no; @@ -3247,6 +3248,12 @@ USRSCTP_SYSCTL_SET_DEF(sctp_recvspace) USRSCTP_SYSCTL_SET_DEF(sctp_auto_asconf) USRSCTP_SYSCTL_SET_DEF(sctp_multiple_asconfs) USRSCTP_SYSCTL_SET_DEF(sctp_ecn_enable) +USRSCTP_SYSCTL_SET_DEF(sctp_pr_enable) +USRSCTP_SYSCTL_SET_DEF(sctp_auth_enable) +USRSCTP_SYSCTL_SET_DEF(sctp_asconf_enable) +USRSCTP_SYSCTL_SET_DEF(sctp_reconfig_enable) +USRSCTP_SYSCTL_SET_DEF(sctp_nrsack_enable) +USRSCTP_SYSCTL_SET_DEF(sctp_pktdrop_enable) USRSCTP_SYSCTL_SET_DEF(sctp_strict_sacks) #if !defined(SCTP_WITH_NO_CSUM) USRSCTP_SYSCTL_SET_DEF(sctp_no_csum_on_loopback) @@ -3278,10 +3285,7 @@ USRSCTP_SYSCTL_SET_DEF(sctp_add_more_threshold) USRSCTP_SYSCTL_SET_DEF(sctp_nr_outgoing_streams_default) USRSCTP_SYSCTL_SET_DEF(sctp_cmt_on_off) USRSCTP_SYSCTL_SET_DEF(sctp_cmt_use_dac) -USRSCTP_SYSCTL_SET_DEF(sctp_nr_sack_on_off) USRSCTP_SYSCTL_SET_DEF(sctp_use_cwnd_based_maxburst) -USRSCTP_SYSCTL_SET_DEF(sctp_asconf_auth_nochk) -USRSCTP_SYSCTL_SET_DEF(sctp_auth_disable) USRSCTP_SYSCTL_SET_DEF(sctp_nat_friendly) USRSCTP_SYSCTL_SET_DEF(sctp_L2_abc_variable) USRSCTP_SYSCTL_SET_DEF(sctp_mbuf_threshold_count) @@ -3326,6 +3330,12 @@ USRSCTP_SYSCTL_GET_DEF(sctp_recvspace) USRSCTP_SYSCTL_GET_DEF(sctp_auto_asconf) USRSCTP_SYSCTL_GET_DEF(sctp_multiple_asconfs) USRSCTP_SYSCTL_GET_DEF(sctp_ecn_enable) +USRSCTP_SYSCTL_GET_DEF(sctp_pr_enable) +USRSCTP_SYSCTL_GET_DEF(sctp_auth_enable) +USRSCTP_SYSCTL_GET_DEF(sctp_asconf_enable) +USRSCTP_SYSCTL_GET_DEF(sctp_reconfig_enable) +USRSCTP_SYSCTL_GET_DEF(sctp_nrsack_enable) +USRSCTP_SYSCTL_GET_DEF(sctp_pktdrop_enable) USRSCTP_SYSCTL_GET_DEF(sctp_strict_sacks) #if !defined(SCTP_WITH_NO_CSUM) USRSCTP_SYSCTL_GET_DEF(sctp_no_csum_on_loopback) @@ -3357,10 +3367,7 @@ USRSCTP_SYSCTL_GET_DEF(sctp_add_more_threshold) USRSCTP_SYSCTL_GET_DEF(sctp_nr_outgoing_streams_default) USRSCTP_SYSCTL_GET_DEF(sctp_cmt_on_off) USRSCTP_SYSCTL_GET_DEF(sctp_cmt_use_dac) -USRSCTP_SYSCTL_GET_DEF(sctp_nr_sack_on_off) USRSCTP_SYSCTL_GET_DEF(sctp_use_cwnd_based_maxburst) -USRSCTP_SYSCTL_GET_DEF(sctp_asconf_auth_nochk) -USRSCTP_SYSCTL_GET_DEF(sctp_auth_disable) USRSCTP_SYSCTL_GET_DEF(sctp_nat_friendly) USRSCTP_SYSCTL_GET_DEF(sctp_L2_abc_variable) USRSCTP_SYSCTL_GET_DEF(sctp_mbuf_threshold_count) @@ -983,7 +983,7 @@ usrsctp_dumppacket(void *, size_t, int); void usrsctp_freedumpbuffer(char *); -#define USRSCTP_SYSCTL_DECL(__field) \ +#define USRSCTP_SYSCTL_DECL(__field) \ void usrsctp_sysctl_set_ ## __field(uint32_t value);\ uint32_t usrsctp_sysctl_get_ ## __field(void); @@ -992,6 +992,12 @@ USRSCTP_SYSCTL_DECL(sctp_recvspace) USRSCTP_SYSCTL_DECL(sctp_auto_asconf) USRSCTP_SYSCTL_DECL(sctp_multiple_asconfs) USRSCTP_SYSCTL_DECL(sctp_ecn_enable) +USRSCTP_SYSCTL_DECL(sctp_pr_enable) +USRSCTP_SYSCTL_DECL(sctp_auth_enable) +USRSCTP_SYSCTL_DECL(sctp_asconf_enable) +USRSCTP_SYSCTL_DECL(sctp_reconfig_enable) +USRSCTP_SYSCTL_DECL(sctp_nrsack_enable) +USRSCTP_SYSCTL_DECL(sctp_pktdrop_enable) USRSCTP_SYSCTL_DECL(sctp_strict_sacks) #if !defined(SCTP_WITH_NO_CSUM) USRSCTP_SYSCTL_DECL(sctp_no_csum_on_loopback) @@ -1024,10 +1030,7 @@ USRSCTP_SYSCTL_DECL(sctp_nr_incoming_streams_default) USRSCTP_SYSCTL_DECL(sctp_nr_outgoing_streams_default) USRSCTP_SYSCTL_DECL(sctp_cmt_on_off) USRSCTP_SYSCTL_DECL(sctp_cmt_use_dac) -USRSCTP_SYSCTL_DECL(sctp_nr_sack_on_off) USRSCTP_SYSCTL_DECL(sctp_use_cwnd_based_maxburst) -USRSCTP_SYSCTL_DECL(sctp_asconf_auth_nochk) -USRSCTP_SYSCTL_DECL(sctp_auth_disable) USRSCTP_SYSCTL_DECL(sctp_nat_friendly) USRSCTP_SYSCTL_DECL(sctp_L2_abc_variable) USRSCTP_SYSCTL_DECL(sctp_mbuf_threshold_count) |