Bug 1826339 - Update to latest libusrsctp. r=bwc

Differential Revision: https://phabricator.services.mozilla.com/D174635
This commit is contained in:
Ryan VanderMeulen 2023-04-04 14:35:25 +00:00
parent 7317157573
commit 57c18d5d8b
20 changed files with 596 additions and 528 deletions

View File

@ -1,21 +0,0 @@
sctp updated from CVS on Tue Mar 20 01:04:08 EDT 2012
sctp updated from CVS on Fri Jun 1 01:31:43 EDT 2012
sctp updated from CVS on Tue Jul 10 12:30:59 EDT 2012
sctp updated from CVS on Thu Jul 12 00:31:32 EDT 2012
sctp updated from CVS on Tue Jul 24 15:38:37 EDT 2012
sctp updated from CVS on Sun Aug 5 03:51:50 EDT 2012
sctp updated from CVS on Mon Aug 6 04:17:12 EDT 2012
sctp updated to version 8119 from SVN on Wed Aug 29 21:52:12 EDT 2012
sctp updated to version 8131 from SVN on Tue Sep 4 00:26:11 EDT 2012
sctp updated to version 8165 from SVN on Wed Sep 5 09:39:43 EDT 2012
sctp updated to version 8176 from SVN on Wed Sep 5 18:02:08 EDT 2012
sctp updated to version 8263 from SVN on Sun Sep 16 00:48:48 EDT 2012
sctp updated to version 8279 from SVN on Thu Sep 20 18:19:24 EDT 2012
sctp updated to version 8397 from SVN on Wed Jan 9 00:41:16 EST 2013
sctp updated to version 8443 from SVN on Sun Mar 31 09:05:07 EDT 2013
sctp updated to version 8815 from SVN on Tue Mar 4 08:50:51 EST 2014
sctp updated to version 9168 from SVN on Tue Mar 3 12:11:40 EST 2015
sctp updated to version 9209 from SVN on Tue Mar 24 18:11:59 EDT 2015
sctp updated to version 0e076261b832121cf120ddc04aaff87ac3a34d30 from git on Tue Nov 28 15:20:51 EST 2017
sctp updated to version ea345b6d0c8a0f8701cf49445dba5ec8d34e2305 from git on Tue 30 Jun 14:01:18 CEST 2020
sctp updated to version 8e12cd9e01fc94d2e84ea1afa351c845966e116e from git on Mon Oct 17 10:23:01 CDT 2022

View File

@ -10,8 +10,8 @@ origin:
url: https://github.com/sctplab/usrsctp/blob/master/Manual.md
release: 8e12cd9e01fc94d2e84ea1afa351c845966e116e (2022-10-12T23:26:25Z).
revision: 8e12cd9e01fc94d2e84ea1afa351c845966e116e
release: f9f95023816b61a2f257d2fb77658dceaea7213f (2023-03-18T22:38:54Z).
revision: f9f95023816b61a2f257d2fb77658dceaea7213f
license: BSD-3-Clause

View File

@ -139,6 +139,7 @@ struct sctp_paramhdr {
#define SCTP_NRSACK_SUPPORTED 0x00000030
#define SCTP_PKTDROP_SUPPORTED 0x00000031
#define SCTP_MAX_CWND 0x00000032
#define SCTP_ACCEPT_ZERO_CHECKSUM 0x00000033
/*
* read-only options

View File

@ -419,7 +419,7 @@ extern void getwintimeofday(struct timeval *tv);
/*************0x8000 series*************/
#define SCTP_ECN_CAPABLE 0x8000
#define SCTP_ZERO_CHECKSUM_ACCEPTABLE 0x8001
/* RFC 4895 */
#define SCTP_RANDOM 0x8002
#define SCTP_CHUNK_LIST 0x8003

View File

@ -193,9 +193,9 @@ struct sctp_init {
#define SCTP_IDENTIFICATION_SIZE 16
#define SCTP_ADDRESS_SIZE 4
#if defined(__Userspace__)
#define SCTP_RESERVE_SPACE 5
#define SCTP_RESERVE_SPACE 4
#else
#define SCTP_RESERVE_SPACE 6
#define SCTP_RESERVE_SPACE 5
#endif
/* state cookie header */
struct sctp_state_cookie { /* this is our definition... */
@ -226,6 +226,7 @@ struct sctp_state_cookie { /* this is our definition... */
uint8_t ipv4_scope; /* IPv4 private addr scope */
uint8_t loopback_scope; /* loopback scope information */
uint8_t zero_checksum; /* copy of the inp value */
uint8_t reserved[SCTP_RESERVE_SPACE]; /* Align to 64 bits */
/*
* at the end is tacked on the INIT chunk and the INIT-ACK chunk

View File

@ -534,8 +534,6 @@ sctp_process_init_ack(struct mbuf *m, int iphlen, int offset,
SCTP_FROM_SCTP_INPUT,
__LINE__);
}
stcb->asoc.overall_error_count = 0;
net->error_count = 0;
/*
* Cancel the INIT timer, We do this first before queueing the
@ -547,8 +545,12 @@ sctp_process_init_ack(struct mbuf *m, int iphlen, int offset,
asoc->primary_destination, SCTP_FROM_SCTP_INPUT + SCTP_LOC_3);
/* calculate the RTO */
sctp_calculate_rto(stcb, asoc, net, &asoc->time_entered,
SCTP_RTT_FROM_NON_DATA);
if (asoc->overall_error_count == 0) {
sctp_calculate_rto(stcb, asoc, net, &asoc->time_entered,
SCTP_RTT_FROM_NON_DATA);
}
stcb->asoc.overall_error_count = 0;
net->error_count = 0;
#if defined(__Userspace__)
if (stcb->sctp_ep->recv_callback) {
if (stcb->sctp_socket) {
@ -1498,7 +1500,6 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
struct sctp_queued_to_read *sq, *nsq;
struct sctp_nets *net;
struct mbuf *op_err;
struct timeval old;
int init_offset, initack_offset, i;
int retval;
int spec_flag = 0;
@ -1669,16 +1670,7 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
}
/* notify upper layer */
*notification = SCTP_NOTIFY_ASSOC_UP;
/*
* since we did not send a HB make sure we
* don't double things
*/
old.tv_sec = cookie->time_entered.tv_sec;
old.tv_usec = cookie->time_entered.tv_usec;
net->hb_responded = 1;
sctp_calculate_rto(stcb, asoc, net, &old,
SCTP_RTT_FROM_NON_DATA);
if (stcb->asoc.sctp_autoclose_ticks &&
(sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTOCLOSE))) {
sctp_timer_start(SCTP_TIMER_TYPE_AUTOCLOSE,
@ -2081,6 +2073,7 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
}
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_asconf_ack), aack);
}
asoc->zero_checksum = cookie->zero_checksum;
/* process the INIT-ACK info (my info) */
asoc->my_vtag = ntohl(initack_cp->init.initiate_tag);
@ -2317,6 +2310,7 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset,
#endif
return (NULL);
}
asoc->zero_checksum = cookie->zero_checksum;
/* process the INIT-ACK info (my info) */
asoc->my_rwnd = ntohl(initack_cp->init.a_rwnd);
@ -2512,17 +2506,11 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset,
(void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
*netp = sctp_findnet(stcb, init_src);
if (*netp != NULL) {
struct timeval old;
/*
* Since we did not send a HB, make sure we don't double
* things.
*/
(*netp)->hb_responded = 1;
/* Calculate the RTT. */
old.tv_sec = cookie->time_entered.tv_sec;
old.tv_usec = cookie->time_entered.tv_usec;
sctp_calculate_rto(stcb, asoc, *netp, &old, SCTP_RTT_FROM_NON_DATA);
}
/* respond with a COOKIE-ACK */
sctp_send_cookie_ack(stcb);
@ -3188,7 +3176,6 @@ sctp_handle_cookie_ack(struct sctp_cookie_ack_chunk *cp SCTP_UNUSED,
SCTP_FROM_SCTP_INPUT,
__LINE__);
}
asoc->overall_error_count = 0;
sctp_stop_all_cookie_timers(stcb);
/* process according to association state */
if (SCTP_GET_STATE(stcb) == SCTP_STATE_COOKIE_ECHOED) {
@ -3207,6 +3194,12 @@ sctp_handle_cookie_ack(struct sctp_cookie_ack_chunk *cp SCTP_UNUSED,
sctp_calculate_rto(stcb, asoc, net, &asoc->time_entered,
SCTP_RTT_FROM_NON_DATA);
}
/*
* Since we did not send a HB make sure we don't double
* things.
*/
asoc->overall_error_count = 0;
net->hb_responded = 1;
(void)SCTP_GETTIME_TIMEVAL(&asoc->time_entered);
sctp_ulp_notify(SCTP_NOTIFY_ASSOC_UP, stcb, 0, NULL, SCTP_SO_NOT_LOCKED);
if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
@ -3231,11 +3224,6 @@ sctp_handle_cookie_ack(struct sctp_cookie_ack_chunk *cp SCTP_UNUSED,
SCTP_SOCKET_UNLOCK(so, 1);
#endif
}
/*
* since we did not send a HB make sure we don't double
* things
*/
net->hb_responded = 1;
if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) {
/* We don't need to do the asconf thing,
@ -5746,78 +5734,136 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt
#endif
uint32_t vrf_id, uint16_t port)
{
uint32_t high_tsn;
int fwd_tsn_seen = 0, data_processed = 0;
struct mbuf *m = *mm, *op_err;
char msg[SCTP_DIAG_INFO_LEN];
int un_sent;
int cnt_ctrl_ready = 0;
struct mbuf *m = *mm, *op_err;
struct sctp_inpcb *inp = NULL, *inp_decr = NULL;
struct sctp_tcb *stcb = NULL;
struct sctp_nets *net = NULL;
#if defined(__Userspace__)
struct socket *upcall_socket = NULL;
#endif
uint32_t high_tsn;
uint32_t cksum_in_hdr;
int un_sent;
int cnt_ctrl_ready = 0;
int fwd_tsn_seen = 0, data_processed = 0;
bool cksum_validated, stcb_looked_up;
SCTP_STAT_INCR(sctps_recvdatagrams);
#ifdef SCTP_AUDITING_ENABLED
sctp_audit_log(0xE0, 1);
sctp_auditing(0, inp, stcb, net);
#endif
if (compute_crc != 0) {
uint32_t check, calc_check;
check = sh->checksum;
sh->checksum = 0;
calc_check = sctp_calculate_cksum(m, iphlen);
sh->checksum = check;
if (calc_check != check) {
SCTPDBG(SCTP_DEBUG_INPUT1, "Bad CSUM on SCTP packet calc_check:%x check:%x m:%p mlen:%d iphlen:%d\n",
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 ((ch->chunk_type != SCTP_INITIATION) &&
(net != NULL) && (net->port != port)) {
if (net->port == 0) {
/* UDP encapsulation turned on. */
net->mtu -= sizeof(struct udphdr);
if (stcb->asoc.smallest_mtu > net->mtu) {
sctp_pathmtu_adjustment(stcb, net->mtu, true);
stcb_looked_up = false;
if (compute_crc != 0) {
cksum_validated = false;
cksum_in_hdr = sh->checksum;
if (cksum_in_hdr != htonl(0)) {
uint32_t cksum_calculated;
validate_cksum:
sh->checksum = 0;
cksum_calculated = sctp_calculate_cksum(m, iphlen);
sh->checksum = cksum_in_hdr;
if (cksum_calculated != cksum_in_hdr) {
if (stcb_looked_up) {
/*
* The packet has a zero checksum, which
* is not the correct CRC, no stcb has
* been found or an stcb has been found
* but an incorrect zero checksum is not
* acceptable.
*/
KASSERT(cksum_in_hdr == htonl(0),
("cksum in header not zero: %x",
ntohl(cksum_in_hdr)));
if ((inp == NULL) &&
(SCTP_BASE_SYSCTL(sctp_ootb_with_zero_cksum) == 1)) {
/*
* This is an OOTB packet,
* depending on the sysctl
* variable, pretend that the
* checksum is acceptable,
* to allow an appropriate
* response (ABORT, for examlpe)
* to be sent.
*/
KASSERT(stcb == NULL,
("stcb is %p", stcb));
SCTP_STAT_INCR(sctps_recvzerocrc);
goto cksum_validated;
}
} else if (port == 0) {
/* UDP encapsulation turned off. */
net->mtu += sizeof(struct udphdr);
/* XXX Update smallest_mtu */
} else {
stcb = sctp_findassociation_addr(m, offset, src, dst,
sh, ch, &inp, &net, vrf_id);
}
SCTPDBG(SCTP_DEBUG_INPUT1, "Bad cksum in SCTP packet:%x calculated:%x m:%p mlen:%d iphlen:%d\n",
ntohl(cksum_in_hdr), ntohl(cksum_calculated), (void *)m, length, iphlen);
#if defined(INET) || defined(INET6)
if ((ch->chunk_type != SCTP_INITIATION) &&
(net != NULL) && (net->port != port)) {
if (net->port == 0) {
/* UDP encapsulation turned on. */
net->mtu -= sizeof(struct udphdr);
if (stcb->asoc.smallest_mtu > net->mtu) {
sctp_pathmtu_adjustment(stcb, net->mtu, true);
}
} else if (port == 0) {
/* UDP encapsulation turned off. */
net->mtu += sizeof(struct udphdr);
/* XXX Update smallest_mtu */
}
net->port = port;
}
net->port = port;
}
#endif
#if defined(__FreeBSD__) && !defined(__Userspace__)
if (net != NULL) {
net->flowtype = mflowtype;
net->flowid = mflowid;
}
SCTP_PROBE5(receive, NULL, stcb, m, stcb, sh);
if (net != NULL) {
net->flowtype = mflowtype;
net->flowid = mflowid;
}
SCTP_PROBE5(receive, NULL, stcb, m, stcb, sh);
#endif
if ((inp != NULL) && (stcb != NULL)) {
sctp_send_packet_dropped(stcb, net, m, length, iphlen, 1);
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_INPUT_ERROR, SCTP_SO_NOT_LOCKED);
} else if ((inp != NULL) && (stcb == NULL)) {
inp_decr = inp;
if ((inp != NULL) && (stcb != NULL)) {
if (stcb->asoc.pktdrop_supported) {
sctp_send_packet_dropped(stcb, net, m, length, iphlen, 1);
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_INPUT_ERROR, SCTP_SO_NOT_LOCKED);
}
} else if ((inp != NULL) && (stcb == NULL)) {
inp_decr = inp;
}
SCTP_STAT_INCR(sctps_badsum);
SCTP_STAT_INCR_COUNTER32(sctps_checksumerrors);
goto out;
} else {
cksum_validated = true;
}
SCTP_STAT_INCR(sctps_badsum);
SCTP_STAT_INCR_COUNTER32(sctps_checksumerrors);
goto out;
}
KASSERT(cksum_validated || cksum_in_hdr == htonl(0),
("cksum 0x%08x not zero and not validated", ntohl(cksum_in_hdr)));
if (!cksum_validated) {
stcb = sctp_findassociation_addr(m, offset, src, dst,
sh, ch, &inp, &net, vrf_id);
stcb_looked_up = true;
if ((stcb == NULL) || (stcb->asoc.zero_checksum == 0)) {
goto validate_cksum;
}
SCTP_STAT_INCR(sctps_recvzerocrc);
}
}
cksum_validated:
/* Destination port of 0 is illegal, based on RFC4960. */
if (sh->dest_port == 0) {
if (sh->dest_port == htons(0)) {
SCTP_STAT_INCR(sctps_hdrops);
if ((stcb == NULL) && (inp != NULL)) {
inp_decr = inp;
}
goto out;
}
stcb = sctp_findassociation_addr(m, offset, src, dst,
sh, ch, &inp, &net, vrf_id);
if (!stcb_looked_up) {
stcb = sctp_findassociation_addr(m, offset, src, dst,
sh, ch, &inp, &net, vrf_id);
}
#if defined(INET) || defined(INET6)
if ((ch->chunk_type != SCTP_INITIATION) &&
(net != NULL) && (net->port != port)) {
@ -5842,11 +5888,9 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt
}
#endif
if (inp == NULL) {
#if defined(__FreeBSD__) && !defined(__Userspace__)
SCTP_PROBE5(receive, NULL, stcb, m, stcb, sh);
#endif
SCTP_STAT_INCR(sctps_noport);
#if defined(__FreeBSD__) && !defined(__Userspace__)
SCTP_PROBE5(receive, NULL, stcb, m, stcb, sh);
if (badport_bandlim(BANDLIM_SCTP_OOTB) < 0) {
goto out;
}

View File

@ -4090,7 +4090,8 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
#if defined(__FreeBSD__) && !defined(__Userspace__)
uint8_t mflowtype, uint32_t mflowid,
#endif
int so_locked)
bool use_zero_crc,
int so_locked)
/* nofragment_flag to tell if IP_DF should be set (IPv4 only) */
{
/**
@ -4390,8 +4391,12 @@ int so_locked)
}
SCTP_ATTACH_CHAIN(o_pak, m, packet_length);
if (port) {
sctphdr->checksum = sctp_calculate_cksum(m, sizeof(struct ip) + sizeof(struct udphdr));
SCTP_STAT_INCR(sctps_sendswcrc);
if (use_zero_crc) {
SCTP_STAT_INCR(sctps_sendzerocrc);
} else {
sctphdr->checksum = sctp_calculate_cksum(m, sizeof(struct ip) + sizeof(struct udphdr));
SCTP_STAT_INCR(sctps_sendswcrc);
}
#if !defined(__Userspace__)
#if defined(__FreeBSD__)
if (V_udp_cksum) {
@ -4402,19 +4407,23 @@ int so_locked)
#endif
#endif
} else {
#if defined(__FreeBSD__) && !defined(__Userspace__)
m->m_pkthdr.csum_flags = CSUM_SCTP;
m->m_pkthdr.csum_data = offsetof(struct sctphdr, checksum);
SCTP_STAT_INCR(sctps_sendhwcrc);
#else
if (!(SCTP_BASE_SYSCTL(sctp_no_csum_on_loopback) &&
(stcb) && (stcb->asoc.scope.loopback_scope))) {
sctphdr->checksum = sctp_calculate_cksum(m, sizeof(struct ip));
SCTP_STAT_INCR(sctps_sendswcrc);
if (use_zero_crc) {
SCTP_STAT_INCR(sctps_sendzerocrc);
} else {
#if defined(__FreeBSD__) && !defined(__Userspace__)
m->m_pkthdr.csum_flags = CSUM_SCTP;
m->m_pkthdr.csum_data = offsetof(struct sctphdr, checksum);
SCTP_STAT_INCR(sctps_sendhwcrc);
}
#else
if (!(SCTP_BASE_SYSCTL(sctp_no_csum_on_loopback) &&
(stcb) && (stcb->asoc.scope.loopback_scope))) {
sctphdr->checksum = sctp_calculate_cksum(m, sizeof(struct ip));
SCTP_STAT_INCR(sctps_sendswcrc);
} else {
SCTP_STAT_INCR(sctps_sendhwcrc);
}
#endif
}
}
#ifdef SCTP_PACKET_LOGGING
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LAST_PACKET_TRACING)
@ -5160,6 +5169,15 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int so_locked)
chunk_len += parameter_len;
}
/* Zero checksum acceptable parameter */
if (stcb->asoc.zero_checksum > 0) {
parameter_len = (uint16_t)sizeof(struct sctp_paramhdr);
ph = (struct sctp_paramhdr *)(mtod(m, caddr_t) + chunk_len);
ph->param_type = htons(SCTP_ZERO_CHECKSUM_ACCEPTABLE);
ph->param_length = htons(parameter_len);
chunk_len += parameter_len;
}
/* Add NAT friendly parameter. */
if (SCTP_BASE_SYSCTL(sctp_inits_include_nat_friendly)) {
parameter_len = (uint16_t)sizeof(struct sctp_paramhdr);
@ -5335,7 +5353,7 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int so_locked)
#if defined(__FreeBSD__) && !defined(__Userspace__)
0, 0,
#endif
so_locked))) {
false, so_locked))) {
SCTPDBG(SCTP_DEBUG_OUTPUT4, "Gak send error %d\n", error);
if (error == ENOBUFS) {
stcb->asoc.ifp_had_enobuf = 1;
@ -6331,6 +6349,11 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
#endif
}
}
if (asoc != NULL) {
stc.zero_checksum = asoc->zero_checksum > 0 ? 1 : 0;
} else {
stc.zero_checksum = inp->zero_checksum;
}
/* Now lets put the SCTP header in place */
initack = mtod(m, struct sctp_init_ack_chunk *);
/* Save it off for quick ref */
@ -6453,6 +6476,16 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
chunk_len += parameter_len;
}
/* Zero checksum acceptable parameter */
if (((asoc != NULL) && (asoc->zero_checksum > 0)) ||
((asoc == NULL) && (inp->zero_checksum == 1))) {
parameter_len = (uint16_t)sizeof(struct sctp_paramhdr);
ph = (struct sctp_paramhdr *)(mtod(m, caddr_t) + chunk_len);
ph->param_type = htons(SCTP_ZERO_CHECKSUM_ACCEPTABLE);
ph->param_length = htons(parameter_len);
chunk_len += parameter_len;
}
/* Add NAT friendly parameter */
if (nat_friendly) {
parameter_len = (uint16_t)sizeof(struct sctp_paramhdr);
@ -6685,6 +6718,7 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
#if defined(__FreeBSD__) && !defined(__Userspace__)
mflowtype, mflowid,
#endif
false, /* XXXMT: Improve this! */
SCTP_SO_NOT_LOCKED))) {
SCTPDBG(SCTP_DEBUG_OUTPUT4, "Gak send error %d\n", error);
if (error == ENOBUFS) {
@ -8370,6 +8404,7 @@ sctp_med_chunk_output(struct sctp_inpcb *inp,
/* JRS 5/14/07 - Add flag for whether a heartbeat is sent to
the destination. */
int quit_now = 0;
bool use_zero_crc;
#if defined(__APPLE__) && !defined(__Userspace__)
if (so_locked) {
@ -8746,7 +8781,7 @@ again_one_more_time:
#if defined(__FreeBSD__) && !defined(__Userspace__)
0, 0,
#endif
so_locked))) {
false, so_locked))) {
/* error, we could not output */
SCTPDBG(SCTP_DEBUG_OUTPUT3, "Gak send error %d\n", error);
if (from_where == 0) {
@ -8765,6 +8800,7 @@ again_one_more_time:
*/
sctp_move_chunks_from_net(stcb, net);
}
asconf = 0;
*reason_code = 7;
break;
} else {
@ -8778,6 +8814,7 @@ again_one_more_time:
outchain = endoutchain = NULL;
auth = NULL;
auth_offset = 0;
asconf = 0;
if (!no_out_cnt)
*num_out += ctl_cnt;
/* recalc a clean slate and setup */
@ -8983,8 +9020,10 @@ again_one_more_time:
* flight size since this little guy
* is a control only packet.
*/
use_zero_crc = asoc->zero_checksum == 2;
if (asconf) {
sctp_timer_start(SCTP_TIMER_TYPE_ASCONF, inp, stcb, net);
use_zero_crc = false;
/*
* do NOT clear the asconf
* flag as it is used to do
@ -8994,6 +9033,7 @@ again_one_more_time:
}
if (cookie) {
sctp_timer_start(SCTP_TIMER_TYPE_COOKIE, inp, stcb, net);
use_zero_crc = false;
cookie = 0;
}
/* Only HB or ASCONF advances time */
@ -9017,7 +9057,7 @@ again_one_more_time:
#if defined(__FreeBSD__) && !defined(__Userspace__)
0, 0,
#endif
so_locked))) {
use_zero_crc, so_locked))) {
/* error, we could not output */
SCTPDBG(SCTP_DEBUG_OUTPUT3, "Gak send error %d\n", error);
if (from_where == 0) {
@ -9035,6 +9075,7 @@ again_one_more_time:
*/
sctp_move_chunks_from_net(stcb, net);
}
asconf = 0;
*reason_code = 7;
break;
} else {
@ -9048,6 +9089,7 @@ again_one_more_time:
outchain = endoutchain = NULL;
auth = NULL;
auth_offset = 0;
asconf = 0;
if (!no_out_cnt)
*num_out += ctl_cnt;
/* recalc a clean slate and setup */
@ -9313,9 +9355,11 @@ again_one_more_time:
/* Is there something to send for this destination? */
if (outchain) {
/* We may need to start a control timer or two */
use_zero_crc = asoc->zero_checksum == 2;
if (asconf) {
sctp_timer_start(SCTP_TIMER_TYPE_ASCONF, inp,
stcb, net);
use_zero_crc = false;
/*
* do NOT clear the asconf flag as it is used
* to do appropriate source address selection.
@ -9323,6 +9367,7 @@ again_one_more_time:
}
if (cookie) {
sctp_timer_start(SCTP_TIMER_TYPE_COOKIE, inp, stcb, net);
use_zero_crc = false;
cookie = 0;
}
/* must start a send timer if data is being sent */
@ -9359,6 +9404,7 @@ again_one_more_time:
#if defined(__FreeBSD__) && !defined(__Userspace__)
0, 0,
#endif
use_zero_crc,
so_locked))) {
/* error, we could not output */
SCTPDBG(SCTP_DEBUG_OUTPUT3, "Gak send error %d\n", error);
@ -9376,6 +9422,7 @@ again_one_more_time:
*/
sctp_move_chunks_from_net(stcb, net);
}
asconf = 0;
*reason_code = 6;
/*-
* I add this line to be paranoid. As far as
@ -9391,6 +9438,7 @@ again_one_more_time:
endoutchain = NULL;
auth = NULL;
auth_offset = 0;
asconf = 0;
if (!no_out_cnt) {
*num_out += (ctl_cnt + bundle_at);
}
@ -9979,6 +10027,7 @@ sctp_chunk_retransmission(struct sctp_inpcb *inp,
int override_ok = 1;
int data_auth_reqd = 0;
uint32_t dmtu = 0;
bool use_zero_crc;
#if defined(__APPLE__) && !defined(__Userspace__)
if (so_locked) {
@ -10049,10 +10098,15 @@ sctp_chunk_retransmission(struct sctp_inpcb *inp,
/* do we have control chunks to retransmit? */
if (m != NULL) {
/* Start a timer no matter if we succeed or fail */
use_zero_crc = asoc->zero_checksum == 2;
if (chk->rec.chunk_id.id == SCTP_COOKIE_ECHO) {
sctp_timer_start(SCTP_TIMER_TYPE_COOKIE, inp, stcb, chk->whoTo);
} else if (chk->rec.chunk_id.id == SCTP_ASCONF)
use_zero_crc = false;
} else if (chk->rec.chunk_id.id == SCTP_ASCONF) {
/* XXXMT: Can this happen? */
sctp_timer_start(SCTP_TIMER_TYPE_ASCONF, inp, stcb, chk->whoTo);
use_zero_crc = false;
}
chk->snd_count++; /* update our count */
if ((error = sctp_lowlevel_chunk_output(inp, stcb, chk->whoTo,
(struct sockaddr *)&chk->whoTo->ro._l_addr, m,
@ -10063,6 +10117,7 @@ sctp_chunk_retransmission(struct sctp_inpcb *inp,
#if defined(__FreeBSD__) && !defined(__Userspace__)
0, 0,
#endif
use_zero_crc,
so_locked))) {
SCTPDBG(SCTP_DEBUG_OUTPUT3, "Gak send error %d\n", error);
if (error == ENOBUFS) {
@ -10344,6 +10399,7 @@ sctp_chunk_retransmission(struct sctp_inpcb *inp,
#if defined(__FreeBSD__) && !defined(__Userspace__)
0, 0,
#endif
asoc->zero_checksum == 2,
so_locked))) {
/* error, we could not output */
SCTPDBG(SCTP_DEBUG_OUTPUT3, "Gak send error %d\n", error);
@ -11524,6 +11580,7 @@ sctp_send_abort_tcb(struct sctp_tcb *stcb, struct mbuf *operr, int so_locked)
#if defined(__FreeBSD__) && !defined(__Userspace__)
0, 0,
#endif
stcb->asoc.zero_checksum == 2,
so_locked))) {
SCTPDBG(SCTP_DEBUG_OUTPUT3, "Gak send error %d\n", error);
if (error == ENOBUFS) {
@ -11574,6 +11631,7 @@ sctp_send_shutdown_complete(struct sctp_tcb *stcb,
#if defined(__FreeBSD__) && !defined(__Userspace__)
0, 0,
#endif
stcb->asoc.zero_checksum == 2,
SCTP_SO_NOT_LOCKED))) {
SCTPDBG(SCTP_DEBUG_OUTPUT3, "Gak send error %d\n", error);
if (error == ENOBUFS) {

View File

@ -2797,6 +2797,7 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id)
inp->nrsack_supported = (uint8_t)SCTP_BASE_SYSCTL(sctp_nrsack_enable);
inp->pktdrop_supported = (uint8_t)SCTP_BASE_SYSCTL(sctp_pktdrop_enable);
inp->idata_supported = 0;
inp->zero_checksum = 0;
#if defined(__FreeBSD__) && !defined(__Userspace__)
inp->fibnum = so->so_fibnum;
@ -7411,6 +7412,14 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
} else if (ptype == SCTP_PRSCTP_SUPPORTED) {
/* Peer supports pr-sctp */
peer_supports_prsctp = 1;
} else if (ptype == SCTP_ZERO_CHECKSUM_ACCEPTABLE) {
/*
* Only send zero checksums if the upper layer has
* also enabled the support for this.
*/
if (stcb->asoc.zero_checksum == 1) {
stcb->asoc.zero_checksum = 2;
}
} else if (ptype == SCTP_SUPPORTED_CHUNK_EXT) {
/* A supported extension chunk */
struct sctp_supported_chunk_types_param *pr_supported;
@ -7949,16 +7958,18 @@ sctp_drain_mbufs(struct sctp_tcb *stcb)
*/
}
#if defined(__FreeBSD__) && !defined(__Userspace__)
static void
#else
void
#endif
sctp_drain(void)
{
/*
* We must walk the PCB lists for ALL associations here. The system
* is LOW on MBUF's and needs help. This is where reneging will
* occur. We really hope this does NOT happen!
*/
#if defined(__FreeBSD__) && !defined(__Userspace__)
struct epoch_tracker et;
VNET_ITERATOR_DECL(vnet_iter);
NET_EPOCH_ENTER(et);
#else
struct sctp_inpcb *inp;
struct sctp_tcb *stcb;
@ -7968,6 +7979,11 @@ sctp_drain(void)
return;
}
#endif
/*
* We must walk the PCB lists for ALL associations here. The system
* is LOW on MBUF's and needs help. This is where reneging will
* occur. We really hope this does NOT happen!
*/
#if defined(__FreeBSD__) && !defined(__Userspace__)
VNET_LIST_RLOCK_NOSLEEP();
VNET_FOREACH(vnet_iter) {
@ -7982,6 +7998,7 @@ sctp_drain(void)
#ifdef VIMAGE
continue;
#else
NET_EPOCH_EXIT(et);
return;
#endif
}
@ -8003,8 +8020,13 @@ sctp_drain(void)
CURVNET_RESTORE();
}
VNET_LIST_RUNLOCK_NOSLEEP();
NET_EPOCH_EXIT(et);
#endif
}
#if defined(__FreeBSD__) && !defined(__Userspace__)
EVENTHANDLER_DEFINE(vm_lowmem, sctp_drain, NULL, LOWMEM_PRI_DEFAULT);
EVENTHANDLER_DEFINE(mbuf_lowmem, sctp_drain, NULL, LOWMEM_PRI_DEFAULT);
#endif
/*
* start a new iterator

View File

@ -496,6 +496,7 @@ struct sctp_inpcb {
uint8_t reconfig_supported;
uint8_t nrsack_supported;
uint8_t pktdrop_supported;
uint8_t zero_checksum;
struct sctp_nonpad_sndrcvinfo def_send;
/*-
* These three are here for the sosend_dgram
@ -845,8 +846,6 @@ sctp_set_primary_addr(struct sctp_tcb *, struct sockaddr *,
bool
sctp_is_vtag_good(uint32_t, uint16_t lport, uint16_t rport, struct timeval *);
/* void sctp_drain(void); */
int sctp_destination_is_reachable(struct sctp_tcb *, struct sockaddr *);
int sctp_swap_inpcb_for_listen(struct sctp_inpcb *inp);

View File

@ -1234,6 +1234,13 @@ struct sctp_association {
uint8_t pktdrop_supported;
uint8_t idata_supported;
/* Zero checksum supported information:
* 0: disabled
* 1: enabled for rcv
* 2: enabled for snd/rcv
*/
uint8_t zero_checksum;
/* Did the peer make the stream config (add out) request */
uint8_t peer_req_out;

View File

@ -151,6 +151,7 @@ sctp_init_sysctls(void)
SCTP_BASE_SYSCTL(sctp_blackhole) = SCTPCTL_BLACKHOLE_DEFAULT;
SCTP_BASE_SYSCTL(sctp_sendall_limit) = SCTPCTL_SENDALL_LIMIT_DEFAULT;
SCTP_BASE_SYSCTL(sctp_diag_info_code) = SCTPCTL_DIAG_INFO_CODE_DEFAULT;
SCTP_BASE_SYSCTL(sctp_ootb_with_zero_cksum) = SCTPCTL_OOTB_WITH_ZERO_CKSUM_DEFAULT;
#if defined(SCTP_LOCAL_TRACE_BUF)
#if defined(_WIN32) && !defined(__Userspace__)
/* On Windows, the resource for global variables is limited. */
@ -1033,6 +1034,9 @@ sctp_sysctl_handle_stats(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;
sb.sctps_queue_upd_ecne += sarry->sctps_queue_upd_ecne;
sb.sctps_recvzerocrc += sarry->sctps_recvzerocrc;
sb.sctps_sendzerocrc += sarry->sctps_sendzerocrc;
if (req->newptr != NULL) {
memcpy(sarry, &sb_temp, sizeof(struct sctpstat));
}
@ -1242,6 +1246,7 @@ SCTP_UINT_SYSCTL(use_dcccecn, sctp_use_dccc_ecn, SCTPCTL_RTTVAR_DCCCECN)
SCTP_UINT_SYSCTL(blackhole, sctp_blackhole, SCTPCTL_BLACKHOLE)
SCTP_UINT_SYSCTL(sendall_limit, sctp_sendall_limit, SCTPCTL_SENDALL_LIMIT)
SCTP_UINT_SYSCTL(diag_info_code, sctp_diag_info_code, SCTPCTL_DIAG_INFO_CODE)
SCTP_UINT_SYSCTL(ootb_with_zero_cksum, sctp_ootb_with_zero_cksum, SCTPCTL_OOTB_WITH_ZERO_CKSUM)
#ifdef SCTP_DEBUG
SCTP_UINT_SYSCTL(debug, sctp_debug_on, SCTPCTL_DEBUG)
#endif
@ -1341,6 +1346,7 @@ sctp_sysctl_handle_int(SYSCTL_HANDLER_ARGS)
RANGECHK(SCTP_BASE_SYSCTL(sctp_blackhole), SCTPCTL_BLACKHOLE_MIN, SCTPCTL_BLACKHOLE_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_sendall_limit), SCTPCTL_SENDALL_LIMIT_MIN, SCTPCTL_SENDALL_LIMIT_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_diag_info_code), SCTPCTL_DIAG_INFO_CODE_MIN, SCTPCTL_DIAG_INFO_CODE_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_ootb_with_zero_cksum), SCTPCTL_OOTB_WITH_ZERO_CKSUM_MIN, SCTPCTL_OOTB_WITH_ZERO_CKSUM_MAX);
#ifdef SCTP_DEBUG
RANGECHK(SCTP_BASE_SYSCTL(sctp_debug_on), SCTPCTL_DEBUG_MIN, SCTPCTL_DEBUG_MAX);
#endif
@ -1641,6 +1647,10 @@ sysctl_setup_sctp(void)
&SCTP_BASE_SYSCTL(sctp_diag_info_code), 0, sctp_sysctl_handle_int,
SCTPCTL_DIAG_INFO_CODE_DESC);
sysctl_add_oid(&sysctl_oid_top, "ootb_with_zero_cksum", CTLTYPE_INT|CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_ootb_with_zero_cksum), 0, sctp_sysctl_handle_int,
SCTPCTL_OOTB_WITH_ZERO_CKSUM_DESC);
#ifdef SCTP_DEBUG
sysctl_add_oid(&sysctl_oid_top, "debug", CTLTYPE_INT|CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_debug_on), 0, sctp_sysctl_handle_int,

View File

@ -111,7 +111,6 @@ struct sctp_sysctl {
uint32_t sctp_rttvar_eqret;
uint32_t sctp_steady_step;
uint32_t sctp_use_dccc_ecn;
uint32_t sctp_diag_info_code;
#if defined(SCTP_LOCAL_TRACE_BUF)
#if defined(_WIN32) && !defined(__Userspace__)
struct sctp_log *sctp_log;
@ -126,6 +125,8 @@ struct sctp_sysctl {
uint32_t sctp_initial_cwnd;
uint32_t sctp_blackhole;
uint32_t sctp_sendall_limit;
uint32_t sctp_diag_info_code;
uint32_t sctp_ootb_with_zero_cksum;
#if defined(SCTP_DEBUG)
uint32_t sctp_debug_on;
#endif
@ -576,6 +577,11 @@ struct sctp_sysctl {
#define SCTPCTL_DIAG_INFO_CODE_MAX 65535
#define SCTPCTL_DIAG_INFO_CODE_DEFAULT 0
#define SCTPCTL_OOTB_WITH_ZERO_CKSUM_DESC "Accept OOTB packets with zero checksum"
#define SCTPCTL_OOTB_WITH_ZERO_CKSUM_MIN 0
#define SCTPCTL_OOTB_WITH_ZERO_CKSUM_MAX 1
#define SCTPCTL_OOTB_WITH_ZERO_CKSUM_DEFAULT 0
#if defined(SCTP_DEBUG)
/* debug: Configure debug output */
#define SCTPCTL_DEBUG_DESC "Configure debug output"

View File

@ -1104,8 +1104,10 @@ struct sctpstat {
uint32_t sctps_send_burst_avoid; /* Unused */
uint32_t sctps_send_cwnd_avoid; /* Send cwnd full avoidance, already max burst inflight to net */
uint32_t sctps_fwdtsn_map_over; /* number of map array over-runs via fwd-tsn's */
uint32_t sctps_queue_upd_ecne; /* Number of times we queued or updated an ECN chunk on send queue */
uint32_t sctps_reserved[31]; /* Future ABI compat - remove int's from here when adding new */
uint32_t sctps_queue_upd_ecne; /* Number of times we queued or updated an ECN chunk on send queue */
uint32_t sctps_recvzerocrc; /* Number of accepted packets with zero CRC */
uint32_t sctps_sendzerocrc; /* Number of packets sent with zero CRC */
uint32_t sctps_reserved[29]; /* Future ABI compat - remove int's from here when adding new */
};
#define SCTP_STAT_INCR(_x) SCTP_STAT_INCR_BY(_x,1)

View File

@ -389,6 +389,96 @@ sctp_notify(struct sctp_inpcb *inp,
#endif
#if !defined(__Userspace__)
#if defined(__FreeBSD__)
void sctp_ctlinput(struct icmp *icmp)
{
struct ip *inner_ip, *outer_ip;
struct sctphdr *sh;
struct sctp_inpcb *inp;
struct sctp_tcb *stcb;
struct sctp_nets *net;
struct sctp_init_chunk *ch;
struct sockaddr_in src, dst;
if (icmp_errmap(icmp) == 0)
return;
outer_ip = (struct ip *)((caddr_t)icmp - sizeof(struct ip));
inner_ip = &icmp->icmp_ip;
sh = (struct sctphdr *)((caddr_t)inner_ip + (inner_ip->ip_hl << 2));
memset(&src, 0, sizeof(struct sockaddr_in));
src.sin_family = AF_INET;
src.sin_len = sizeof(struct sockaddr_in);
src.sin_port = sh->src_port;
src.sin_addr = inner_ip->ip_src;
memset(&dst, 0, sizeof(struct sockaddr_in));
dst.sin_family = AF_INET;
dst.sin_len = sizeof(struct sockaddr_in);
dst.sin_port = sh->dest_port;
dst.sin_addr = inner_ip->ip_dst;
/*
* 'dst' holds the dest of the packet that failed to be sent.
* 'src' holds our local endpoint address. Thus we reverse
* the dst and the src in the lookup.
*/
inp = NULL;
net = NULL;
stcb = sctp_findassociation_addr_sa((struct sockaddr *)&dst,
(struct sockaddr *)&src,
&inp, &net, 1,
SCTP_DEFAULT_VRFID);
if ((stcb != NULL) &&
(net != NULL) &&
(inp != NULL)) {
/* Check the verification tag */
if (ntohl(sh->v_tag) != 0) {
/*
* This must be the verification tag used for
* sending out packets. We don't consider
* packets reflecting the verification tag.
*/
if (ntohl(sh->v_tag) != stcb->asoc.peer_vtag) {
SCTP_TCB_UNLOCK(stcb);
return;
}
} else {
if (ntohs(outer_ip->ip_len) >=
sizeof(struct ip) +
8 + (inner_ip->ip_hl << 2) + 20) {
/*
* In this case we can check if we
* got an INIT chunk and if the
* initiate tag matches.
*/
ch = (struct sctp_init_chunk *)(sh + 1);
if ((ch->ch.chunk_type != SCTP_INITIATION) ||
(ntohl(ch->init.initiate_tag) != stcb->asoc.my_vtag)) {
SCTP_TCB_UNLOCK(stcb);
return;
}
} else {
SCTP_TCB_UNLOCK(stcb);
return;
}
}
sctp_notify(inp, stcb, net,
icmp->icmp_type,
icmp->icmp_code,
ntohs(inner_ip->ip_len),
(uint32_t)ntohs(icmp->icmp_nextmtu));
} else {
if ((stcb == NULL) && (inp != NULL)) {
/* reduce ref-count */
SCTP_INP_WLOCK(inp);
SCTP_INP_DECR_REF(inp);
SCTP_INP_WUNLOCK(inp);
}
if (stcb) {
SCTP_TCB_UNLOCK(stcb);
}
}
}
#else
void
#if defined(__APPLE__) && !defined(APPLE_LEOPARD) && !defined(APPLE_SNOWLEOPARD) && !defined(APPLE_LION) && !defined(APPLE_MOUNTAINLION) && !defined(APPLE_ELCAPITAN)
sctp_ctlinput(int cmd, struct sockaddr *sa, void *vip, struct ifnet *ifp SCTP_UNUSED)
@ -396,24 +486,20 @@ sctp_ctlinput(int cmd, struct sockaddr *sa, void *vip, struct ifnet *ifp SCTP_UN
sctp_ctlinput(int cmd, struct sockaddr *sa, void *vip)
#endif
{
#if defined(__FreeBSD__) && !defined(__Userspace__)
struct ip *outer_ip;
#endif
struct ip *inner_ip;
struct sctphdr *sh;
struct icmp *icmp;
struct sctp_inpcb *inp;
struct sctp_tcb *stcb;
struct sctp_nets *net;
#if defined(__FreeBSD__) && !defined(__Userspace__)
struct sctp_init_chunk *ch;
#endif
struct sockaddr_in src, dst;
#if !defined(__FreeBSD__) && !defined(__Userspace__)
if (sa->sa_family != AF_INET ||
((struct sockaddr_in *)sa)->sin_addr.s_addr == INADDR_ANY) {
return;
}
#endif
if (PRC_IS_REDIRECT(cmd)) {
vip = NULL;
} else if ((unsigned)cmd >= PRC_NCMDS || inetctlerrmap[cmd] == 0) {
@ -423,9 +509,6 @@ sctp_ctlinput(int cmd, struct sockaddr *sa, void *vip)
inner_ip = (struct ip *)vip;
icmp = (struct icmp *)((caddr_t)inner_ip -
(sizeof(struct icmp) - sizeof(struct ip)));
#if defined(__FreeBSD__) && !defined(__Userspace__)
outer_ip = (struct ip *)((caddr_t)icmp - sizeof(struct ip));
#endif
sh = (struct sctphdr *)((caddr_t)inner_ip + (inner_ip->ip_hl << 2));
memset(&src, 0, sizeof(struct sockaddr_in));
src.sin_family = AF_INET;
@ -467,38 +550,13 @@ sctp_ctlinput(int cmd, struct sockaddr *sa, void *vip)
return;
}
} else {
#if defined(__FreeBSD__) && !defined(__Userspace__)
if (ntohs(outer_ip->ip_len) >=
sizeof(struct ip) +
8 + (inner_ip->ip_hl << 2) + 20) {
/*
* In this case we can check if we
* got an INIT chunk and if the
* initiate tag matches.
*/
ch = (struct sctp_init_chunk *)(sh + 1);
if ((ch->ch.chunk_type != SCTP_INITIATION) ||
(ntohl(ch->init.initiate_tag) != stcb->asoc.my_vtag)) {
SCTP_TCB_UNLOCK(stcb);
return;
}
} else {
SCTP_TCB_UNLOCK(stcb);
return;
}
#else
SCTP_TCB_UNLOCK(stcb);
return;
#endif
}
sctp_notify(inp, stcb, net,
icmp->icmp_type,
icmp->icmp_code,
#if defined(__FreeBSD__) && !defined(__Userspace__)
ntohs(inner_ip->ip_len),
#else
inner_ip->ip_len,
#endif
(uint32_t)ntohs(icmp->icmp_nextmtu));
#if defined(__Userspace__)
if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
@ -534,6 +592,7 @@ sctp_ctlinput(int cmd, struct sockaddr *sa, void *vip)
}
#endif
#endif
#endif
#if defined(__FreeBSD__) && !defined(__Userspace__)
static int
@ -7736,6 +7795,21 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
}
break;
}
case SCTP_ACCEPT_ZERO_CHECKSUM:
{
uint32_t *value;
SCTP_CHECK_AND_CAST(value, optval, uint32_t, optsize);
SCTP_INP_WLOCK(inp);
if (*value != 0) {
inp->zero_checksum = 1;
} else {
inp->zero_checksum = 0;
}
SCTP_INP_WUNLOCK(inp);
break;
}
default:
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
error = ENOPROTOOPT;
@ -8809,27 +8883,43 @@ sctp_peeraddr(struct socket *so, struct mbuf *nam)
}
#if !defined(__Userspace__)
struct pr_usrreqs sctp_usrreqs = {
#if defined(__FreeBSD__)
.pru_abort = sctp_abort,
.pru_accept = sctp_accept,
.pru_attach = sctp_attach,
.pru_bind = sctp_bind,
.pru_connect = sctp_connect,
.pru_control = in_control,
.pru_close = sctp_close,
.pru_detach = sctp_close,
.pru_sopoll = sopoll_generic,
.pru_flush = sctp_flush,
.pru_disconnect = sctp_disconnect,
.pru_listen = sctp_listen,
.pru_peeraddr = sctp_peeraddr,
.pru_send = sctp_sendm,
.pru_shutdown = sctp_shutdown,
.pru_sockaddr = sctp_ingetaddr,
.pru_sosend = sctp_sosend,
.pru_soreceive = sctp_soreceive
#elif defined(__APPLE__)
#define SCTP_PROTOSW \
.pr_protocol = IPPROTO_SCTP, \
.pr_ctloutput = sctp_ctloutput, \
.pr_abort = sctp_abort, \
.pr_accept = sctp_accept, \
.pr_attach = sctp_attach, \
.pr_bind = sctp_bind, \
.pr_connect = sctp_connect, \
.pr_control = in_control, \
.pr_close = sctp_close, \
.pr_detach = sctp_close, \
.pr_sopoll = sopoll_generic, \
.pr_flush = sctp_flush, \
.pr_disconnect = sctp_disconnect, \
.pr_listen = sctp_listen, \
.pr_peeraddr = sctp_peeraddr, \
.pr_send = sctp_sendm, \
.pr_shutdown = sctp_shutdown, \
.pr_sockaddr = sctp_ingetaddr, \
.pr_sosend = sctp_sosend, \
.pr_soreceive = sctp_soreceive \
struct protosw sctp_seqpacket_protosw = {
.pr_type = SOCK_SEQPACKET,
.pr_flags = PR_WANTRCVD,
SCTP_PROTOSW
};
struct protosw sctp_stream_protosw = {
.pr_type = SOCK_STREAM,
.pr_flags = PR_CONNREQUIRED | PR_WANTRCVD,
SCTP_PROTOSW
};
#else
struct pr_usrreqs sctp_usrreqs = {
#if defined(__APPLE__)
.pru_abort = sctp_abort,
.pru_accept = sctp_accept,
.pru_attach = sctp_attach,
@ -8876,127 +8966,7 @@ struct pr_usrreqs sctp_usrreqs = {
sctp_close
#endif
};
#elif !defined(__Userspace__)
int
sctp_usrreq(so, req, m, nam, control)
struct socket *so;
int req;
struct mbuf *m, *nam, *control;
{
struct proc *p = curproc;
int error;
int family;
struct sctp_inpcb *inp = (struct sctp_inpcb *)so->so_pcb;
error = 0;
family = so->so_proto->pr_domain->dom_family;
if (req == PRU_CONTROL) {
switch (family) {
case PF_INET:
error = in_control(so, (long)m, (caddr_t)nam,
(struct ifnet *)control);
break;
#ifdef INET6
case PF_INET6:
error = in6_control(so, (long)m, (caddr_t)nam,
(struct ifnet *)control, p);
break;
#endif
default:
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EAFNOSUPPORT);
error = EAFNOSUPPORT;
}
return (error);
}
switch (req) {
case PRU_ATTACH:
error = sctp_attach(so, family, p);
break;
case PRU_DETACH:
error = sctp_detach(so);
break;
case PRU_BIND:
if (nam == NULL) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
return (EINVAL);
}
error = sctp_bind(so, nam, p);
break;
case PRU_LISTEN:
error = sctp_listen(so, p);
break;
case PRU_CONNECT:
if (nam == NULL) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
return (EINVAL);
}
error = sctp_connect(so, nam, p);
break;
case PRU_DISCONNECT:
error = sctp_disconnect(so);
break;
case PRU_ACCEPT:
if (nam == NULL) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
return (EINVAL);
}
error = sctp_accept(so, nam);
break;
case PRU_SHUTDOWN:
error = sctp_shutdown(so);
break;
case PRU_RCVD:
/*
* For Open and Net BSD, this is real ugly. The mbuf *nam
* that is passed (by soreceive()) is the int flags c ast as
* a (mbuf *) yuck!
*/
break;
case PRU_SEND:
/* Flags are ignored */
{
struct sockaddr *addr;
if (nam == NULL)
addr = NULL;
else
addr = mtod(nam, struct sockaddr *);
error = sctp_sendm(so, 0, m, addr, control, p);
}
break;
case PRU_ABORT:
error = sctp_abort(so);
break;
case PRU_SENSE:
error = 0;
break;
case PRU_RCVOOB:
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EAFNOSUPPORT);
error = EAFNOSUPPORT;
break;
case PRU_SENDOOB:
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EAFNOSUPPORT);
error = EAFNOSUPPORT;
break;
case PRU_PEERADDR:
error = sctp_peeraddr(so, nam);
break;
case PRU_SOCKADDR:
error = sctp_ingetaddr(so, nam);
break;
case PRU_SLOWTIMO:
error = 0;
break;
default:
break;
}
return (error);
}
#endif
#endif

View File

@ -45,8 +45,12 @@ __FBSDID("$FreeBSD$");
#if defined(_KERNEL) || defined(__Userspace__)
#if !defined(__Userspace__)
#if defined(__FreeBSD__)
extern struct protosw sctp_seqpacket_protosw, sctp_stream_protosw;
#else
extern struct pr_usrreqs sctp_usrreqs;
#endif
#endif
#define sctp_feature_on(inp, feature) (inp->sctp_features |= feature)
#define sctp_feature_off(inp, feature) (inp->sctp_features &= ~feature)
@ -372,6 +376,8 @@ int sctp_disconnect(struct socket *so);
#if !defined(__Userspace__)
#if defined(__APPLE__) && !defined(APPLE_LEOPARD) && !defined(APPLE_SNOWLEOPARD) && !defined(APPLE_LION) && !defined(APPLE_MOUNTAINLION) && !defined(APPLE_ELCAPITAN)
void sctp_ctlinput(int, struct sockaddr *, void *, struct ifnet * SCTP_UNUSED);
#elif defined(__FreeBSD__)
ipproto_ctlinput_t sctp_ctlinput;
#else
void sctp_ctlinput(int, struct sockaddr *, void *);
#endif
@ -394,7 +400,9 @@ void sctp_input(struct mbuf *,...);
void *sctp_ctlinput(int, struct sockaddr *, void *);
int sctp_ctloutput(int, struct socket *, int, int, struct mbuf **);
#endif
#if !(defined(__FreeBSD__) && !defined(__Userspace__))
void sctp_drain(void);
#endif
#if defined(__Userspace__)
void sctp_init(uint16_t,
int (*)(void *addr, void *buffer, size_t length, uint8_t tos, uint8_t set_df),

View File

@ -1178,6 +1178,7 @@ sctp_init_asoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
asoc->nrsack_supported = inp->nrsack_supported;
asoc->pktdrop_supported = inp->pktdrop_supported;
asoc->idata_supported = inp->idata_supported;
asoc->zero_checksum = inp->zero_checksum;
asoc->sctp_cmt_pf = (uint8_t)0;
asoc->sctp_frag_point = inp->sctp_frag_point;
asoc->sctp_features = inp->sctp_features;
@ -3993,10 +3994,17 @@ sctp_notify_stream_reset_add(struct sctp_tcb *stcb, uint16_t numberin, uint16_t
struct sctp_stream_change_event *stradd;
if ((stcb == NULL) ||
(sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_STREAM_CHANGEEVNT))) {
(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) ||
(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
(stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET)) {
/* If the socket is gone we are out of here. */
return;
}
if (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_STREAM_CHANGEEVNT)) {
/* event not enabled */
return;
}
if ((stcb->asoc.peer_req_out) && flag) {
/* Peer made the request, don't tell the local user */
stcb->asoc.peer_req_out = 0;
@ -4049,10 +4057,17 @@ sctp_notify_stream_reset_tsn(struct sctp_tcb *stcb, uint32_t sending_tsn, uint32
struct sctp_assoc_reset_event *strasoc;
if ((stcb == NULL) ||
(sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_ASSOC_RESETEVNT))) {
(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) ||
(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
(stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET)) {
/* If the socket is gone we are out of here. */
return;
}
if (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(sizeof(struct sctp_assoc_reset_event), 0, M_NOWAIT, 1, MT_DATA);
if (m_notify == NULL)
/* no space left */
@ -8162,11 +8177,11 @@ sctp_recv_udp_tunneled_packet(struct mbuf *m, int off, struct inpcb *inp,
#ifdef INET
static void
sctp_recv_icmp_tunneled_packet(int cmd, struct sockaddr *sa, void *vip, void *ctx SCTP_UNUSED)
sctp_recv_icmp_tunneled_packet(udp_tun_icmp_param_t param)
{
struct icmp *icmp = param.icmp;
struct ip *outer_ip, *inner_ip;
struct sctphdr *sh;
struct icmp *icmp;
struct udphdr *udp;
struct sctp_inpcb *inp;
struct sctp_tcb *stcb;
@ -8175,9 +8190,7 @@ sctp_recv_icmp_tunneled_packet(int cmd, struct sockaddr *sa, void *vip, void *ct
struct sockaddr_in src, dst;
uint8_t type, code;
inner_ip = (struct ip *)vip;
icmp = (struct icmp *)((caddr_t)inner_ip -
(sizeof(struct icmp) - sizeof(struct ip)));
inner_ip = &icmp->icmp_ip;
outer_ip = (struct ip *)((caddr_t)icmp - sizeof(struct ip));
if (ntohs(outer_ip->ip_len) <
sizeof(struct ip) + 8 + (inner_ip->ip_hl << 2) + sizeof(struct udphdr) + 8) {
@ -8295,9 +8308,9 @@ sctp_recv_icmp_tunneled_packet(int cmd, struct sockaddr *sa, void *vip, void *ct
#ifdef INET6
static void
sctp_recv_icmp6_tunneled_packet(int cmd, struct sockaddr *sa, void *d, void *ctx SCTP_UNUSED)
sctp_recv_icmp6_tunneled_packet(udp_tun_icmp_param_t param)
{
struct ip6ctlparam *ip6cp;
struct ip6ctlparam *ip6cp = param.ip6cp;
struct sctp_inpcb *inp;
struct sctp_tcb *stcb;
struct sctp_nets *net;
@ -8306,7 +8319,6 @@ sctp_recv_icmp6_tunneled_packet(int cmd, struct sockaddr *sa, void *d, void *ctx
struct sockaddr_in6 src, dst;
uint8_t type, code;
ip6cp = (struct ip6ctlparam *)d;
/*
* XXX: We assume that when IPV6 is non NULL, M and OFF are
* valid.

View File

@ -401,6 +401,121 @@ sctp6_notify(struct sctp_inpcb *inp,
}
}
#if defined(__FreeBSD__) && !defined(__Userspace__)
void
sctp6_ctlinput(struct ip6ctlparam *ip6cp)
{
struct sctp_inpcb *inp;
struct sctp_tcb *stcb;
struct sctp_nets *net;
struct sctphdr sh;
struct sockaddr_in6 src, dst;
if (icmp6_errmap(ip6cp->ip6c_icmp6) == 0) {
return;
}
/*
* Check if we can safely examine the ports and the
* verification tag of the SCTP common header.
*/
if (ip6cp->ip6c_m->m_pkthdr.len <
(int32_t)(ip6cp->ip6c_off + offsetof(struct sctphdr, checksum))) {
return;
}
/* Copy out the port numbers and the verification tag. */
memset(&sh, 0, sizeof(sh));
m_copydata(ip6cp->ip6c_m,
ip6cp->ip6c_off,
sizeof(uint16_t) + sizeof(uint16_t) + sizeof(uint32_t),
(caddr_t)&sh);
memset(&src, 0, sizeof(struct sockaddr_in6));
src.sin6_family = AF_INET6;
src.sin6_len = sizeof(struct sockaddr_in6);
src.sin6_port = sh.src_port;
src.sin6_addr = ip6cp->ip6c_ip6->ip6_src;
if (in6_setscope(&src.sin6_addr, ip6cp->ip6c_m->m_pkthdr.rcvif, NULL) != 0) {
return;
}
memset(&dst, 0, sizeof(struct sockaddr_in6));
dst.sin6_family = AF_INET6;
dst.sin6_len = sizeof(struct sockaddr_in6);
dst.sin6_port = sh.dest_port;
dst.sin6_addr = ip6cp->ip6c_ip6->ip6_dst;
if (in6_setscope(&dst.sin6_addr, ip6cp->ip6c_m->m_pkthdr.rcvif, NULL) != 0) {
return;
}
inp = NULL;
net = NULL;
stcb = sctp_findassociation_addr_sa((struct sockaddr *)&dst,
(struct sockaddr *)&src,
&inp, &net, 1, SCTP_DEFAULT_VRFID);
if ((stcb != NULL) &&
(net != NULL) &&
(inp != NULL)) {
/* Check the verification tag */
if (ntohl(sh.v_tag) != 0) {
/*
* This must be the verification tag used for
* sending out packets. We don't consider
* packets reflecting the verification tag.
*/
if (ntohl(sh.v_tag) != stcb->asoc.peer_vtag) {
SCTP_TCB_UNLOCK(stcb);
return;
}
} else {
if (ip6cp->ip6c_m->m_pkthdr.len >=
ip6cp->ip6c_off + sizeof(struct sctphdr) +
sizeof(struct sctp_chunkhdr) +
offsetof(struct sctp_init, a_rwnd)) {
/*
* In this case we can check if we
* got an INIT chunk and if the
* initiate tag matches.
*/
uint32_t initiate_tag;
uint8_t chunk_type;
m_copydata(ip6cp->ip6c_m,
ip6cp->ip6c_off +
sizeof(struct sctphdr),
sizeof(uint8_t),
(caddr_t)&chunk_type);
m_copydata(ip6cp->ip6c_m,
ip6cp->ip6c_off +
sizeof(struct sctphdr) +
sizeof(struct sctp_chunkhdr),
sizeof(uint32_t),
(caddr_t)&initiate_tag);
if ((chunk_type != SCTP_INITIATION) ||
(ntohl(initiate_tag) != stcb->asoc.my_vtag)) {
SCTP_TCB_UNLOCK(stcb);
return;
}
} else {
SCTP_TCB_UNLOCK(stcb);
return;
}
}
sctp6_notify(inp, stcb, net,
ip6cp->ip6c_icmp6->icmp6_type,
ip6cp->ip6c_icmp6->icmp6_code,
ntohl(ip6cp->ip6c_icmp6->icmp6_mtu));
} else {
if ((stcb == NULL) && (inp != NULL)) {
/* reduce inp's ref-count */
SCTP_INP_WLOCK(inp);
SCTP_INP_DECR_REF(inp);
SCTP_INP_WUNLOCK(inp);
}
if (stcb) {
SCTP_TCB_UNLOCK(stcb);
}
}
}
#else
void
#if defined(__APPLE__) && !defined(APPLE_LEOPARD) && !defined(APPLE_SNOWLEOPARD) && !defined(APPLE_LION) && !defined(APPLE_MOUNTAINLION) && !defined(APPLE_ELCAPITAN)
sctp6_ctlinput(int cmd, struct sockaddr *pktdst, void *d, struct ifnet *ifp SCTP_UNUSED)
@ -469,11 +584,6 @@ sctp6_ctlinput(int cmd, struct sockaddr *pktdst, void *d)
#endif
src.sin6_port = sh.src_port;
src.sin6_addr = ip6cp->ip6c_ip6->ip6_src;
#if defined(__FreeBSD__)
if (in6_setscope(&src.sin6_addr, ip6cp->ip6c_m->m_pkthdr.rcvif, NULL) != 0) {
return;
}
#endif
memset(&dst, 0, sizeof(struct sockaddr_in6));
dst.sin6_family = AF_INET6;
#ifdef HAVE_SIN6_LEN
@ -481,11 +591,6 @@ sctp6_ctlinput(int cmd, struct sockaddr *pktdst, void *d)
#endif
dst.sin6_port = sh.dest_port;
dst.sin6_addr = ip6cp->ip6c_ip6->ip6_dst;
#if defined(__FreeBSD__)
if (in6_setscope(&dst.sin6_addr, ip6cp->ip6c_m->m_pkthdr.rcvif, NULL) != 0) {
return;
}
#endif
inp = NULL;
net = NULL;
stcb = sctp_findassociation_addr_sa((struct sockaddr *)&dst,
@ -506,43 +611,8 @@ sctp6_ctlinput(int cmd, struct sockaddr *pktdst, void *d)
return;
}
} else {
#if defined(__FreeBSD__)
if (ip6cp->ip6c_m->m_pkthdr.len >=
ip6cp->ip6c_off + sizeof(struct sctphdr) +
sizeof(struct sctp_chunkhdr) +
offsetof(struct sctp_init, a_rwnd)) {
/*
* In this case we can check if we
* got an INIT chunk and if the
* initiate tag matches.
*/
uint32_t initiate_tag;
uint8_t chunk_type;
m_copydata(ip6cp->ip6c_m,
ip6cp->ip6c_off +
sizeof(struct sctphdr),
sizeof(uint8_t),
(caddr_t)&chunk_type);
m_copydata(ip6cp->ip6c_m,
ip6cp->ip6c_off +
sizeof(struct sctphdr) +
sizeof(struct sctp_chunkhdr),
sizeof(uint32_t),
(caddr_t)&initiate_tag);
if ((chunk_type != SCTP_INITIATION) ||
(ntohl(initiate_tag) != stcb->asoc.my_vtag)) {
SCTP_TCB_UNLOCK(stcb);
return;
}
} else {
SCTP_TCB_UNLOCK(stcb);
return;
}
#else
SCTP_TCB_UNLOCK(stcb);
return;
#endif
}
sctp6_notify(inp, stcb, net,
ip6cp->ip6c_icmp6->icmp6_type,
@ -580,6 +650,7 @@ sctp6_ctlinput(int cmd, struct sockaddr *pktdst, void *d)
}
}
#endif
#endif
/*
* this routine can probably be collasped into the one in sctp_userreq.c
@ -1667,27 +1738,43 @@ sctp6_getpeeraddr(struct socket *so, struct mbuf *nam)
}
#if !defined(__Userspace__)
struct pr_usrreqs sctp6_usrreqs = {
#if defined(__FreeBSD__)
.pru_abort = sctp6_abort,
.pru_accept = sctp_accept,
.pru_attach = sctp6_attach,
.pru_bind = sctp6_bind,
.pru_connect = sctp6_connect,
.pru_control = in6_control,
.pru_close = sctp6_close,
.pru_detach = sctp6_close,
.pru_sopoll = sopoll_generic,
.pru_flush = sctp_flush,
.pru_disconnect = sctp6_disconnect,
.pru_listen = sctp_listen,
.pru_peeraddr = sctp6_getpeeraddr,
.pru_send = sctp6_send,
.pru_shutdown = sctp_shutdown,
.pru_sockaddr = sctp6_in6getaddr,
.pru_sosend = sctp_sosend,
.pru_soreceive = sctp_soreceive
#elif defined(__APPLE__) && !defined(__Userspace__)
#define SCTP6_PROTOSW \
.pr_protocol = IPPROTO_SCTP, \
.pr_ctloutput = sctp_ctloutput, \
.pr_abort = sctp6_abort, \
.pr_accept = sctp_accept, \
.pr_attach = sctp6_attach, \
.pr_bind = sctp6_bind, \
.pr_connect = sctp6_connect, \
.pr_control = in6_control, \
.pr_close = sctp6_close, \
.pr_detach = sctp6_close, \
.pr_sopoll = sopoll_generic, \
.pr_flush = sctp_flush, \
.pr_disconnect = sctp6_disconnect, \
.pr_listen = sctp_listen, \
.pr_peeraddr = sctp6_getpeeraddr, \
.pr_send = sctp6_send, \
.pr_shutdown = sctp_shutdown, \
.pr_sockaddr = sctp6_in6getaddr, \
.pr_sosend = sctp_sosend, \
.pr_soreceive = sctp_soreceive
struct protosw sctp6_seqpacket_protosw = {
.pr_type = SOCK_SEQPACKET,
.pr_flags = PR_WANTRCVD,
SCTP6_PROTOSW
};
struct protosw sctp6_stream_protosw = {
.pr_type = SOCK_STREAM,
.pr_flags = PR_CONNREQUIRED | PR_WANTRCVD,
SCTP6_PROTOSW
};
#else
struct pr_usrreqs sctp6_usrreqs = {
#if defined(__APPLE__) && !defined(__Userspace__)
.pru_abort = sctp6_abort,
.pru_accept = sctp_accept,
.pru_attach = sctp6_attach,
@ -1732,120 +1819,8 @@ struct pr_usrreqs sctp6_usrreqs = {
sopoll_generic,
NULL,
sctp6_close
#endif
};
#elif !defined(__Userspace__)
int
sctp6_usrreq(so, req, m, nam, control, p)
struct socket *so;
int req;
struct mbuf *m, *nam, *control;
struct proc *p;
{
int error;
int family;
family = so->so_proto->pr_domain->dom_family;
if (req == PRU_CONTROL) {
switch (family) {
case PF_INET:
error = in_control(so, (long)m, (caddr_t)nam,
(struct ifnet *)control);
break;
#ifdef INET6
case PF_INET6:
error = in6_control(so, (long)m, (caddr_t)nam,
(struct ifnet *)control, p);
break;
#endif
default:
SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EAFNOSUPPORT);
error = EAFNOSUPPORT;
}
return (error);
}
switch (req) {
case PRU_ATTACH:
error = sctp6_attach(so, family, p);
break;
case PRU_DETACH:
error = sctp6_detach(so);
break;
case PRU_BIND:
if (nam == NULL) {
SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
return (EINVAL);
}
error = sctp6_bind(so, nam, p);
break;
case PRU_LISTEN:
error = sctp_listen(so, p);
break;
case PRU_CONNECT:
if (nam == NULL) {
SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
return (EINVAL);
}
error = sctp6_connect(so, nam, p);
break;
case PRU_DISCONNECT:
error = sctp6_disconnect(so);
break;
case PRU_ACCEPT:
if (nam == NULL) {
SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
return (EINVAL);
}
error = sctp_accept(so, nam);
break;
case PRU_SHUTDOWN:
error = sctp_shutdown(so);
break;
case PRU_RCVD:
/*
* For OpenBSD and NetBSD, this is real ugly. The (mbuf *)
* nam that is passed (by soreceive()) is the int flags cast
* as a (mbuf *) yuck!
*/
error = sctp_usr_recvd(so, (int)((long)nam));
break;
case PRU_SEND:
/* Flags are ignored */
error = sctp6_send(so, 0, m, nam, control, p);
break;
case PRU_ABORT:
error = sctp6_abort(so);
break;
case PRU_SENSE:
error = 0;
break;
case PRU_RCVOOB:
SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EAFNOSUPPORT);
error = EAFNOSUPPORT;
break;
case PRU_SENDOOB:
SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EAFNOSUPPORT);
error = EAFNOSUPPORT;
break;
case PRU_PEERADDR:
error = sctp6_getpeeraddr(so, nam);
break;
case PRU_SOCKADDR:
error = sctp6_in6getaddr(so, nam);
break;
case PRU_SLOWTIMO:
error = 0;
break;
default:
error = 0;
break;
}
return (error);
}
#endif
#endif
#endif
#endif

View File

@ -51,7 +51,11 @@ extern void in6_sin_2_v4mapsin6(const struct sockaddr_in *, struct sockaddr_in6
#if !defined(__Userspace__)
SYSCTL_DECL(_net_inet6_sctp6);
#if defined(__FreeBSD__)
extern struct protosw sctp6_seqpacket_protosw, sctp6_stream_protosw;
#else
extern struct pr_usrreqs sctp6_usrreqs;
#endif
#else
int sctp6_usrreq(struct socket *, int, struct mbuf *, struct mbuf *, struct mbuf *);
#endif
@ -67,8 +71,10 @@ int sctp6_output(struct sctp_inpcb *, struct mbuf *, struct sockaddr *,
struct mbuf *, struct proc *);
#if defined(__APPLE__) && !defined(__Userspace__) && !defined(APPLE_LEOPARD) && !defined(APPLE_SNOWLEOPARD) && !defined(APPLE_LION) && !defined(APPLE_MOUNTAINLION) && !defined(APPLE_ELCAPITAN)
void sctp6_ctlinput(int, struct sockaddr *, void *, struct ifnet * SCTP_UNUSED);
#elif defined(__FreeBSD__) && !defined(__Userspace__)
ip6proto_ctlinput_t sctp6_ctlinput;
#else
void sctp6_ctlinput(int, struct sockaddr *, void *);
void sctp6_ctlinput(int, struct sockaddr_in6 *, ip6ctlparam *);
#endif
#if !((defined(__FreeBSD__) || defined(__APPLE__)) && !defined(__Userspace__))
extern void in6_sin_2_v4mapsin6(struct sockaddr_in *, struct sockaddr_in6 *);

View File

@ -1146,6 +1146,7 @@ USRSCTP_SYSCTL_DECL(sctp_steady_step)
USRSCTP_SYSCTL_DECL(sctp_use_dccc_ecn)
USRSCTP_SYSCTL_DECL(sctp_buffer_splitting)
USRSCTP_SYSCTL_DECL(sctp_initial_cwnd)
USRSCTP_SYSCTL_DECL(sctp_ootb_with_zero_cksum)
#ifdef SCTP_DEBUG
USRSCTP_SYSCTL_DECL(sctp_debug_on)
/* More specific values can be found in sctp_constants, but
@ -1304,7 +1305,9 @@ struct sctpstat {
uint32_t sctps_send_cwnd_avoid; /* Send cwnd full avoidance, already max burst inflight to net */
uint32_t sctps_fwdtsn_map_over; /* number of map array over-runs via fwd-tsn's */
uint32_t sctps_queue_upd_ecne; /* Number of times we queued or updated an ECN chunk on send queue */
uint32_t sctps_reserved[31]; /* Future ABI compat - remove int's from here when adding new */
uint32_t sctps_recvzerocrc; /* Number of accepted packets with zero CRC */
uint32_t sctps_sendzerocrc; /* Number of packets sent with zero CRC */
uint32_t sctps_reserved[29]; /* Future ABI compat - remove int's from here when adding new */
};
void

View File

@ -1,35 +0,0 @@
#!/bin/bash
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
# assume $1 is the directory with a checkout of the libsctp source
#
# sctp usrlib source was available (via svn) at:
# svn co https://sctp-refimpl.googlecode.com/svn/trunk sctpSVN
# now available via git:
# git clone https://github.com/sctplab/usrsctp.git
#
# also assumes we've made *NO* changes to the SCTP sources! If we do, we have to merge by
# hand after this process, or use a more complex one.
#
# For example, one could update an sctp library import head, and merge back to default. Or keep a
# separate repo with this in it, and pull from there to m-c and merge.
if [ "$1" ] ; then
export date=`date`
export revision=`(cd $1; git rev-parse HEAD)`
cp $1/usrsctplib/*.c $1/usrsctplib/*.h netwerk/sctp/src
cp $1/usrsctplib/netinet/*.c $1/usrsctplib/netinet/*.h netwerk/sctp/src/netinet
cp $1/usrsctplib/netinet6/*.c $1/usrsctplib/netinet6/*.h netwerk/sctp/src/netinet6
hg addremove netwerk/sctp/src --include "**.c" --include "**.h" --similarity 90
echo "sctp updated to version $revision from git on $date" >> netwerk/sctp/sctp_update.log
echo "sctp updated to version $revision from git on $date"
else
echo "usage: $0 path_to_sctp_directory"
echo "run from the root of your m-c clone"
echo "example: sh netwerk/sctp/update.sh ../../sctp"
fi