1163953Srrs/*- 2185694Srrs * Copyright (c) 2001-2008, by Cisco Systems, Inc. All rights reserved. 3235828Stuexen * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved. 4235828Stuexen * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved. 5163953Srrs * 6163953Srrs * Redistribution and use in source and binary forms, with or without 7163953Srrs * modification, are permitted provided that the following conditions are met: 8163953Srrs * 9163953Srrs * a) Redistributions of source code must retain the above copyright notice, 10228653Stuexen * this list of conditions and the following disclaimer. 11163953Srrs * 12163953Srrs * b) Redistributions in binary form must reproduce the above copyright 13163953Srrs * notice, this list of conditions and the following disclaimer in 14228653Stuexen * the documentation and/or other materials provided with the distribution. 15163953Srrs * 16163953Srrs * c) Neither the name of Cisco Systems, Inc. nor the names of its 17163953Srrs * contributors may be used to endorse or promote products derived 18163953Srrs * from this software without specific prior written permission. 19163953Srrs * 20163953Srrs * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21163953Srrs * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 22163953Srrs * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23163953Srrs * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 24163953Srrs * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25163953Srrs * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26163953Srrs * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27163953Srrs * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28163953Srrs * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29163953Srrs * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 30163953Srrs * THE POSSIBILITY OF SUCH DAMAGE. 31163953Srrs */ 32163953Srrs 33163953Srrs#include <sys/cdefs.h> 34163953Srrs__FBSDID("$FreeBSD$"); 35163953Srrs 36163953Srrs#include <netinet/sctp_os.h> 37163953Srrs#include <netinet/sctp_pcb.h> 38163953Srrs#include <netinet/sctputil.h> 39163953Srrs#include <netinet/sctp_var.h> 40167598Srrs#include <netinet/sctp_sysctl.h> 41163953Srrs#ifdef INET6 42243186Stuexen#include <netinet6/sctp6_var.h> 43163953Srrs#endif 44163953Srrs#include <netinet/sctp_header.h> 45163953Srrs#include <netinet/sctp_output.h> 46163953Srrs#include <netinet/sctp_uio.h> 47163953Srrs#include <netinet/sctp_timer.h> 48163953Srrs#include <netinet/sctp_indata.h>/* for sctp_deliver_data() */ 49163953Srrs#include <netinet/sctp_auth.h> 50163953Srrs#include <netinet/sctp_asconf.h> 51208160Srrs#include <netinet/sctp_bsd_addr.h> 52243186Stuexen#include <netinet/udp.h> 53243186Stuexen#include <netinet/udp_var.h> 54243186Stuexen#include <sys/proc.h> 55163953Srrs 56163953Srrs 57170791Srrs#ifndef KTR_SCTP 58170791Srrs#define KTR_SCTP KTR_SUBSYS 59170744Srrs#endif 60163953Srrs 61217611Stuexenextern struct sctp_cc_functions sctp_cc_functions[]; 62217760Stuexenextern struct sctp_ss_functions sctp_ss_functions[]; 63217611Stuexen 64163953Srrsvoid 65240507Stuexensctp_sblog(struct sockbuf *sb, struct sctp_tcb *stcb, int from, int incr) 66163953Srrs{ 67170744Srrs struct sctp_cwnd_log sctp_clog; 68163953Srrs 69170744Srrs sctp_clog.x.sb.stcb = stcb; 70170744Srrs sctp_clog.x.sb.so_sbcc = sb->sb_cc; 71163953Srrs if (stcb) 72170744Srrs sctp_clog.x.sb.stcb_sbcc = stcb->asoc.sb_cc; 73163953Srrs else 74170744Srrs sctp_clog.x.sb.stcb_sbcc = 0; 75170744Srrs sctp_clog.x.sb.incr = incr; 76171943Srrs SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x", 77170744Srrs SCTP_LOG_EVENT_SB, 78170744Srrs from, 79170744Srrs sctp_clog.x.misc.log1, 80170744Srrs sctp_clog.x.misc.log2, 81170744Srrs sctp_clog.x.misc.log3, 82170744Srrs sctp_clog.x.misc.log4); 83163953Srrs} 84163953Srrs 85163953Srrsvoid 86163953Srrssctp_log_closing(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int16_t loc) 87163953Srrs{ 88170744Srrs struct sctp_cwnd_log sctp_clog; 89163953Srrs 90170744Srrs sctp_clog.x.close.inp = (void *)inp; 91170744Srrs sctp_clog.x.close.sctp_flags = inp->sctp_flags; 92163953Srrs if (stcb) { 93170744Srrs sctp_clog.x.close.stcb = (void *)stcb; 94170744Srrs sctp_clog.x.close.state = (uint16_t) stcb->asoc.state; 95163953Srrs } else { 96170744Srrs sctp_clog.x.close.stcb = 0; 97170744Srrs sctp_clog.x.close.state = 0; 98163953Srrs } 99170744Srrs sctp_clog.x.close.loc = loc; 100171943Srrs SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x", 101170744Srrs SCTP_LOG_EVENT_CLOSE, 102170744Srrs 0, 103170744Srrs sctp_clog.x.misc.log1, 104170744Srrs sctp_clog.x.misc.log2, 105170744Srrs sctp_clog.x.misc.log3, 106170744Srrs sctp_clog.x.misc.log4); 107163953Srrs} 108163953Srrs 109163953Srrsvoid 110163953Srrsrto_logging(struct sctp_nets *net, int from) 111163953Srrs{ 112170744Srrs struct sctp_cwnd_log sctp_clog; 113163953Srrs 114179141Srrs memset(&sctp_clog, 0, sizeof(sctp_clog)); 115170744Srrs sctp_clog.x.rto.net = (void *)net; 116219013Stuexen sctp_clog.x.rto.rtt = net->rtt / 1000; 117171943Srrs SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x", 118170744Srrs SCTP_LOG_EVENT_RTT, 119170744Srrs from, 120170744Srrs sctp_clog.x.misc.log1, 121170744Srrs sctp_clog.x.misc.log2, 122170744Srrs sctp_clog.x.misc.log3, 123170744Srrs sctp_clog.x.misc.log4); 124163953Srrs} 125163953Srrs 126163953Srrsvoid 127164181Srrssctp_log_strm_del_alt(struct sctp_tcb *stcb, uint32_t tsn, uint16_t sseq, uint16_t stream, int from) 128163953Srrs{ 129170744Srrs struct sctp_cwnd_log sctp_clog; 130163953Srrs 131170744Srrs sctp_clog.x.strlog.stcb = stcb; 132170744Srrs sctp_clog.x.strlog.n_tsn = tsn; 133170744Srrs sctp_clog.x.strlog.n_sseq = sseq; 134170744Srrs sctp_clog.x.strlog.e_tsn = 0; 135170744Srrs sctp_clog.x.strlog.e_sseq = 0; 136170744Srrs sctp_clog.x.strlog.strm = stream; 137171943Srrs SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x", 138170744Srrs SCTP_LOG_EVENT_STRM, 139170744Srrs from, 140170744Srrs sctp_clog.x.misc.log1, 141170744Srrs sctp_clog.x.misc.log2, 142170744Srrs sctp_clog.x.misc.log3, 143170744Srrs sctp_clog.x.misc.log4); 144163953Srrs} 145163953Srrs 146163953Srrsvoid 147163953Srrssctp_log_nagle_event(struct sctp_tcb *stcb, int action) 148163953Srrs{ 149170744Srrs struct sctp_cwnd_log sctp_clog; 150163953Srrs 151170744Srrs sctp_clog.x.nagle.stcb = (void *)stcb; 152170744Srrs sctp_clog.x.nagle.total_flight = stcb->asoc.total_flight; 153170744Srrs sctp_clog.x.nagle.total_in_queue = stcb->asoc.total_output_queue_size; 154170744Srrs sctp_clog.x.nagle.count_in_queue = stcb->asoc.chunks_on_out_queue; 155170744Srrs sctp_clog.x.nagle.count_in_flight = stcb->asoc.total_flight_count; 156171943Srrs SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x", 157170744Srrs SCTP_LOG_EVENT_NAGLE, 158170744Srrs action, 159170744Srrs sctp_clog.x.misc.log1, 160170744Srrs sctp_clog.x.misc.log2, 161170744Srrs sctp_clog.x.misc.log3, 162170744Srrs sctp_clog.x.misc.log4); 163163953Srrs} 164163953Srrs 165163953Srrsvoid 166163953Srrssctp_log_sack(uint32_t old_cumack, uint32_t cumack, uint32_t tsn, uint16_t gaps, uint16_t dups, int from) 167163953Srrs{ 168170744Srrs struct sctp_cwnd_log sctp_clog; 169163953Srrs 170170744Srrs sctp_clog.x.sack.cumack = cumack; 171170744Srrs sctp_clog.x.sack.oldcumack = old_cumack; 172170744Srrs sctp_clog.x.sack.tsn = tsn; 173170744Srrs sctp_clog.x.sack.numGaps = gaps; 174170744Srrs sctp_clog.x.sack.numDups = dups; 175171943Srrs SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x", 176170744Srrs SCTP_LOG_EVENT_SACK, 177170744Srrs from, 178170744Srrs sctp_clog.x.misc.log1, 179170744Srrs sctp_clog.x.misc.log2, 180170744Srrs sctp_clog.x.misc.log3, 181170744Srrs sctp_clog.x.misc.log4); 182163953Srrs} 183163953Srrs 184163953Srrsvoid 185163953Srrssctp_log_map(uint32_t map, uint32_t cum, uint32_t high, int from) 186163953Srrs{ 187170744Srrs struct sctp_cwnd_log sctp_clog; 188163953Srrs 189179141Srrs memset(&sctp_clog, 0, sizeof(sctp_clog)); 190170744Srrs sctp_clog.x.map.base = map; 191170744Srrs sctp_clog.x.map.cum = cum; 192170744Srrs sctp_clog.x.map.high = high; 193171943Srrs SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x", 194170744Srrs SCTP_LOG_EVENT_MAP, 195170744Srrs from, 196170744Srrs sctp_clog.x.misc.log1, 197170744Srrs sctp_clog.x.misc.log2, 198170744Srrs sctp_clog.x.misc.log3, 199170744Srrs sctp_clog.x.misc.log4); 200163953Srrs} 201163953Srrs 202163953Srrsvoid 203240507Stuexensctp_log_fr(uint32_t biggest_tsn, uint32_t biggest_new_tsn, uint32_t tsn, int from) 204163953Srrs{ 205170744Srrs struct sctp_cwnd_log sctp_clog; 206163953Srrs 207179141Srrs memset(&sctp_clog, 0, sizeof(sctp_clog)); 208170744Srrs sctp_clog.x.fr.largest_tsn = biggest_tsn; 209170744Srrs sctp_clog.x.fr.largest_new_tsn = biggest_new_tsn; 210170744Srrs sctp_clog.x.fr.tsn = tsn; 211171943Srrs SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x", 212170744Srrs SCTP_LOG_EVENT_FR, 213170744Srrs from, 214170744Srrs sctp_clog.x.misc.log1, 215170744Srrs sctp_clog.x.misc.log2, 216170744Srrs sctp_clog.x.misc.log3, 217170744Srrs sctp_clog.x.misc.log4); 218163953Srrs} 219163953Srrs 220283708Stuexen#ifdef SCTP_MBUF_LOGGING 221163953Srrsvoid 222163953Srrssctp_log_mb(struct mbuf *m, int from) 223163953Srrs{ 224170744Srrs struct sctp_cwnd_log sctp_clog; 225163953Srrs 226170744Srrs sctp_clog.x.mb.mp = m; 227170744Srrs sctp_clog.x.mb.mbuf_flags = (uint8_t) (SCTP_BUF_GET_FLAGS(m)); 228170744Srrs sctp_clog.x.mb.size = (uint16_t) (SCTP_BUF_LEN(m)); 229170744Srrs sctp_clog.x.mb.data = SCTP_BUF_AT(m, 0); 230165647Srrs if (SCTP_BUF_IS_EXTENDED(m)) { 231170744Srrs sctp_clog.x.mb.ext = SCTP_BUF_EXTEND_BASE(m); 232170744Srrs sctp_clog.x.mb.refcnt = (uint8_t) (SCTP_BUF_EXTEND_REFCNT(m)); 233163953Srrs } else { 234170744Srrs sctp_clog.x.mb.ext = 0; 235170744Srrs sctp_clog.x.mb.refcnt = 0; 236163953Srrs } 237171943Srrs SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x", 238170744Srrs SCTP_LOG_EVENT_MBUF, 239170744Srrs from, 240170744Srrs sctp_clog.x.misc.log1, 241170744Srrs sctp_clog.x.misc.log2, 242170744Srrs sctp_clog.x.misc.log3, 243170744Srrs sctp_clog.x.misc.log4); 244163953Srrs} 245163953Srrs 246163953Srrsvoid 247283708Stuexensctp_log_mbc(struct mbuf *m, int from) 248283708Stuexen{ 249283708Stuexen struct mbuf *mat; 250283708Stuexen 251283708Stuexen for (mat = m; mat; mat = SCTP_BUF_NEXT(mat)) { 252283708Stuexen sctp_log_mb(mat, from); 253283708Stuexen } 254283708Stuexen} 255283708Stuexen 256283708Stuexen#endif 257283708Stuexen 258283708Stuexenvoid 259240507Stuexensctp_log_strm_del(struct sctp_queued_to_read *control, struct sctp_queued_to_read *poschk, int from) 260163953Srrs{ 261170744Srrs struct sctp_cwnd_log sctp_clog; 262163953Srrs 263163953Srrs if (control == NULL) { 264169420Srrs SCTP_PRINTF("Gak log of NULL?\n"); 265163953Srrs return; 266163953Srrs } 267170744Srrs sctp_clog.x.strlog.stcb = control->stcb; 268170744Srrs sctp_clog.x.strlog.n_tsn = control->sinfo_tsn; 269170744Srrs sctp_clog.x.strlog.n_sseq = control->sinfo_ssn; 270170744Srrs sctp_clog.x.strlog.strm = control->sinfo_stream; 271163953Srrs if (poschk != NULL) { 272170744Srrs sctp_clog.x.strlog.e_tsn = poschk->sinfo_tsn; 273170744Srrs sctp_clog.x.strlog.e_sseq = poschk->sinfo_ssn; 274163953Srrs } else { 275170744Srrs sctp_clog.x.strlog.e_tsn = 0; 276170744Srrs sctp_clog.x.strlog.e_sseq = 0; 277163953Srrs } 278171943Srrs SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x", 279170744Srrs SCTP_LOG_EVENT_STRM, 280170744Srrs from, 281170744Srrs sctp_clog.x.misc.log1, 282170744Srrs sctp_clog.x.misc.log2, 283170744Srrs sctp_clog.x.misc.log3, 284170744Srrs sctp_clog.x.misc.log4); 285163953Srrs} 286163953Srrs 287163953Srrsvoid 288163953Srrssctp_log_cwnd(struct sctp_tcb *stcb, struct sctp_nets *net, int augment, uint8_t from) 289163953Srrs{ 290170744Srrs struct sctp_cwnd_log sctp_clog; 291163953Srrs 292170744Srrs sctp_clog.x.cwnd.net = net; 293163953Srrs if (stcb->asoc.send_queue_cnt > 255) 294170744Srrs sctp_clog.x.cwnd.cnt_in_send = 255; 295163953Srrs else 296170744Srrs sctp_clog.x.cwnd.cnt_in_send = stcb->asoc.send_queue_cnt; 297163953Srrs if (stcb->asoc.stream_queue_cnt > 255) 298170744Srrs sctp_clog.x.cwnd.cnt_in_str = 255; 299163953Srrs else 300170744Srrs sctp_clog.x.cwnd.cnt_in_str = stcb->asoc.stream_queue_cnt; 301163953Srrs 302163953Srrs if (net) { 303170744Srrs sctp_clog.x.cwnd.cwnd_new_value = net->cwnd; 304170744Srrs sctp_clog.x.cwnd.inflight = net->flight_size; 305170744Srrs sctp_clog.x.cwnd.pseudo_cumack = net->pseudo_cumack; 306170744Srrs sctp_clog.x.cwnd.meets_pseudo_cumack = net->new_pseudo_cumack; 307170744Srrs sctp_clog.x.cwnd.need_new_pseudo_cumack = net->find_pseudo_cumack; 308163953Srrs } 309163953Srrs if (SCTP_CWNDLOG_PRESEND == from) { 310170744Srrs sctp_clog.x.cwnd.meets_pseudo_cumack = stcb->asoc.peers_rwnd; 311163953Srrs } 312170744Srrs sctp_clog.x.cwnd.cwnd_augment = augment; 313171943Srrs SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x", 314170744Srrs SCTP_LOG_EVENT_CWND, 315170744Srrs from, 316170744Srrs sctp_clog.x.misc.log1, 317170744Srrs sctp_clog.x.misc.log2, 318170744Srrs sctp_clog.x.misc.log3, 319170744Srrs sctp_clog.x.misc.log4); 320163953Srrs} 321163953Srrs 322163953Srrsvoid 323163953Srrssctp_log_lock(struct sctp_inpcb *inp, struct sctp_tcb *stcb, uint8_t from) 324163953Srrs{ 325170744Srrs struct sctp_cwnd_log sctp_clog; 326163953Srrs 327179141Srrs memset(&sctp_clog, 0, sizeof(sctp_clog)); 328164085Srrs if (inp) { 329170744Srrs sctp_clog.x.lock.sock = (void *)inp->sctp_socket; 330164085Srrs 331164085Srrs } else { 332170744Srrs sctp_clog.x.lock.sock = (void *)NULL; 333164085Srrs } 334170744Srrs sctp_clog.x.lock.inp = (void *)inp; 335163953Srrs if (stcb) { 336170744Srrs sctp_clog.x.lock.tcb_lock = mtx_owned(&stcb->tcb_mtx); 337163953Srrs } else { 338170744Srrs sctp_clog.x.lock.tcb_lock = SCTP_LOCK_UNKNOWN; 339163953Srrs } 340163953Srrs if (inp) { 341170744Srrs sctp_clog.x.lock.inp_lock = mtx_owned(&inp->inp_mtx); 342170744Srrs sctp_clog.x.lock.create_lock = mtx_owned(&inp->inp_create_mtx); 343163953Srrs } else { 344170744Srrs sctp_clog.x.lock.inp_lock = SCTP_LOCK_UNKNOWN; 345170744Srrs sctp_clog.x.lock.create_lock = SCTP_LOCK_UNKNOWN; 346163953Srrs } 347179783Srrs sctp_clog.x.lock.info_lock = rw_wowned(&SCTP_BASE_INFO(ipi_ep_mtx)); 348212225Srrs if (inp && (inp->sctp_socket)) { 349170744Srrs sctp_clog.x.lock.sock_lock = mtx_owned(&(inp->sctp_socket->so_rcv.sb_mtx)); 350170744Srrs sctp_clog.x.lock.sockrcvbuf_lock = mtx_owned(&(inp->sctp_socket->so_rcv.sb_mtx)); 351170744Srrs sctp_clog.x.lock.socksndbuf_lock = mtx_owned(&(inp->sctp_socket->so_snd.sb_mtx)); 352163953Srrs } else { 353170744Srrs sctp_clog.x.lock.sock_lock = SCTP_LOCK_UNKNOWN; 354170744Srrs sctp_clog.x.lock.sockrcvbuf_lock = SCTP_LOCK_UNKNOWN; 355170744Srrs sctp_clog.x.lock.socksndbuf_lock = SCTP_LOCK_UNKNOWN; 356163953Srrs } 357171943Srrs SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x", 358170744Srrs SCTP_LOG_LOCK_EVENT, 359170744Srrs from, 360170744Srrs sctp_clog.x.misc.log1, 361170744Srrs sctp_clog.x.misc.log2, 362170744Srrs sctp_clog.x.misc.log3, 363170744Srrs sctp_clog.x.misc.log4); 364163953Srrs} 365163953Srrs 366163953Srrsvoid 367163953Srrssctp_log_maxburst(struct sctp_tcb *stcb, struct sctp_nets *net, int error, int burst, uint8_t from) 368163953Srrs{ 369170744Srrs struct sctp_cwnd_log sctp_clog; 370163953Srrs 371179141Srrs memset(&sctp_clog, 0, sizeof(sctp_clog)); 372170744Srrs sctp_clog.x.cwnd.net = net; 373170744Srrs sctp_clog.x.cwnd.cwnd_new_value = error; 374170744Srrs sctp_clog.x.cwnd.inflight = net->flight_size; 375170744Srrs sctp_clog.x.cwnd.cwnd_augment = burst; 376163953Srrs if (stcb->asoc.send_queue_cnt > 255) 377170744Srrs sctp_clog.x.cwnd.cnt_in_send = 255; 378163953Srrs else 379170744Srrs sctp_clog.x.cwnd.cnt_in_send = stcb->asoc.send_queue_cnt; 380163953Srrs if (stcb->asoc.stream_queue_cnt > 255) 381170744Srrs sctp_clog.x.cwnd.cnt_in_str = 255; 382163953Srrs else 383170744Srrs sctp_clog.x.cwnd.cnt_in_str = stcb->asoc.stream_queue_cnt; 384171943Srrs SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x", 385170744Srrs SCTP_LOG_EVENT_MAXBURST, 386170744Srrs from, 387170744Srrs sctp_clog.x.misc.log1, 388170744Srrs sctp_clog.x.misc.log2, 389170744Srrs sctp_clog.x.misc.log3, 390170744Srrs sctp_clog.x.misc.log4); 391163953Srrs} 392163953Srrs 393163953Srrsvoid 394163953Srrssctp_log_rwnd(uint8_t from, uint32_t peers_rwnd, uint32_t snd_size, uint32_t overhead) 395163953Srrs{ 396170744Srrs struct sctp_cwnd_log sctp_clog; 397163953Srrs 398170744Srrs sctp_clog.x.rwnd.rwnd = peers_rwnd; 399170744Srrs sctp_clog.x.rwnd.send_size = snd_size; 400170744Srrs sctp_clog.x.rwnd.overhead = overhead; 401170744Srrs sctp_clog.x.rwnd.new_rwnd = 0; 402171943Srrs SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x", 403170744Srrs SCTP_LOG_EVENT_RWND, 404170744Srrs from, 405170744Srrs sctp_clog.x.misc.log1, 406170744Srrs sctp_clog.x.misc.log2, 407170744Srrs sctp_clog.x.misc.log3, 408170744Srrs sctp_clog.x.misc.log4); 409163953Srrs} 410163953Srrs 411163953Srrsvoid 412163953Srrssctp_log_rwnd_set(uint8_t from, uint32_t peers_rwnd, uint32_t flight_size, uint32_t overhead, uint32_t a_rwndval) 413163953Srrs{ 414170744Srrs struct sctp_cwnd_log sctp_clog; 415163953Srrs 416170744Srrs sctp_clog.x.rwnd.rwnd = peers_rwnd; 417170744Srrs sctp_clog.x.rwnd.send_size = flight_size; 418170744Srrs sctp_clog.x.rwnd.overhead = overhead; 419170744Srrs sctp_clog.x.rwnd.new_rwnd = a_rwndval; 420171943Srrs SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x", 421170744Srrs SCTP_LOG_EVENT_RWND, 422170744Srrs from, 423170744Srrs sctp_clog.x.misc.log1, 424170744Srrs sctp_clog.x.misc.log2, 425170744Srrs sctp_clog.x.misc.log3, 426170744Srrs sctp_clog.x.misc.log4); 427163953Srrs} 428163953Srrs 429283708Stuexen#ifdef SCTP_MBCNT_LOGGING 430283708Stuexenstatic void 431163953Srrssctp_log_mbcnt(uint8_t from, uint32_t total_oq, uint32_t book, uint32_t total_mbcnt_q, uint32_t mbcnt) 432163953Srrs{ 433170744Srrs struct sctp_cwnd_log sctp_clog; 434163953Srrs 435170744Srrs sctp_clog.x.mbcnt.total_queue_size = total_oq; 436170744Srrs sctp_clog.x.mbcnt.size_change = book; 437170744Srrs sctp_clog.x.mbcnt.total_queue_mb_size = total_mbcnt_q; 438170744Srrs sctp_clog.x.mbcnt.mbcnt_change = mbcnt; 439171943Srrs SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x", 440170744Srrs SCTP_LOG_EVENT_MBCNT, 441170744Srrs from, 442170744Srrs sctp_clog.x.misc.log1, 443170744Srrs sctp_clog.x.misc.log2, 444170744Srrs sctp_clog.x.misc.log3, 445170744Srrs sctp_clog.x.misc.log4); 446163953Srrs} 447163953Srrs 448283708Stuexen#endif 449283708Stuexen 450163953Srrsvoid 451163953Srrssctp_misc_ints(uint8_t from, uint32_t a, uint32_t b, uint32_t c, uint32_t d) 452163953Srrs{ 453171943Srrs SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x", 454170744Srrs SCTP_LOG_MISC_EVENT, 455170744Srrs from, 456170744Srrs a, b, c, d); 457163953Srrs} 458163953Srrs 459163953Srrsvoid 460228653Stuexensctp_wakeup_log(struct sctp_tcb *stcb, uint32_t wake_cnt, int from) 461163953Srrs{ 462170744Srrs struct sctp_cwnd_log sctp_clog; 463163953Srrs 464170744Srrs sctp_clog.x.wake.stcb = (void *)stcb; 465170744Srrs sctp_clog.x.wake.wake_cnt = wake_cnt; 466170744Srrs sctp_clog.x.wake.flight = stcb->asoc.total_flight_count; 467170744Srrs sctp_clog.x.wake.send_q = stcb->asoc.send_queue_cnt; 468170744Srrs sctp_clog.x.wake.sent_q = stcb->asoc.sent_queue_cnt; 469163953Srrs 470163953Srrs if (stcb->asoc.stream_queue_cnt < 0xff) 471170744Srrs sctp_clog.x.wake.stream_qcnt = (uint8_t) stcb->asoc.stream_queue_cnt; 472163953Srrs else 473170744Srrs sctp_clog.x.wake.stream_qcnt = 0xff; 474163953Srrs 475163953Srrs if (stcb->asoc.chunks_on_out_queue < 0xff) 476170744Srrs sctp_clog.x.wake.chunks_on_oque = (uint8_t) stcb->asoc.chunks_on_out_queue; 477163953Srrs else 478170744Srrs sctp_clog.x.wake.chunks_on_oque = 0xff; 479163953Srrs 480170744Srrs sctp_clog.x.wake.sctpflags = 0; 481163953Srrs /* set in the defered mode stuff */ 482163953Srrs if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_DONT_WAKE) 483170744Srrs sctp_clog.x.wake.sctpflags |= 1; 484163953Srrs if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_WAKEOUTPUT) 485170744Srrs sctp_clog.x.wake.sctpflags |= 2; 486163953Srrs if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_WAKEINPUT) 487170744Srrs sctp_clog.x.wake.sctpflags |= 4; 488163953Srrs /* what about the sb */ 489163953Srrs if (stcb->sctp_socket) { 490163953Srrs struct socket *so = stcb->sctp_socket; 491163953Srrs 492170744Srrs sctp_clog.x.wake.sbflags = (uint8_t) ((so->so_snd.sb_flags & 0x00ff)); 493163953Srrs } else { 494170744Srrs sctp_clog.x.wake.sbflags = 0xff; 495163953Srrs } 496171943Srrs SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x", 497170744Srrs SCTP_LOG_EVENT_WAKE, 498170744Srrs from, 499170744Srrs sctp_clog.x.misc.log1, 500170744Srrs sctp_clog.x.misc.log2, 501170744Srrs sctp_clog.x.misc.log3, 502170744Srrs sctp_clog.x.misc.log4); 503163953Srrs} 504163953Srrs 505163953Srrsvoid 506228653Stuexensctp_log_block(uint8_t from, struct sctp_association *asoc, int sendlen) 507163953Srrs{ 508170744Srrs struct sctp_cwnd_log sctp_clog; 509163953Srrs 510170744Srrs sctp_clog.x.blk.onsb = asoc->total_output_queue_size; 511170744Srrs sctp_clog.x.blk.send_sent_qcnt = (uint16_t) (asoc->send_queue_cnt + asoc->sent_queue_cnt); 512170744Srrs sctp_clog.x.blk.peer_rwnd = asoc->peers_rwnd; 513170744Srrs sctp_clog.x.blk.stream_qcnt = (uint16_t) asoc->stream_queue_cnt; 514170744Srrs sctp_clog.x.blk.chunks_on_oque = (uint16_t) asoc->chunks_on_out_queue; 515170744Srrs sctp_clog.x.blk.flight_size = (uint16_t) (asoc->total_flight / 1024); 516170744Srrs sctp_clog.x.blk.sndlen = sendlen; 517171943Srrs SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x", 518170744Srrs SCTP_LOG_EVENT_BLOCK, 519170744Srrs from, 520170744Srrs sctp_clog.x.misc.log1, 521170744Srrs sctp_clog.x.misc.log2, 522170744Srrs sctp_clog.x.misc.log3, 523170744Srrs sctp_clog.x.misc.log4); 524163953Srrs} 525163953Srrs 526163953Srrsint 527228653Stuexensctp_fill_stat_log(void *optval SCTP_UNUSED, size_t *optsize SCTP_UNUSED) 528163953Srrs{ 529170744Srrs /* May need to fix this if ktrdump does not work */ 530163953Srrs return (0); 531163953Srrs} 532163953Srrs 533163953Srrs#ifdef SCTP_AUDITING_ENABLED 534163953Srrsuint8_t sctp_audit_data[SCTP_AUDIT_SIZE][2]; 535163953Srrsstatic int sctp_audit_indx = 0; 536163953Srrs 537163953Srrsstatic 538163953Srrsvoid 539163953Srrssctp_print_audit_report(void) 540163953Srrs{ 541163953Srrs int i; 542163953Srrs int cnt; 543163953Srrs 544163953Srrs cnt = 0; 545163953Srrs for (i = sctp_audit_indx; i < SCTP_AUDIT_SIZE; i++) { 546163953Srrs if ((sctp_audit_data[i][0] == 0xe0) && 547163953Srrs (sctp_audit_data[i][1] == 0x01)) { 548163953Srrs cnt = 0; 549169420Srrs SCTP_PRINTF("\n"); 550163953Srrs } else if (sctp_audit_data[i][0] == 0xf0) { 551163953Srrs cnt = 0; 552169420Srrs SCTP_PRINTF("\n"); 553163953Srrs } else if ((sctp_audit_data[i][0] == 0xc0) && 554163953Srrs (sctp_audit_data[i][1] == 0x01)) { 555169420Srrs SCTP_PRINTF("\n"); 556163953Srrs cnt = 0; 557163953Srrs } 558169420Srrs SCTP_PRINTF("%2.2x%2.2x ", (uint32_t) sctp_audit_data[i][0], 559163953Srrs (uint32_t) sctp_audit_data[i][1]); 560163953Srrs cnt++; 561163953Srrs if ((cnt % 14) == 0) 562169420Srrs SCTP_PRINTF("\n"); 563163953Srrs } 564163953Srrs for (i = 0; i < sctp_audit_indx; i++) { 565163953Srrs if ((sctp_audit_data[i][0] == 0xe0) && 566163953Srrs (sctp_audit_data[i][1] == 0x01)) { 567163953Srrs cnt = 0; 568169420Srrs SCTP_PRINTF("\n"); 569163953Srrs } else if (sctp_audit_data[i][0] == 0xf0) { 570163953Srrs cnt = 0; 571169420Srrs SCTP_PRINTF("\n"); 572163953Srrs } else if ((sctp_audit_data[i][0] == 0xc0) && 573163953Srrs (sctp_audit_data[i][1] == 0x01)) { 574169420Srrs SCTP_PRINTF("\n"); 575163953Srrs cnt = 0; 576163953Srrs } 577169420Srrs SCTP_PRINTF("%2.2x%2.2x ", (uint32_t) sctp_audit_data[i][0], 578163953Srrs (uint32_t) sctp_audit_data[i][1]); 579163953Srrs cnt++; 580163953Srrs if ((cnt % 14) == 0) 581169420Srrs SCTP_PRINTF("\n"); 582163953Srrs } 583169420Srrs SCTP_PRINTF("\n"); 584163953Srrs} 585163953Srrs 586163953Srrsvoid 587163953Srrssctp_auditing(int from, struct sctp_inpcb *inp, struct sctp_tcb *stcb, 588163953Srrs struct sctp_nets *net) 589163953Srrs{ 590163953Srrs int resend_cnt, tot_out, rep, tot_book_cnt; 591163953Srrs struct sctp_nets *lnet; 592163953Srrs struct sctp_tmit_chunk *chk; 593163953Srrs 594163953Srrs sctp_audit_data[sctp_audit_indx][0] = 0xAA; 595163953Srrs sctp_audit_data[sctp_audit_indx][1] = 0x000000ff & from; 596163953Srrs sctp_audit_indx++; 597163953Srrs if (sctp_audit_indx >= SCTP_AUDIT_SIZE) { 598163953Srrs sctp_audit_indx = 0; 599163953Srrs } 600163953Srrs if (inp == NULL) { 601163953Srrs sctp_audit_data[sctp_audit_indx][0] = 0xAF; 602163953Srrs sctp_audit_data[sctp_audit_indx][1] = 0x01; 603163953Srrs sctp_audit_indx++; 604163953Srrs if (sctp_audit_indx >= SCTP_AUDIT_SIZE) { 605163953Srrs sctp_audit_indx = 0; 606163953Srrs } 607163953Srrs return; 608163953Srrs } 609163953Srrs if (stcb == NULL) { 610163953Srrs sctp_audit_data[sctp_audit_indx][0] = 0xAF; 611163953Srrs sctp_audit_data[sctp_audit_indx][1] = 0x02; 612163953Srrs sctp_audit_indx++; 613163953Srrs if (sctp_audit_indx >= SCTP_AUDIT_SIZE) { 614163953Srrs sctp_audit_indx = 0; 615163953Srrs } 616163953Srrs return; 617163953Srrs } 618163953Srrs sctp_audit_data[sctp_audit_indx][0] = 0xA1; 619163953Srrs sctp_audit_data[sctp_audit_indx][1] = 620163953Srrs (0x000000ff & stcb->asoc.sent_queue_retran_cnt); 621163953Srrs sctp_audit_indx++; 622163953Srrs if (sctp_audit_indx >= SCTP_AUDIT_SIZE) { 623163953Srrs sctp_audit_indx = 0; 624163953Srrs } 625163953Srrs rep = 0; 626163953Srrs tot_book_cnt = 0; 627163953Srrs resend_cnt = tot_out = 0; 628163953Srrs TAILQ_FOREACH(chk, &stcb->asoc.sent_queue, sctp_next) { 629163953Srrs if (chk->sent == SCTP_DATAGRAM_RESEND) { 630163953Srrs resend_cnt++; 631163953Srrs } else if (chk->sent < SCTP_DATAGRAM_RESEND) { 632163953Srrs tot_out += chk->book_size; 633163953Srrs tot_book_cnt++; 634163953Srrs } 635163953Srrs } 636163953Srrs if (resend_cnt != stcb->asoc.sent_queue_retran_cnt) { 637163953Srrs sctp_audit_data[sctp_audit_indx][0] = 0xAF; 638163953Srrs sctp_audit_data[sctp_audit_indx][1] = 0xA1; 639163953Srrs sctp_audit_indx++; 640163953Srrs if (sctp_audit_indx >= SCTP_AUDIT_SIZE) { 641163953Srrs sctp_audit_indx = 0; 642163953Srrs } 643169420Srrs SCTP_PRINTF("resend_cnt:%d asoc-tot:%d\n", 644163953Srrs resend_cnt, stcb->asoc.sent_queue_retran_cnt); 645163953Srrs rep = 1; 646163953Srrs stcb->asoc.sent_queue_retran_cnt = resend_cnt; 647163953Srrs sctp_audit_data[sctp_audit_indx][0] = 0xA2; 648163953Srrs sctp_audit_data[sctp_audit_indx][1] = 649163953Srrs (0x000000ff & stcb->asoc.sent_queue_retran_cnt); 650163953Srrs sctp_audit_indx++; 651163953Srrs if (sctp_audit_indx >= SCTP_AUDIT_SIZE) { 652163953Srrs sctp_audit_indx = 0; 653163953Srrs } 654163953Srrs } 655163953Srrs if (tot_out != stcb->asoc.total_flight) { 656163953Srrs sctp_audit_data[sctp_audit_indx][0] = 0xAF; 657163953Srrs sctp_audit_data[sctp_audit_indx][1] = 0xA2; 658163953Srrs sctp_audit_indx++; 659163953Srrs if (sctp_audit_indx >= SCTP_AUDIT_SIZE) { 660163953Srrs sctp_audit_indx = 0; 661163953Srrs } 662163953Srrs rep = 1; 663169420Srrs SCTP_PRINTF("tot_flt:%d asoc_tot:%d\n", tot_out, 664163953Srrs (int)stcb->asoc.total_flight); 665163953Srrs stcb->asoc.total_flight = tot_out; 666163953Srrs } 667163953Srrs if (tot_book_cnt != stcb->asoc.total_flight_count) { 668163953Srrs sctp_audit_data[sctp_audit_indx][0] = 0xAF; 669163953Srrs sctp_audit_data[sctp_audit_indx][1] = 0xA5; 670163953Srrs sctp_audit_indx++; 671163953Srrs if (sctp_audit_indx >= SCTP_AUDIT_SIZE) { 672163953Srrs sctp_audit_indx = 0; 673163953Srrs } 674163953Srrs rep = 1; 675207099Stuexen SCTP_PRINTF("tot_flt_book:%d\n", tot_book_cnt); 676163953Srrs 677163953Srrs stcb->asoc.total_flight_count = tot_book_cnt; 678163953Srrs } 679163953Srrs tot_out = 0; 680163953Srrs TAILQ_FOREACH(lnet, &stcb->asoc.nets, sctp_next) { 681163953Srrs tot_out += lnet->flight_size; 682163953Srrs } 683163953Srrs if (tot_out != stcb->asoc.total_flight) { 684163953Srrs sctp_audit_data[sctp_audit_indx][0] = 0xAF; 685163953Srrs sctp_audit_data[sctp_audit_indx][1] = 0xA3; 686163953Srrs sctp_audit_indx++; 687163953Srrs if (sctp_audit_indx >= SCTP_AUDIT_SIZE) { 688163953Srrs sctp_audit_indx = 0; 689163953Srrs } 690163953Srrs rep = 1; 691169420Srrs SCTP_PRINTF("real flight:%d net total was %d\n", 692163953Srrs stcb->asoc.total_flight, tot_out); 693163953Srrs /* now corrective action */ 694163953Srrs TAILQ_FOREACH(lnet, &stcb->asoc.nets, sctp_next) { 695163953Srrs 696163953Srrs tot_out = 0; 697163953Srrs TAILQ_FOREACH(chk, &stcb->asoc.sent_queue, sctp_next) { 698163953Srrs if ((chk->whoTo == lnet) && 699163953Srrs (chk->sent < SCTP_DATAGRAM_RESEND)) { 700163953Srrs tot_out += chk->book_size; 701163953Srrs } 702163953Srrs } 703163953Srrs if (lnet->flight_size != tot_out) { 704207099Stuexen SCTP_PRINTF("net:%p flight was %d corrected to %d\n", 705240148Stuexen (void *)lnet, lnet->flight_size, 706169420Srrs tot_out); 707163953Srrs lnet->flight_size = tot_out; 708163953Srrs } 709163953Srrs } 710163953Srrs } 711163953Srrs if (rep) { 712163953Srrs sctp_print_audit_report(); 713163953Srrs } 714163953Srrs} 715163953Srrs 716163953Srrsvoid 717163953Srrssctp_audit_log(uint8_t ev, uint8_t fd) 718163953Srrs{ 719163953Srrs 720163953Srrs sctp_audit_data[sctp_audit_indx][0] = ev; 721163953Srrs sctp_audit_data[sctp_audit_indx][1] = fd; 722163953Srrs sctp_audit_indx++; 723163953Srrs if (sctp_audit_indx >= SCTP_AUDIT_SIZE) { 724163953Srrs sctp_audit_indx = 0; 725163953Srrs } 726163953Srrs} 727163953Srrs 728163953Srrs#endif 729163953Srrs 730163953Srrs/* 731214918Stuexen * sctp_stop_timers_for_shutdown() should be called 732214918Stuexen * when entering the SHUTDOWN_SENT or SHUTDOWN_ACK_SENT 733214918Stuexen * state to make sure that all timers are stopped. 734214918Stuexen */ 735214918Stuexenvoid 736214918Stuexensctp_stop_timers_for_shutdown(struct sctp_tcb *stcb) 737214918Stuexen{ 738214918Stuexen struct sctp_association *asoc; 739214918Stuexen struct sctp_nets *net; 740214918Stuexen 741214918Stuexen asoc = &stcb->asoc; 742214918Stuexen 743214918Stuexen (void)SCTP_OS_TIMER_STOP(&asoc->dack_timer.timer); 744214918Stuexen (void)SCTP_OS_TIMER_STOP(&asoc->strreset_timer.timer); 745214918Stuexen (void)SCTP_OS_TIMER_STOP(&asoc->asconf_timer.timer); 746214918Stuexen (void)SCTP_OS_TIMER_STOP(&asoc->autoclose_timer.timer); 747214918Stuexen (void)SCTP_OS_TIMER_STOP(&asoc->delayed_event_timer.timer); 748214918Stuexen TAILQ_FOREACH(net, &asoc->nets, sctp_next) { 749214918Stuexen (void)SCTP_OS_TIMER_STOP(&net->pmtu_timer.timer); 750224641Stuexen (void)SCTP_OS_TIMER_STOP(&net->hb_timer.timer); 751214918Stuexen } 752214918Stuexen} 753214918Stuexen 754214918Stuexen/* 755163953Srrs * a list of sizes based on typical mtu's, used only if next hop size not 756163953Srrs * returned. 757163953Srrs */ 758214939Stuexenstatic uint32_t sctp_mtu_sizes[] = { 759163953Srrs 68, 760163953Srrs 296, 761163953Srrs 508, 762163953Srrs 512, 763163953Srrs 544, 764163953Srrs 576, 765163953Srrs 1006, 766163953Srrs 1492, 767163953Srrs 1500, 768163953Srrs 1536, 769163953Srrs 2002, 770163953Srrs 2048, 771163953Srrs 4352, 772163953Srrs 4464, 773163953Srrs 8166, 774163953Srrs 17914, 775163953Srrs 32000, 776163953Srrs 65535 777163953Srrs}; 778163953Srrs 779214939Stuexen/* 780214939Stuexen * Return the largest MTU smaller than val. If there is no 781214939Stuexen * entry, just return val. 782214939Stuexen */ 783214939Stuexenuint32_t 784214939Stuexensctp_get_prev_mtu(uint32_t val) 785163953Srrs{ 786214939Stuexen uint32_t i; 787163953Srrs 788214939Stuexen if (val <= sctp_mtu_sizes[0]) { 789214939Stuexen return (val); 790214939Stuexen } 791214939Stuexen for (i = 1; i < (sizeof(sctp_mtu_sizes) / sizeof(uint32_t)); i++) { 792214939Stuexen if (val <= sctp_mtu_sizes[i]) { 793163953Srrs break; 794163953Srrs } 795163953Srrs } 796214939Stuexen return (sctp_mtu_sizes[i - 1]); 797163953Srrs} 798163953Srrs 799214939Stuexen/* 800214939Stuexen * Return the smallest MTU larger than val. If there is no 801214939Stuexen * entry, just return val. 802214939Stuexen */ 803214939Stuexenuint32_t 804228653Stuexensctp_get_next_mtu(uint32_t val) 805214939Stuexen{ 806214939Stuexen /* select another MTU that is just bigger than this one */ 807214939Stuexen uint32_t i; 808214939Stuexen 809214939Stuexen for (i = 0; i < (sizeof(sctp_mtu_sizes) / sizeof(uint32_t)); i++) { 810214939Stuexen if (val < sctp_mtu_sizes[i]) { 811214939Stuexen return (sctp_mtu_sizes[i]); 812214939Stuexen } 813214939Stuexen } 814214939Stuexen return (val); 815214939Stuexen} 816214939Stuexen 817163953Srrsvoid 818163953Srrssctp_fill_random_store(struct sctp_pcb *m) 819163953Srrs{ 820163953Srrs /* 821163953Srrs * Here we use the MD5/SHA-1 to hash with our good randomNumbers and 822163953Srrs * our counter. The result becomes our good random numbers and we 823163953Srrs * then setup to give these out. Note that we do no locking to 824163953Srrs * protect this. This is ok, since if competing folks call this we 825169352Srrs * will get more gobbled gook in the random store which is what we 826163953Srrs * want. There is a danger that two guys will use the same random 827163953Srrs * numbers, but thats ok too since that is random as well :-> 828163953Srrs */ 829163953Srrs m->store_at = 0; 830169420Srrs (void)sctp_hmac(SCTP_HMAC, (uint8_t *) m->random_numbers, 831163953Srrs sizeof(m->random_numbers), (uint8_t *) & m->random_counter, 832163953Srrs sizeof(m->random_counter), (uint8_t *) m->random_store); 833163953Srrs m->random_counter++; 834163953Srrs} 835163953Srrs 836163953Srrsuint32_t 837172091Srrssctp_select_initial_TSN(struct sctp_pcb *inp) 838163953Srrs{ 839163953Srrs /* 840163953Srrs * A true implementation should use random selection process to get 841163953Srrs * the initial stream sequence number, using RFC1750 as a good 842163953Srrs * guideline 843163953Srrs */ 844165647Srrs uint32_t x, *xp; 845163953Srrs uint8_t *p; 846172091Srrs int store_at, new_store; 847163953Srrs 848172091Srrs if (inp->initial_sequence_debug != 0) { 849163953Srrs uint32_t ret; 850163953Srrs 851172091Srrs ret = inp->initial_sequence_debug; 852172091Srrs inp->initial_sequence_debug++; 853163953Srrs return (ret); 854163953Srrs } 855172091Srrsretry: 856172091Srrs store_at = inp->store_at; 857172091Srrs new_store = store_at + sizeof(uint32_t); 858172091Srrs if (new_store >= (SCTP_SIGNATURE_SIZE - 3)) { 859172091Srrs new_store = 0; 860172091Srrs } 861172091Srrs if (!atomic_cmpset_int(&inp->store_at, store_at, new_store)) { 862172091Srrs goto retry; 863172091Srrs } 864172091Srrs if (new_store == 0) { 865163953Srrs /* Refill the random store */ 866172091Srrs sctp_fill_random_store(inp); 867163953Srrs } 868172091Srrs p = &inp->random_store[store_at]; 869165647Srrs xp = (uint32_t *) p; 870163953Srrs x = *xp; 871163953Srrs return (x); 872163953Srrs} 873163953Srrs 874163953Srrsuint32_t 875228653Stuexensctp_select_a_tag(struct sctp_inpcb *inp, uint16_t lport, uint16_t rport, int check) 876163953Srrs{ 877228653Stuexen uint32_t x; 878163953Srrs struct timeval now; 879163953Srrs 880228653Stuexen if (check) { 881228653Stuexen (void)SCTP_GETTIME_TIMEVAL(&now); 882228653Stuexen } 883228653Stuexen for (;;) { 884172091Srrs x = sctp_select_initial_TSN(&inp->sctp_ep); 885163953Srrs if (x == 0) { 886163953Srrs /* we never use 0 */ 887163953Srrs continue; 888163953Srrs } 889228653Stuexen if (!check || sctp_is_vtag_good(x, lport, rport, &now)) { 890228653Stuexen break; 891163953Srrs } 892163953Srrs } 893163953Srrs return (x); 894163953Srrs} 895163953Srrs 896294149Stuexenint32_t 897294149Stuexensctp_map_assoc_state(int kernel_state) 898294149Stuexen{ 899294149Stuexen int32_t user_state; 900294149Stuexen 901294149Stuexen if (kernel_state & SCTP_STATE_WAS_ABORTED) { 902294149Stuexen user_state = SCTP_CLOSED; 903294149Stuexen } else if (kernel_state & SCTP_STATE_SHUTDOWN_PENDING) { 904294149Stuexen user_state = SCTP_SHUTDOWN_PENDING; 905294149Stuexen } else { 906294149Stuexen switch (kernel_state & SCTP_STATE_MASK) { 907294149Stuexen case SCTP_STATE_EMPTY: 908294149Stuexen user_state = SCTP_CLOSED; 909294149Stuexen break; 910294149Stuexen case SCTP_STATE_INUSE: 911294149Stuexen user_state = SCTP_CLOSED; 912294149Stuexen break; 913294149Stuexen case SCTP_STATE_COOKIE_WAIT: 914294149Stuexen user_state = SCTP_COOKIE_WAIT; 915294149Stuexen break; 916294149Stuexen case SCTP_STATE_COOKIE_ECHOED: 917294149Stuexen user_state = SCTP_COOKIE_ECHOED; 918294149Stuexen break; 919294149Stuexen case SCTP_STATE_OPEN: 920294149Stuexen user_state = SCTP_ESTABLISHED; 921294149Stuexen break; 922294149Stuexen case SCTP_STATE_SHUTDOWN_SENT: 923294149Stuexen user_state = SCTP_SHUTDOWN_SENT; 924294149Stuexen break; 925294149Stuexen case SCTP_STATE_SHUTDOWN_RECEIVED: 926294149Stuexen user_state = SCTP_SHUTDOWN_RECEIVED; 927294149Stuexen break; 928294149Stuexen case SCTP_STATE_SHUTDOWN_ACK_SENT: 929294149Stuexen user_state = SCTP_SHUTDOWN_ACK_SENT; 930294149Stuexen break; 931294149Stuexen default: 932294149Stuexen user_state = SCTP_CLOSED; 933294149Stuexen break; 934294149Stuexen } 935294149Stuexen } 936294149Stuexen return (user_state); 937294149Stuexen} 938294149Stuexen 939163953Srrsint 940246595Stuexensctp_init_asoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, 941294215Stuexen uint32_t override_tag, uint32_t vrf_id, uint16_t o_strms) 942163953Srrs{ 943170138Srrs struct sctp_association *asoc; 944170138Srrs 945163953Srrs /* 946163953Srrs * Anything set to zero is taken care of by the allocation routine's 947163953Srrs * bzero 948163953Srrs */ 949163953Srrs 950163953Srrs /* 951163953Srrs * Up front select what scoping to apply on addresses I tell my peer 952163953Srrs * Not sure what to do with these right now, we will need to come up 953163953Srrs * with a way to set them. We may need to pass them through from the 954163953Srrs * caller in the sctp_aloc_assoc() function. 955163953Srrs */ 956163953Srrs int i; 957163953Srrs 958270363Stuexen#if defined(SCTP_DETAILED_STR_STATS) 959270363Stuexen int j; 960270363Stuexen 961270363Stuexen#endif 962270363Stuexen 963170138Srrs asoc = &stcb->asoc; 964163953Srrs /* init all variables to a known value. */ 965171943Srrs SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_INUSE); 966246595Stuexen asoc->max_burst = inp->sctp_ep.max_burst; 967246595Stuexen asoc->fr_max_burst = inp->sctp_ep.fr_max_burst; 968246595Stuexen asoc->heart_beat_delay = TICKS_TO_MSEC(inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT]); 969246595Stuexen asoc->cookie_life = inp->sctp_ep.def_cookie_life; 970246595Stuexen asoc->sctp_cmt_on_off = inp->sctp_cmt_on_off; 971270356Stuexen asoc->ecn_supported = inp->ecn_supported; 972270357Stuexen asoc->prsctp_supported = inp->prsctp_supported; 973270362Stuexen asoc->auth_supported = inp->auth_supported; 974270362Stuexen asoc->asconf_supported = inp->asconf_supported; 975270361Stuexen asoc->reconfig_supported = inp->reconfig_supported; 976270359Stuexen asoc->nrsack_supported = inp->nrsack_supported; 977270360Stuexen asoc->pktdrop_supported = inp->pktdrop_supported; 978224641Stuexen asoc->sctp_cmt_pf = (uint8_t) 0; 979246595Stuexen asoc->sctp_frag_point = inp->sctp_frag_point; 980246595Stuexen asoc->sctp_features = inp->sctp_features; 981246595Stuexen asoc->default_dscp = inp->sctp_ep.default_dscp; 982283724Stuexen asoc->max_cwnd = inp->max_cwnd; 983167598Srrs#ifdef INET6 984246595Stuexen if (inp->sctp_ep.default_flowlabel) { 985246595Stuexen asoc->default_flowlabel = inp->sctp_ep.default_flowlabel; 986225549Stuexen } else { 987246595Stuexen if (inp->ip_inp.inp.inp_flags & IN6P_AUTOFLOWLABEL) { 988246595Stuexen asoc->default_flowlabel = sctp_select_initial_TSN(&inp->sctp_ep); 989225549Stuexen asoc->default_flowlabel &= 0x000fffff; 990225549Stuexen asoc->default_flowlabel |= 0x80000000; 991225549Stuexen } else { 992225549Stuexen asoc->default_flowlabel = 0; 993225549Stuexen } 994225549Stuexen } 995163953Srrs#endif 996174257Srrs asoc->sb_send_resv = 0; 997163953Srrs if (override_tag) { 998185694Srrs asoc->my_vtag = override_tag; 999163953Srrs } else { 1000246595Stuexen asoc->my_vtag = sctp_select_a_tag(inp, stcb->sctp_ep->sctp_lport, stcb->rport, 1); 1001163953Srrs } 1002164144Srrs /* Get the nonce tags */ 1003246595Stuexen asoc->my_vtag_nonce = sctp_select_a_tag(inp, stcb->sctp_ep->sctp_lport, stcb->rport, 0); 1004246595Stuexen asoc->peer_vtag_nonce = sctp_select_a_tag(inp, stcb->sctp_ep->sctp_lport, stcb->rport, 0); 1005167598Srrs asoc->vrf_id = vrf_id; 1006164144Srrs 1007171477Srrs#ifdef SCTP_ASOCLOG_OF_TSNS 1008171477Srrs asoc->tsn_in_at = 0; 1009171477Srrs asoc->tsn_out_at = 0; 1010171477Srrs asoc->tsn_in_wrapped = 0; 1011171477Srrs asoc->tsn_out_wrapped = 0; 1012171477Srrs asoc->cumack_log_at = 0; 1013172703Srrs asoc->cumack_log_atsnt = 0; 1014171477Srrs#endif 1015171477Srrs#ifdef SCTP_FS_SPEC_LOG 1016171477Srrs asoc->fs_index = 0; 1017171477Srrs#endif 1018163953Srrs asoc->refcnt = 0; 1019163953Srrs asoc->assoc_up_sent = 0; 1020163953Srrs asoc->asconf_seq_out = asoc->str_reset_seq_out = asoc->init_seq_number = asoc->sending_seq = 1021246595Stuexen sctp_select_initial_TSN(&inp->sctp_ep); 1022179157Srrs asoc->asconf_seq_out_acked = asoc->asconf_seq_out - 1; 1023163953Srrs /* we are optimisitic here */ 1024185694Srrs asoc->peer_supports_nat = 0; 1025163953Srrs asoc->sent_queue_retran_cnt = 0; 1026163953Srrs 1027163953Srrs /* for CMT */ 1028190689Srrs asoc->last_net_cmt_send_started = NULL; 1029163953Srrs 1030163953Srrs /* This will need to be adjusted */ 1031163953Srrs asoc->last_acked_seq = asoc->init_seq_number - 1; 1032163953Srrs asoc->advanced_peer_ack_point = asoc->last_acked_seq; 1033163953Srrs asoc->asconf_seq_in = asoc->last_acked_seq; 1034163953Srrs 1035163953Srrs /* here we are different, we hold the next one we expect */ 1036163953Srrs asoc->str_reset_seq_in = asoc->last_acked_seq + 1; 1037163953Srrs 1038246595Stuexen asoc->initial_init_rto_max = inp->sctp_ep.initial_init_rto_max; 1039246595Stuexen asoc->initial_rto = inp->sctp_ep.initial_rto; 1040163953Srrs 1041246595Stuexen asoc->max_init_times = inp->sctp_ep.max_init_times; 1042246595Stuexen asoc->max_send_times = inp->sctp_ep.max_send_times; 1043246595Stuexen asoc->def_net_failure = inp->sctp_ep.def_net_failure; 1044246595Stuexen asoc->def_net_pf_threshold = inp->sctp_ep.def_net_pf_threshold; 1045163953Srrs asoc->free_chunk_cnt = 0; 1046163953Srrs 1047163953Srrs asoc->iam_blocking = 0; 1048246595Stuexen asoc->context = inp->sctp_context; 1049246595Stuexen asoc->local_strreset_support = inp->local_strreset_support; 1050246595Stuexen asoc->def_send = inp->def_send; 1051246595Stuexen asoc->delayed_ack = TICKS_TO_MSEC(inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV]); 1052246595Stuexen asoc->sack_freq = inp->sctp_ep.sctp_sack_freq; 1053163953Srrs asoc->pr_sctp_cnt = 0; 1054163953Srrs asoc->total_output_queue_size = 0; 1055163953Srrs 1056246595Stuexen if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) { 1057246595Stuexen asoc->scope.ipv6_addr_legal = 1; 1058246595Stuexen if (SCTP_IPV6_V6ONLY(inp) == 0) { 1059246595Stuexen asoc->scope.ipv4_addr_legal = 1; 1060163953Srrs } else { 1061246595Stuexen asoc->scope.ipv4_addr_legal = 0; 1062163953Srrs } 1063163953Srrs } else { 1064246595Stuexen asoc->scope.ipv6_addr_legal = 0; 1065246595Stuexen asoc->scope.ipv4_addr_legal = 1; 1066163953Srrs } 1067163953Srrs 1068246595Stuexen asoc->my_rwnd = max(SCTP_SB_LIMIT_RCV(inp->sctp_socket), SCTP_MINIMAL_RWND); 1069246595Stuexen asoc->peers_rwnd = SCTP_SB_LIMIT_RCV(inp->sctp_socket); 1070163953Srrs 1071246595Stuexen asoc->smallest_mtu = inp->sctp_frag_point; 1072246595Stuexen asoc->minrto = inp->sctp_ep.sctp_minrto; 1073246595Stuexen asoc->maxrto = inp->sctp_ep.sctp_maxrto; 1074163953Srrs 1075163953Srrs asoc->locked_on_sending = NULL; 1076163953Srrs asoc->stream_locked_on = 0; 1077163953Srrs asoc->ecn_echo_cnt_onq = 0; 1078163953Srrs asoc->stream_locked = 0; 1079163953Srrs 1080167598Srrs asoc->send_sack = 1; 1081167598Srrs 1082167598Srrs LIST_INIT(&asoc->sctp_restricted_addrs); 1083167598Srrs 1084163953Srrs TAILQ_INIT(&asoc->nets); 1085163953Srrs TAILQ_INIT(&asoc->pending_reply_queue); 1086171990Srrs TAILQ_INIT(&asoc->asconf_ack_sent); 1087163953Srrs /* Setup to fill the hb random cache at first HB */ 1088163953Srrs asoc->hb_random_idx = 4; 1089163953Srrs 1090246595Stuexen asoc->sctp_autoclose_ticks = inp->sctp_ep.auto_close_time; 1091163953Srrs 1092246595Stuexen stcb->asoc.congestion_control_module = inp->sctp_ep.sctp_default_cc_module; 1093246595Stuexen stcb->asoc.cc_functions = sctp_cc_functions[inp->sctp_ep.sctp_default_cc_module]; 1094171440Srrs 1095246595Stuexen stcb->asoc.stream_scheduling_module = inp->sctp_ep.sctp_default_ss_module; 1096246595Stuexen stcb->asoc.ss_functions = sctp_ss_functions[inp->sctp_ep.sctp_default_ss_module]; 1097217760Stuexen 1098171440Srrs /* 1099163953Srrs * Now the stream parameters, here we allocate space for all streams 1100163953Srrs * that we request by default. 1101163953Srrs */ 1102188854Srrs asoc->strm_realoutsize = asoc->streamoutcnt = asoc->pre_open_streams = 1103294215Stuexen o_strms; 1104163953Srrs SCTP_MALLOC(asoc->strmout, struct sctp_stream_out *, 1105163953Srrs asoc->streamoutcnt * sizeof(struct sctp_stream_out), 1106170091Srrs SCTP_M_STRMO); 1107163953Srrs if (asoc->strmout == NULL) { 1108163953Srrs /* big trouble no memory */ 1109171943Srrs SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ENOMEM); 1110163953Srrs return (ENOMEM); 1111163953Srrs } 1112163953Srrs for (i = 0; i < asoc->streamoutcnt; i++) { 1113163953Srrs /* 1114163953Srrs * inbound side must be set to 0xffff, also NOTE when we get 1115163953Srrs * the INIT-ACK back (for INIT sender) we MUST reduce the 1116163953Srrs * count (streamoutcnt) but first check if we sent to any of 1117163953Srrs * the upper streams that were dropped (if some were). Those 1118163953Srrs * that were dropped must be notified to the upper layer as 1119163953Srrs * failed to send. 1120163953Srrs */ 1121242627Stuexen asoc->strmout[i].next_sequence_send = 0x0; 1122163953Srrs TAILQ_INIT(&asoc->strmout[i].outqueue); 1123243157Stuexen asoc->strmout[i].chunks_on_queues = 0; 1124270363Stuexen#if defined(SCTP_DETAILED_STR_STATS) 1125270363Stuexen for (j = 0; j < SCTP_PR_SCTP_MAX + 1; j++) { 1126270363Stuexen asoc->strmout[i].abandoned_sent[j] = 0; 1127270363Stuexen asoc->strmout[i].abandoned_unsent[j] = 0; 1128270363Stuexen } 1129270363Stuexen#else 1130270363Stuexen asoc->strmout[i].abandoned_sent[0] = 0; 1131270363Stuexen asoc->strmout[i].abandoned_unsent[0] = 0; 1132270363Stuexen#endif 1133163953Srrs asoc->strmout[i].stream_no = i; 1134163953Srrs asoc->strmout[i].last_msg_incomplete = 0; 1135294140Stuexen asoc->strmout[i].state = SCTP_STREAM_OPENING; 1136218241Stuexen asoc->ss_functions.sctp_ss_init_stream(&asoc->strmout[i], NULL); 1137163953Srrs } 1138217760Stuexen asoc->ss_functions.sctp_ss_init(stcb, asoc, 0); 1139217760Stuexen 1140163953Srrs /* Now the mapping array */ 1141163953Srrs asoc->mapping_array_size = SCTP_INITIAL_MAPPING_ARRAY; 1142163953Srrs SCTP_MALLOC(asoc->mapping_array, uint8_t *, asoc->mapping_array_size, 1143170091Srrs SCTP_M_MAP); 1144163953Srrs if (asoc->mapping_array == NULL) { 1145170091Srrs SCTP_FREE(asoc->strmout, SCTP_M_STRMO); 1146171943Srrs SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ENOMEM); 1147163953Srrs return (ENOMEM); 1148163953Srrs } 1149163953Srrs memset(asoc->mapping_array, 0, asoc->mapping_array_size); 1150206137Stuexen SCTP_MALLOC(asoc->nr_mapping_array, uint8_t *, asoc->mapping_array_size, 1151185694Srrs SCTP_M_MAP); 1152193089Srrs if (asoc->nr_mapping_array == NULL) { 1153193089Srrs SCTP_FREE(asoc->strmout, SCTP_M_STRMO); 1154193089Srrs SCTP_FREE(asoc->mapping_array, SCTP_M_MAP); 1155193089Srrs SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ENOMEM); 1156193089Srrs return (ENOMEM); 1157193089Srrs } 1158206137Stuexen memset(asoc->nr_mapping_array, 0, asoc->mapping_array_size); 1159185694Srrs 1160163953Srrs /* Now the init of the other outqueues */ 1161163953Srrs TAILQ_INIT(&asoc->free_chunks); 1162163953Srrs TAILQ_INIT(&asoc->control_send_queue); 1163179157Srrs TAILQ_INIT(&asoc->asconf_send_queue); 1164163953Srrs TAILQ_INIT(&asoc->send_queue); 1165163953Srrs TAILQ_INIT(&asoc->sent_queue); 1166163953Srrs TAILQ_INIT(&asoc->reasmqueue); 1167163953Srrs TAILQ_INIT(&asoc->resetHead); 1168246595Stuexen asoc->max_inbound_streams = inp->sctp_ep.max_open_streams_intome; 1169163953Srrs TAILQ_INIT(&asoc->asconf_queue); 1170163953Srrs /* authentication fields */ 1171163953Srrs asoc->authinfo.random = NULL; 1172185694Srrs asoc->authinfo.active_keyid = 0; 1173163953Srrs asoc->authinfo.assoc_key = NULL; 1174163953Srrs asoc->authinfo.assoc_keyid = 0; 1175163953Srrs asoc->authinfo.recv_key = NULL; 1176163953Srrs asoc->authinfo.recv_keyid = 0; 1177163953Srrs LIST_INIT(&asoc->shared_keys); 1178166675Srrs asoc->marked_retrans = 0; 1179246595Stuexen asoc->port = inp->sctp_ep.port; 1180166675Srrs asoc->timoinit = 0; 1181166675Srrs asoc->timodata = 0; 1182166675Srrs asoc->timosack = 0; 1183166675Srrs asoc->timoshutdown = 0; 1184166675Srrs asoc->timoheartbeat = 0; 1185166675Srrs asoc->timocookie = 0; 1186166675Srrs asoc->timoshutdownack = 0; 1187169378Srrs (void)SCTP_GETTIME_TIMEVAL(&asoc->start_time); 1188169378Srrs asoc->discontinuity_time = asoc->start_time; 1189270363Stuexen for (i = 0; i < SCTP_PR_SCTP_MAX + 1; i++) { 1190270363Stuexen asoc->abandoned_unsent[i] = 0; 1191270363Stuexen asoc->abandoned_sent[i] = 0; 1192270363Stuexen } 1193170931Srrs /* 1194170931Srrs * sa_ignore MEMLEAK {memory is put in the assoc mapping array and 1195205627Srrs * freed later when the association is freed. 1196170931Srrs */ 1197163953Srrs return (0); 1198163953Srrs} 1199163953Srrs 1200205502Srrsvoid 1201205502Srrssctp_print_mapping_array(struct sctp_association *asoc) 1202205502Srrs{ 1203206281Stuexen unsigned int i, limit; 1204205502Srrs 1205234995Stuexen SCTP_PRINTF("Mapping array size: %d, baseTSN: %8.8x, cumAck: %8.8x, highestTSN: (%8.8x, %8.8x).\n", 1206205502Srrs asoc->mapping_array_size, 1207205502Srrs asoc->mapping_array_base_tsn, 1208205502Srrs asoc->cumulative_tsn, 1209206281Stuexen asoc->highest_tsn_inside_map, 1210206281Stuexen asoc->highest_tsn_inside_nr_map); 1211206281Stuexen for (limit = asoc->mapping_array_size; limit > 1; limit--) { 1212228907Stuexen if (asoc->mapping_array[limit - 1] != 0) { 1213205627Srrs break; 1214205627Srrs } 1215205627Srrs } 1216234995Stuexen SCTP_PRINTF("Renegable mapping array (last %d entries are zero):\n", asoc->mapping_array_size - limit); 1217205627Srrs for (i = 0; i < limit; i++) { 1218234995Stuexen SCTP_PRINTF("%2.2x%c", asoc->mapping_array[i], ((i + 1) % 16) ? ' ' : '\n'); 1219205502Srrs } 1220206281Stuexen if (limit % 16) 1221234995Stuexen SCTP_PRINTF("\n"); 1222206281Stuexen for (limit = asoc->mapping_array_size; limit > 1; limit--) { 1223206281Stuexen if (asoc->nr_mapping_array[limit - 1]) { 1224205627Srrs break; 1225205627Srrs } 1226205627Srrs } 1227234995Stuexen SCTP_PRINTF("Non renegable mapping array (last %d entries are zero):\n", asoc->mapping_array_size - limit); 1228205627Srrs for (i = 0; i < limit; i++) { 1229234995Stuexen SCTP_PRINTF("%2.2x%c", asoc->nr_mapping_array[i], ((i + 1) % 16) ? ' ' : '\n'); 1230205627Srrs } 1231206281Stuexen if (limit % 16) 1232234995Stuexen SCTP_PRINTF("\n"); 1233205502Srrs} 1234205502Srrs 1235163953Srrsint 1236170138Srrssctp_expand_mapping_array(struct sctp_association *asoc, uint32_t needed) 1237163953Srrs{ 1238163953Srrs /* mapping array needs to grow */ 1239206137Stuexen uint8_t *new_array1, *new_array2; 1240170138Srrs uint32_t new_size; 1241163953Srrs 1242170138Srrs new_size = asoc->mapping_array_size + ((needed + 7) / 8 + SCTP_MAPPING_ARRAY_INCR); 1243206137Stuexen SCTP_MALLOC(new_array1, uint8_t *, new_size, SCTP_M_MAP); 1244206137Stuexen SCTP_MALLOC(new_array2, uint8_t *, new_size, SCTP_M_MAP); 1245206137Stuexen if ((new_array1 == NULL) || (new_array2 == NULL)) { 1246163953Srrs /* can't get more, forget it */ 1247206137Stuexen SCTP_PRINTF("No memory for expansion of SCTP mapping array %d\n", new_size); 1248206137Stuexen if (new_array1) { 1249206137Stuexen SCTP_FREE(new_array1, SCTP_M_MAP); 1250206137Stuexen } 1251206137Stuexen if (new_array2) { 1252206137Stuexen SCTP_FREE(new_array2, SCTP_M_MAP); 1253206137Stuexen } 1254163953Srrs return (-1); 1255163953Srrs } 1256206137Stuexen memset(new_array1, 0, new_size); 1257206137Stuexen memset(new_array2, 0, new_size); 1258206137Stuexen memcpy(new_array1, asoc->mapping_array, asoc->mapping_array_size); 1259206137Stuexen memcpy(new_array2, asoc->nr_mapping_array, asoc->mapping_array_size); 1260170091Srrs SCTP_FREE(asoc->mapping_array, SCTP_M_MAP); 1261206137Stuexen SCTP_FREE(asoc->nr_mapping_array, SCTP_M_MAP); 1262206137Stuexen asoc->mapping_array = new_array1; 1263206137Stuexen asoc->nr_mapping_array = new_array2; 1264163953Srrs asoc->mapping_array_size = new_size; 1265163953Srrs return (0); 1266163953Srrs} 1267163953Srrs 1268185694Srrs 1269167598Srrsstatic void 1270167598Srrssctp_iterator_work(struct sctp_iterator *it) 1271167598Srrs{ 1272167598Srrs int iteration_count = 0; 1273167598Srrs int inp_skip = 0; 1274209029Srrs int first_in = 1; 1275209029Srrs struct sctp_inpcb *tinp; 1276163953Srrs 1277209029Srrs SCTP_INP_INFO_RLOCK(); 1278167598Srrs SCTP_ITERATOR_LOCK(); 1279169420Srrs if (it->inp) { 1280209029Srrs SCTP_INP_RLOCK(it->inp); 1281167598Srrs SCTP_INP_DECR_REF(it->inp); 1282169420Srrs } 1283167598Srrs if (it->inp == NULL) { 1284167598Srrs /* iterator is complete */ 1285167598Srrsdone_with_iterator: 1286167598Srrs SCTP_ITERATOR_UNLOCK(); 1287209029Srrs SCTP_INP_INFO_RUNLOCK(); 1288167598Srrs if (it->function_atend != NULL) { 1289167598Srrs (*it->function_atend) (it->pointer, it->val); 1290167598Srrs } 1291170091Srrs SCTP_FREE(it, SCTP_M_ITER); 1292167598Srrs return; 1293167598Srrs } 1294167598Srrsselect_a_new_ep: 1295209029Srrs if (first_in) { 1296209029Srrs first_in = 0; 1297209029Srrs } else { 1298209029Srrs SCTP_INP_RLOCK(it->inp); 1299209029Srrs } 1300167598Srrs while (((it->pcb_flags) && 1301167598Srrs ((it->inp->sctp_flags & it->pcb_flags) != it->pcb_flags)) || 1302167598Srrs ((it->pcb_features) && 1303167598Srrs ((it->inp->sctp_features & it->pcb_features) != it->pcb_features))) { 1304167598Srrs /* endpoint flags or features don't match, so keep looking */ 1305167598Srrs if (it->iterator_flags & SCTP_ITERATOR_DO_SINGLE_INP) { 1306208160Srrs SCTP_INP_RUNLOCK(it->inp); 1307167598Srrs goto done_with_iterator; 1308167598Srrs } 1309209029Srrs tinp = it->inp; 1310167598Srrs it->inp = LIST_NEXT(it->inp, sctp_list); 1311209029Srrs SCTP_INP_RUNLOCK(tinp); 1312167598Srrs if (it->inp == NULL) { 1313167598Srrs goto done_with_iterator; 1314167598Srrs } 1315208160Srrs SCTP_INP_RLOCK(it->inp); 1316167598Srrs } 1317167598Srrs /* now go through each assoc which is in the desired state */ 1318167598Srrs if (it->done_current_ep == 0) { 1319167598Srrs if (it->function_inp != NULL) 1320167598Srrs inp_skip = (*it->function_inp) (it->inp, it->pointer, it->val); 1321167598Srrs it->done_current_ep = 1; 1322167598Srrs } 1323167598Srrs if (it->stcb == NULL) { 1324167598Srrs /* run the per instance function */ 1325167598Srrs it->stcb = LIST_FIRST(&it->inp->sctp_asoc_list); 1326167598Srrs } 1327167598Srrs if ((inp_skip) || it->stcb == NULL) { 1328167598Srrs if (it->function_inp_end != NULL) { 1329167598Srrs inp_skip = (*it->function_inp_end) (it->inp, 1330167598Srrs it->pointer, 1331167598Srrs it->val); 1332167598Srrs } 1333167598Srrs SCTP_INP_RUNLOCK(it->inp); 1334167598Srrs goto no_stcb; 1335167598Srrs } 1336167598Srrs while (it->stcb) { 1337167598Srrs SCTP_TCB_LOCK(it->stcb); 1338167598Srrs if (it->asoc_state && ((it->stcb->asoc.state & it->asoc_state) != it->asoc_state)) { 1339167598Srrs /* not in the right state... keep looking */ 1340167598Srrs SCTP_TCB_UNLOCK(it->stcb); 1341167598Srrs goto next_assoc; 1342167598Srrs } 1343167598Srrs /* see if we have limited out the iterator loop */ 1344167598Srrs iteration_count++; 1345167598Srrs if (iteration_count > SCTP_ITERATOR_MAX_AT_ONCE) { 1346167598Srrs /* Pause to let others grab the lock */ 1347167598Srrs atomic_add_int(&it->stcb->asoc.refcnt, 1); 1348167598Srrs SCTP_TCB_UNLOCK(it->stcb); 1349171943Srrs SCTP_INP_INCR_REF(it->inp); 1350167598Srrs SCTP_INP_RUNLOCK(it->inp); 1351167598Srrs SCTP_ITERATOR_UNLOCK(); 1352209029Srrs SCTP_INP_INFO_RUNLOCK(); 1353209029Srrs SCTP_INP_INFO_RLOCK(); 1354167598Srrs SCTP_ITERATOR_LOCK(); 1355208160Srrs if (sctp_it_ctl.iterator_flags) { 1356208160Srrs /* We won't be staying here */ 1357208160Srrs SCTP_INP_DECR_REF(it->inp); 1358208160Srrs atomic_add_int(&it->stcb->asoc.refcnt, -1); 1359208160Srrs if (sctp_it_ctl.iterator_flags & 1360208160Srrs SCTP_ITERATOR_STOP_CUR_IT) { 1361208160Srrs sctp_it_ctl.iterator_flags &= ~SCTP_ITERATOR_STOP_CUR_IT; 1362208160Srrs goto done_with_iterator; 1363208160Srrs } 1364208160Srrs if (sctp_it_ctl.iterator_flags & 1365208160Srrs SCTP_ITERATOR_STOP_CUR_INP) { 1366208160Srrs sctp_it_ctl.iterator_flags &= ~SCTP_ITERATOR_STOP_CUR_INP; 1367208160Srrs goto no_stcb; 1368208160Srrs } 1369208160Srrs /* If we reach here huh? */ 1370234995Stuexen SCTP_PRINTF("Unknown it ctl flag %x\n", 1371208160Srrs sctp_it_ctl.iterator_flags); 1372208160Srrs sctp_it_ctl.iterator_flags = 0; 1373208160Srrs } 1374167598Srrs SCTP_INP_RLOCK(it->inp); 1375171943Srrs SCTP_INP_DECR_REF(it->inp); 1376167598Srrs SCTP_TCB_LOCK(it->stcb); 1377167598Srrs atomic_add_int(&it->stcb->asoc.refcnt, -1); 1378167598Srrs iteration_count = 0; 1379167598Srrs } 1380167598Srrs /* run function on this one */ 1381167598Srrs (*it->function_assoc) (it->inp, it->stcb, it->pointer, it->val); 1382167598Srrs 1383167598Srrs /* 1384167598Srrs * we lie here, it really needs to have its own type but 1385167598Srrs * first I must verify that this won't effect things :-0 1386167598Srrs */ 1387167598Srrs if (it->no_chunk_output == 0) 1388172090Srrs sctp_chunk_output(it->inp, it->stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_NOT_LOCKED); 1389167598Srrs 1390167598Srrs SCTP_TCB_UNLOCK(it->stcb); 1391167598Srrsnext_assoc: 1392167598Srrs it->stcb = LIST_NEXT(it->stcb, sctp_tcblist); 1393167598Srrs if (it->stcb == NULL) { 1394167598Srrs /* Run last function */ 1395167598Srrs if (it->function_inp_end != NULL) { 1396167598Srrs inp_skip = (*it->function_inp_end) (it->inp, 1397167598Srrs it->pointer, 1398167598Srrs it->val); 1399167598Srrs } 1400167598Srrs } 1401167598Srrs } 1402167598Srrs SCTP_INP_RUNLOCK(it->inp); 1403167598Srrsno_stcb: 1404167598Srrs /* done with all assocs on this endpoint, move on to next endpoint */ 1405167598Srrs it->done_current_ep = 0; 1406167598Srrs if (it->iterator_flags & SCTP_ITERATOR_DO_SINGLE_INP) { 1407167598Srrs it->inp = NULL; 1408167598Srrs } else { 1409167598Srrs it->inp = LIST_NEXT(it->inp, sctp_list); 1410167598Srrs } 1411167598Srrs if (it->inp == NULL) { 1412167598Srrs goto done_with_iterator; 1413167598Srrs } 1414167598Srrs goto select_a_new_ep; 1415167598Srrs} 1416167598Srrs 1417167598Srrsvoid 1418167598Srrssctp_iterator_worker(void) 1419167598Srrs{ 1420216822Stuexen struct sctp_iterator *it, *nit; 1421167598Srrs 1422167598Srrs /* This function is called with the WQ lock in place */ 1423167598Srrs 1424208160Srrs sctp_it_ctl.iterator_running = 1; 1425216822Stuexen TAILQ_FOREACH_SAFE(it, &sctp_it_ctl.iteratorhead, sctp_nxt_itr, nit) { 1426216822Stuexen sctp_it_ctl.cur_it = it; 1427167598Srrs /* now lets work on this one */ 1428208160Srrs TAILQ_REMOVE(&sctp_it_ctl.iteratorhead, it, sctp_nxt_itr); 1429167598Srrs SCTP_IPI_ITERATOR_WQ_UNLOCK(); 1430208160Srrs CURVNET_SET(it->vn); 1431167598Srrs sctp_iterator_work(it); 1432219397Srrs sctp_it_ctl.cur_it = NULL; 1433208160Srrs CURVNET_RESTORE(); 1434167598Srrs SCTP_IPI_ITERATOR_WQ_LOCK(); 1435169655Srrs /* sa_ignore FREED_MEMORY */ 1436167598Srrs } 1437208160Srrs sctp_it_ctl.iterator_running = 0; 1438167598Srrs return; 1439167598Srrs} 1440167598Srrs 1441167598Srrs 1442163953Srrsstatic void 1443163953Srrssctp_handle_addr_wq(void) 1444163953Srrs{ 1445163953Srrs /* deal with the ADDR wq from the rtsock calls */ 1446216822Stuexen struct sctp_laddr *wi, *nwi; 1447167598Srrs struct sctp_asconf_iterator *asc; 1448163953Srrs 1449167598Srrs SCTP_MALLOC(asc, struct sctp_asconf_iterator *, 1450170091Srrs sizeof(struct sctp_asconf_iterator), SCTP_M_ASC_IT); 1451167598Srrs if (asc == NULL) { 1452167598Srrs /* Try later, no memory */ 1453163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_ADDR_WQ, 1454163953Srrs (struct sctp_inpcb *)NULL, 1455163953Srrs (struct sctp_tcb *)NULL, 1456163953Srrs (struct sctp_nets *)NULL); 1457167598Srrs return; 1458163953Srrs } 1459167598Srrs LIST_INIT(&asc->list_of_work); 1460167598Srrs asc->cnt = 0; 1461208160Srrs 1462208160Srrs SCTP_WQ_ADDR_LOCK(); 1463216822Stuexen LIST_FOREACH_SAFE(wi, &SCTP_BASE_INFO(addr_wq), sctp_nxt_addr, nwi) { 1464167598Srrs LIST_REMOVE(wi, sctp_nxt_addr); 1465167598Srrs LIST_INSERT_HEAD(&asc->list_of_work, wi, sctp_nxt_addr); 1466167598Srrs asc->cnt++; 1467163953Srrs } 1468208160Srrs SCTP_WQ_ADDR_UNLOCK(); 1469208160Srrs 1470167598Srrs if (asc->cnt == 0) { 1471170091Srrs SCTP_FREE(asc, SCTP_M_ASC_IT); 1472167598Srrs } else { 1473296052Stuexen int ret; 1474296052Stuexen 1475296052Stuexen ret = sctp_initiate_iterator(sctp_asconf_iterator_ep, 1476171572Srrs sctp_asconf_iterator_stcb, 1477167598Srrs NULL, /* No ep end for boundall */ 1478167598Srrs SCTP_PCB_FLAGS_BOUNDALL, 1479167598Srrs SCTP_PCB_ANY_FEATURES, 1480171572Srrs SCTP_ASOC_ANY_STATE, 1481171572Srrs (void *)asc, 0, 1482171572Srrs sctp_asconf_iterator_end, NULL, 0); 1483296052Stuexen if (ret) { 1484296052Stuexen SCTP_PRINTF("Failed to initiate iterator for handle_addr_wq\n"); 1485296052Stuexen /* 1486296052Stuexen * Freeing if we are stopping or put back on the 1487296052Stuexen * addr_wq. 1488296052Stuexen */ 1489296052Stuexen if (SCTP_BASE_VAR(sctp_pcb_initialized) == 0) { 1490296052Stuexen sctp_asconf_iterator_end(asc, 0); 1491296052Stuexen } else { 1492296052Stuexen SCTP_WQ_ADDR_LOCK(); 1493296052Stuexen LIST_FOREACH(wi, &asc->list_of_work, sctp_nxt_addr) { 1494296052Stuexen LIST_INSERT_HEAD(&SCTP_BASE_INFO(addr_wq), wi, sctp_nxt_addr); 1495296052Stuexen } 1496296052Stuexen SCTP_WQ_ADDR_UNLOCK(); 1497296052Stuexen SCTP_FREE(asc, SCTP_M_ASC_IT); 1498296052Stuexen } 1499296052Stuexen } 1500167598Srrs } 1501163953Srrs} 1502163953Srrs 1503163953Srrsvoid 1504163953Srrssctp_timeout_handler(void *t) 1505163953Srrs{ 1506163953Srrs struct sctp_inpcb *inp; 1507163953Srrs struct sctp_tcb *stcb; 1508163953Srrs struct sctp_nets *net; 1509163953Srrs struct sctp_timer *tmr; 1510294145Stuexen struct mbuf *op_err; 1511172090Srrs 1512237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1513172090Srrs struct socket *so; 1514172090Srrs 1515172090Srrs#endif 1516283821Stuexen int did_output; 1517294221Stuexen int type; 1518163953Srrs 1519163953Srrs tmr = (struct sctp_timer *)t; 1520163953Srrs inp = (struct sctp_inpcb *)tmr->ep; 1521163953Srrs stcb = (struct sctp_tcb *)tmr->tcb; 1522163953Srrs net = (struct sctp_nets *)tmr->net; 1523197326Stuexen CURVNET_SET((struct vnet *)tmr->vnet); 1524163953Srrs did_output = 1; 1525163953Srrs 1526163953Srrs#ifdef SCTP_AUDITING_ENABLED 1527163953Srrs sctp_audit_log(0xF0, (uint8_t) tmr->type); 1528163953Srrs sctp_auditing(3, inp, stcb, net); 1529163953Srrs#endif 1530163953Srrs 1531163953Srrs /* sanity checks... */ 1532163953Srrs if (tmr->self != (void *)tmr) { 1533163953Srrs /* 1534169420Srrs * SCTP_PRINTF("Stale SCTP timer fired (%p), ignoring...\n", 1535240148Stuexen * (void *)tmr); 1536163953Srrs */ 1537197326Stuexen CURVNET_RESTORE(); 1538163953Srrs return; 1539163953Srrs } 1540165220Srrs tmr->stopped_from = 0xa001; 1541163953Srrs if (!SCTP_IS_TIMER_TYPE_VALID(tmr->type)) { 1542163953Srrs /* 1543169420Srrs * SCTP_PRINTF("SCTP timer fired with invalid type: 0x%x\n", 1544163953Srrs * tmr->type); 1545163953Srrs */ 1546197326Stuexen CURVNET_RESTORE(); 1547163953Srrs return; 1548163953Srrs } 1549165220Srrs tmr->stopped_from = 0xa002; 1550163953Srrs if ((tmr->type != SCTP_TIMER_TYPE_ADDR_WQ) && (inp == NULL)) { 1551197326Stuexen CURVNET_RESTORE(); 1552163953Srrs return; 1553163953Srrs } 1554163953Srrs /* if this is an iterator timeout, get the struct and clear inp */ 1555165220Srrs tmr->stopped_from = 0xa003; 1556163953Srrs if (inp) { 1557163953Srrs SCTP_INP_INCR_REF(inp); 1558229729Stuexen if ((inp->sctp_socket == NULL) && 1559163953Srrs ((tmr->type != SCTP_TIMER_TYPE_INPKILL) && 1560196260Stuexen (tmr->type != SCTP_TIMER_TYPE_INIT) && 1561184883Srrs (tmr->type != SCTP_TIMER_TYPE_SEND) && 1562184883Srrs (tmr->type != SCTP_TIMER_TYPE_RECV) && 1563184883Srrs (tmr->type != SCTP_TIMER_TYPE_HEARTBEAT) && 1564163953Srrs (tmr->type != SCTP_TIMER_TYPE_SHUTDOWN) && 1565163953Srrs (tmr->type != SCTP_TIMER_TYPE_SHUTDOWNACK) && 1566163953Srrs (tmr->type != SCTP_TIMER_TYPE_SHUTDOWNGUARD) && 1567163953Srrs (tmr->type != SCTP_TIMER_TYPE_ASOCKILL)) 1568163953Srrs ) { 1569163953Srrs SCTP_INP_DECR_REF(inp); 1570197326Stuexen CURVNET_RESTORE(); 1571163953Srrs return; 1572163953Srrs } 1573163953Srrs } 1574165220Srrs tmr->stopped_from = 0xa004; 1575163953Srrs if (stcb) { 1576168709Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 1577163953Srrs if (stcb->asoc.state == 0) { 1578168709Srrs atomic_add_int(&stcb->asoc.refcnt, -1); 1579163953Srrs if (inp) { 1580163953Srrs SCTP_INP_DECR_REF(inp); 1581163953Srrs } 1582197326Stuexen CURVNET_RESTORE(); 1583163953Srrs return; 1584163953Srrs } 1585163953Srrs } 1586294221Stuexen type = tmr->type; 1587165220Srrs tmr->stopped_from = 0xa005; 1588294221Stuexen SCTPDBG(SCTP_DEBUG_TIMER1, "Timer type %d goes off\n", type); 1589165647Srrs if (!SCTP_OS_TIMER_ACTIVE(&tmr->timer)) { 1590163953Srrs if (inp) { 1591163953Srrs SCTP_INP_DECR_REF(inp); 1592163953Srrs } 1593170091Srrs if (stcb) { 1594170091Srrs atomic_add_int(&stcb->asoc.refcnt, -1); 1595170091Srrs } 1596197326Stuexen CURVNET_RESTORE(); 1597163953Srrs return; 1598163953Srrs } 1599165220Srrs tmr->stopped_from = 0xa006; 1600165220Srrs 1601163953Srrs if (stcb) { 1602163953Srrs SCTP_TCB_LOCK(stcb); 1603163996Srrs atomic_add_int(&stcb->asoc.refcnt, -1); 1604294221Stuexen if ((type != SCTP_TIMER_TYPE_ASOCKILL) && 1605171440Srrs ((stcb->asoc.state == 0) || 1606171440Srrs (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED))) { 1607171440Srrs SCTP_TCB_UNLOCK(stcb); 1608171440Srrs if (inp) { 1609171440Srrs SCTP_INP_DECR_REF(inp); 1610171440Srrs } 1611197326Stuexen CURVNET_RESTORE(); 1612171440Srrs return; 1613171440Srrs } 1614163953Srrs } 1615166023Srrs /* record in stopped what t-o occured */ 1616294221Stuexen tmr->stopped_from = type; 1617166023Srrs 1618163953Srrs /* mark as being serviced now */ 1619166023Srrs if (SCTP_OS_TIMER_PENDING(&tmr->timer)) { 1620166023Srrs /* 1621166023Srrs * Callout has been rescheduled. 1622166023Srrs */ 1623166023Srrs goto get_out; 1624166023Srrs } 1625166023Srrs if (!SCTP_OS_TIMER_ACTIVE(&tmr->timer)) { 1626166023Srrs /* 1627166023Srrs * Not active, so no action. 1628166023Srrs */ 1629166023Srrs goto get_out; 1630166023Srrs } 1631165647Srrs SCTP_OS_TIMER_DEACTIVATE(&tmr->timer); 1632163953Srrs 1633163953Srrs /* call the handler for the appropriate timer type */ 1634294221Stuexen switch (type) { 1635170056Srrs case SCTP_TIMER_TYPE_ZERO_COPY: 1636170931Srrs if (inp == NULL) { 1637170931Srrs break; 1638170931Srrs } 1639170056Srrs if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_ZERO_COPY_ACTIVE)) { 1640170056Srrs SCTP_ZERO_COPY_EVENT(inp, inp->sctp_socket); 1641170056Srrs } 1642170056Srrs break; 1643170181Srrs case SCTP_TIMER_TYPE_ZCOPY_SENDQ: 1644170931Srrs if (inp == NULL) { 1645170931Srrs break; 1646170931Srrs } 1647170181Srrs if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_ZERO_COPY_ACTIVE)) { 1648170181Srrs SCTP_ZERO_COPY_SENDQ_EVENT(inp, inp->sctp_socket); 1649170181Srrs } 1650170181Srrs break; 1651163953Srrs case SCTP_TIMER_TYPE_ADDR_WQ: 1652163953Srrs sctp_handle_addr_wq(); 1653163953Srrs break; 1654163953Srrs case SCTP_TIMER_TYPE_SEND: 1655169420Srrs if ((stcb == NULL) || (inp == NULL)) { 1656169420Srrs break; 1657169420Srrs } 1658163953Srrs SCTP_STAT_INCR(sctps_timodata); 1659166675Srrs stcb->asoc.timodata++; 1660163953Srrs stcb->asoc.num_send_timers_up--; 1661163953Srrs if (stcb->asoc.num_send_timers_up < 0) { 1662163953Srrs stcb->asoc.num_send_timers_up = 0; 1663163953Srrs } 1664171440Srrs SCTP_TCB_LOCK_ASSERT(stcb); 1665228907Stuexen if (sctp_t3rxt_timer(inp, stcb, net)) { 1666163953Srrs /* no need to unlock on tcb its gone */ 1667163953Srrs 1668163953Srrs goto out_decr; 1669163953Srrs } 1670171440Srrs SCTP_TCB_LOCK_ASSERT(stcb); 1671163953Srrs#ifdef SCTP_AUDITING_ENABLED 1672163953Srrs sctp_auditing(4, inp, stcb, net); 1673163953Srrs#endif 1674172090Srrs sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_NOT_LOCKED); 1675163953Srrs if ((stcb->asoc.num_send_timers_up == 0) && 1676216822Stuexen (stcb->asoc.sent_queue_cnt > 0)) { 1677163953Srrs struct sctp_tmit_chunk *chk; 1678163953Srrs 1679163953Srrs /* 1680163953Srrs * safeguard. If there on some on the sent queue 1681163953Srrs * somewhere but no timers running something is 1682163953Srrs * wrong... so we start a timer on the first chunk 1683163953Srrs * on the send queue on whatever net it is sent to. 1684163953Srrs */ 1685163953Srrs chk = TAILQ_FIRST(&stcb->asoc.sent_queue); 1686163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_SEND, inp, stcb, 1687163953Srrs chk->whoTo); 1688163953Srrs } 1689163953Srrs break; 1690163953Srrs case SCTP_TIMER_TYPE_INIT: 1691169420Srrs if ((stcb == NULL) || (inp == NULL)) { 1692169420Srrs break; 1693169420Srrs } 1694163953Srrs SCTP_STAT_INCR(sctps_timoinit); 1695166675Srrs stcb->asoc.timoinit++; 1696163953Srrs if (sctp_t1init_timer(inp, stcb, net)) { 1697163953Srrs /* no need to unlock on tcb its gone */ 1698163953Srrs goto out_decr; 1699163953Srrs } 1700163953Srrs /* We do output but not here */ 1701163953Srrs did_output = 0; 1702163953Srrs break; 1703163953Srrs case SCTP_TIMER_TYPE_RECV: 1704169420Srrs if ((stcb == NULL) || (inp == NULL)) { 1705169420Srrs break; 1706169420Srrs } 1707224641Stuexen SCTP_STAT_INCR(sctps_timosack); 1708224641Stuexen stcb->asoc.timosack++; 1709224641Stuexen sctp_send_sack(stcb, SCTP_SO_NOT_LOCKED); 1710163953Srrs#ifdef SCTP_AUDITING_ENABLED 1711163953Srrs sctp_auditing(4, inp, stcb, net); 1712163953Srrs#endif 1713172090Srrs sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_SACK_TMR, SCTP_SO_NOT_LOCKED); 1714163953Srrs break; 1715163953Srrs case SCTP_TIMER_TYPE_SHUTDOWN: 1716169420Srrs if ((stcb == NULL) || (inp == NULL)) { 1717169420Srrs break; 1718169420Srrs } 1719163953Srrs if (sctp_shutdown_timer(inp, stcb, net)) { 1720163953Srrs /* no need to unlock on tcb its gone */ 1721163953Srrs goto out_decr; 1722163953Srrs } 1723163953Srrs SCTP_STAT_INCR(sctps_timoshutdown); 1724166675Srrs stcb->asoc.timoshutdown++; 1725163953Srrs#ifdef SCTP_AUDITING_ENABLED 1726163953Srrs sctp_auditing(4, inp, stcb, net); 1727163953Srrs#endif 1728172090Srrs sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_SHUT_TMR, SCTP_SO_NOT_LOCKED); 1729163953Srrs break; 1730163953Srrs case SCTP_TIMER_TYPE_HEARTBEAT: 1731224641Stuexen if ((stcb == NULL) || (inp == NULL) || (net == NULL)) { 1732224641Stuexen break; 1733224641Stuexen } 1734224641Stuexen SCTP_STAT_INCR(sctps_timoheartbeat); 1735224641Stuexen stcb->asoc.timoheartbeat++; 1736224641Stuexen if (sctp_heartbeat_timer(inp, stcb, net)) { 1737224641Stuexen /* no need to unlock on tcb its gone */ 1738224641Stuexen goto out_decr; 1739224641Stuexen } 1740163953Srrs#ifdef SCTP_AUDITING_ENABLED 1741224641Stuexen sctp_auditing(4, inp, stcb, net); 1742163953Srrs#endif 1743224641Stuexen if (!(net->dest_state & SCTP_ADDR_NOHB)) { 1744226168Stuexen sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net); 1745172090Srrs sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_HB_TMR, SCTP_SO_NOT_LOCKED); 1746163953Srrs } 1747163953Srrs break; 1748163953Srrs case SCTP_TIMER_TYPE_COOKIE: 1749169420Srrs if ((stcb == NULL) || (inp == NULL)) { 1750169420Srrs break; 1751169420Srrs } 1752163953Srrs if (sctp_cookie_timer(inp, stcb, net)) { 1753163953Srrs /* no need to unlock on tcb its gone */ 1754163953Srrs goto out_decr; 1755163953Srrs } 1756163953Srrs SCTP_STAT_INCR(sctps_timocookie); 1757166675Srrs stcb->asoc.timocookie++; 1758163953Srrs#ifdef SCTP_AUDITING_ENABLED 1759163953Srrs sctp_auditing(4, inp, stcb, net); 1760163953Srrs#endif 1761163953Srrs /* 1762163953Srrs * We consider T3 and Cookie timer pretty much the same with 1763163953Srrs * respect to where from in chunk_output. 1764163953Srrs */ 1765172090Srrs sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_NOT_LOCKED); 1766163953Srrs break; 1767163953Srrs case SCTP_TIMER_TYPE_NEWCOOKIE: 1768163953Srrs { 1769163953Srrs struct timeval tv; 1770163953Srrs int i, secret; 1771163953Srrs 1772169420Srrs if (inp == NULL) { 1773169420Srrs break; 1774169420Srrs } 1775163953Srrs SCTP_STAT_INCR(sctps_timosecret); 1776169378Srrs (void)SCTP_GETTIME_TIMEVAL(&tv); 1777163953Srrs SCTP_INP_WLOCK(inp); 1778163953Srrs inp->sctp_ep.time_of_secret_change = tv.tv_sec; 1779163953Srrs inp->sctp_ep.last_secret_number = 1780163953Srrs inp->sctp_ep.current_secret_number; 1781163953Srrs inp->sctp_ep.current_secret_number++; 1782163953Srrs if (inp->sctp_ep.current_secret_number >= 1783163953Srrs SCTP_HOW_MANY_SECRETS) { 1784163953Srrs inp->sctp_ep.current_secret_number = 0; 1785163953Srrs } 1786163953Srrs secret = (int)inp->sctp_ep.current_secret_number; 1787163953Srrs for (i = 0; i < SCTP_NUMBER_OF_SECRETS; i++) { 1788163953Srrs inp->sctp_ep.secret_key[secret][i] = 1789163953Srrs sctp_select_initial_TSN(&inp->sctp_ep); 1790163953Srrs } 1791163953Srrs SCTP_INP_WUNLOCK(inp); 1792163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_NEWCOOKIE, inp, stcb, net); 1793163953Srrs } 1794163953Srrs did_output = 0; 1795163953Srrs break; 1796163953Srrs case SCTP_TIMER_TYPE_PATHMTURAISE: 1797169420Srrs if ((stcb == NULL) || (inp == NULL)) { 1798169420Srrs break; 1799169420Srrs } 1800163953Srrs SCTP_STAT_INCR(sctps_timopathmtu); 1801163953Srrs sctp_pathmtu_timer(inp, stcb, net); 1802163953Srrs did_output = 0; 1803163953Srrs break; 1804163953Srrs case SCTP_TIMER_TYPE_SHUTDOWNACK: 1805169420Srrs if ((stcb == NULL) || (inp == NULL)) { 1806169420Srrs break; 1807169420Srrs } 1808163953Srrs if (sctp_shutdownack_timer(inp, stcb, net)) { 1809163953Srrs /* no need to unlock on tcb its gone */ 1810163953Srrs goto out_decr; 1811163953Srrs } 1812163953Srrs SCTP_STAT_INCR(sctps_timoshutdownack); 1813166675Srrs stcb->asoc.timoshutdownack++; 1814163953Srrs#ifdef SCTP_AUDITING_ENABLED 1815163953Srrs sctp_auditing(4, inp, stcb, net); 1816163953Srrs#endif 1817172090Srrs sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_SHUT_ACK_TMR, SCTP_SO_NOT_LOCKED); 1818163953Srrs break; 1819163953Srrs case SCTP_TIMER_TYPE_SHUTDOWNGUARD: 1820169420Srrs if ((stcb == NULL) || (inp == NULL)) { 1821169420Srrs break; 1822169420Srrs } 1823163953Srrs SCTP_STAT_INCR(sctps_timoshutdownguard); 1824294145Stuexen op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), 1825294145Stuexen "Shutdown guard timer expired"); 1826294145Stuexen sctp_abort_an_association(inp, stcb, op_err, SCTP_SO_NOT_LOCKED); 1827163953Srrs /* no need to unlock on tcb its gone */ 1828163953Srrs goto out_decr; 1829163953Srrs 1830163953Srrs case SCTP_TIMER_TYPE_STRRESET: 1831169420Srrs if ((stcb == NULL) || (inp == NULL)) { 1832169420Srrs break; 1833169420Srrs } 1834163953Srrs if (sctp_strreset_timer(inp, stcb, net)) { 1835163953Srrs /* no need to unlock on tcb its gone */ 1836163953Srrs goto out_decr; 1837163953Srrs } 1838163953Srrs SCTP_STAT_INCR(sctps_timostrmrst); 1839172090Srrs sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_TMR, SCTP_SO_NOT_LOCKED); 1840163953Srrs break; 1841163953Srrs case SCTP_TIMER_TYPE_ASCONF: 1842169420Srrs if ((stcb == NULL) || (inp == NULL)) { 1843169420Srrs break; 1844169420Srrs } 1845163953Srrs if (sctp_asconf_timer(inp, stcb, net)) { 1846163953Srrs /* no need to unlock on tcb its gone */ 1847163953Srrs goto out_decr; 1848163953Srrs } 1849163953Srrs SCTP_STAT_INCR(sctps_timoasconf); 1850163953Srrs#ifdef SCTP_AUDITING_ENABLED 1851163953Srrs sctp_auditing(4, inp, stcb, net); 1852163953Srrs#endif 1853172090Srrs sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_ASCONF_TMR, SCTP_SO_NOT_LOCKED); 1854163953Srrs break; 1855172091Srrs case SCTP_TIMER_TYPE_PRIM_DELETED: 1856172091Srrs if ((stcb == NULL) || (inp == NULL)) { 1857172091Srrs break; 1858172091Srrs } 1859172156Srrs sctp_delete_prim_timer(inp, stcb, net); 1860172091Srrs SCTP_STAT_INCR(sctps_timodelprim); 1861172091Srrs break; 1862163953Srrs 1863163953Srrs case SCTP_TIMER_TYPE_AUTOCLOSE: 1864169420Srrs if ((stcb == NULL) || (inp == NULL)) { 1865169420Srrs break; 1866169420Srrs } 1867163953Srrs SCTP_STAT_INCR(sctps_timoautoclose); 1868163953Srrs sctp_autoclose_timer(inp, stcb, net); 1869172090Srrs sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_AUTOCLOSE_TMR, SCTP_SO_NOT_LOCKED); 1870163953Srrs did_output = 0; 1871163953Srrs break; 1872163953Srrs case SCTP_TIMER_TYPE_ASOCKILL: 1873169420Srrs if ((stcb == NULL) || (inp == NULL)) { 1874169420Srrs break; 1875169420Srrs } 1876163953Srrs SCTP_STAT_INCR(sctps_timoassockill); 1877163953Srrs /* Can we free it yet? */ 1878163953Srrs SCTP_INP_DECR_REF(inp); 1879283823Stuexen sctp_timer_stop(SCTP_TIMER_TYPE_ASOCKILL, inp, stcb, NULL, 1880283823Stuexen SCTP_FROM_SCTPUTIL + SCTP_LOC_1); 1881237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1882172090Srrs so = SCTP_INP_SO(inp); 1883172090Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 1884172090Srrs SCTP_TCB_UNLOCK(stcb); 1885172090Srrs SCTP_SOCKET_LOCK(so, 1); 1886172090Srrs SCTP_TCB_LOCK(stcb); 1887172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 1888172090Srrs#endif 1889283823Stuexen (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, 1890283823Stuexen SCTP_FROM_SCTPUTIL + SCTP_LOC_2); 1891237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1892172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 1893172090Srrs#endif 1894163953Srrs /* 1895163953Srrs * free asoc, always unlocks (or destroy's) so prevent 1896163953Srrs * duplicate unlock or unlock of a free mtx :-0 1897163953Srrs */ 1898163953Srrs stcb = NULL; 1899163953Srrs goto out_no_decr; 1900163953Srrs case SCTP_TIMER_TYPE_INPKILL: 1901163953Srrs SCTP_STAT_INCR(sctps_timoinpkill); 1902169420Srrs if (inp == NULL) { 1903169420Srrs break; 1904169420Srrs } 1905163953Srrs /* 1906163953Srrs * special case, take away our increment since WE are the 1907163953Srrs * killer 1908163953Srrs */ 1909163953Srrs SCTP_INP_DECR_REF(inp); 1910283823Stuexen sctp_timer_stop(SCTP_TIMER_TYPE_INPKILL, inp, NULL, NULL, 1911283823Stuexen SCTP_FROM_SCTPUTIL + SCTP_LOC_3); 1912169380Srrs sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT, 1913208878Srrs SCTP_CALLED_FROM_INPKILL_TIMER); 1914179180Srrs inp = NULL; 1915163953Srrs goto out_no_decr; 1916163953Srrs default: 1917169420Srrs SCTPDBG(SCTP_DEBUG_TIMER1, "sctp_timeout_handler:unknown timer %d\n", 1918294221Stuexen type); 1919163953Srrs break; 1920228907Stuexen } 1921163953Srrs#ifdef SCTP_AUDITING_ENABLED 1922294221Stuexen sctp_audit_log(0xF1, (uint8_t) type); 1923163953Srrs if (inp) 1924163953Srrs sctp_auditing(5, inp, stcb, net); 1925163953Srrs#endif 1926163953Srrs if ((did_output) && stcb) { 1927163953Srrs /* 1928163953Srrs * Now we need to clean up the control chunk chain if an 1929163953Srrs * ECNE is on it. It must be marked as UNSENT again so next 1930163953Srrs * call will continue to send it until such time that we get 1931163953Srrs * a CWR, to remove it. It is, however, less likely that we 1932163953Srrs * will find a ecn echo on the chain though. 1933163953Srrs */ 1934163953Srrs sctp_fix_ecn_echo(&stcb->asoc); 1935163953Srrs } 1936166023Srrsget_out: 1937163953Srrs if (stcb) { 1938163953Srrs SCTP_TCB_UNLOCK(stcb); 1939163953Srrs } 1940163953Srrsout_decr: 1941163953Srrs if (inp) { 1942163953Srrs SCTP_INP_DECR_REF(inp); 1943163953Srrs } 1944163953Srrsout_no_decr: 1945294221Stuexen SCTPDBG(SCTP_DEBUG_TIMER1, "Timer now complete (type = %d)\n", type); 1946197326Stuexen CURVNET_RESTORE(); 1947163953Srrs} 1948163953Srrs 1949169420Srrsvoid 1950163953Srrssctp_timer_start(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb, 1951163953Srrs struct sctp_nets *net) 1952163953Srrs{ 1953224641Stuexen uint32_t to_ticks; 1954163953Srrs struct sctp_timer *tmr; 1955163953Srrs 1956165647Srrs if ((t_type != SCTP_TIMER_TYPE_ADDR_WQ) && (inp == NULL)) 1957169420Srrs return; 1958163953Srrs 1959163953Srrs tmr = NULL; 1960163953Srrs if (stcb) { 1961163953Srrs SCTP_TCB_LOCK_ASSERT(stcb); 1962163953Srrs } 1963163953Srrs switch (t_type) { 1964170056Srrs case SCTP_TIMER_TYPE_ZERO_COPY: 1965170056Srrs tmr = &inp->sctp_ep.zero_copy_timer; 1966170056Srrs to_ticks = SCTP_ZERO_COPY_TICK_DELAY; 1967170056Srrs break; 1968170181Srrs case SCTP_TIMER_TYPE_ZCOPY_SENDQ: 1969170181Srrs tmr = &inp->sctp_ep.zero_copy_sendq_timer; 1970170181Srrs to_ticks = SCTP_ZERO_COPY_SENDQ_TICK_DELAY; 1971170181Srrs break; 1972163953Srrs case SCTP_TIMER_TYPE_ADDR_WQ: 1973163953Srrs /* Only 1 tick away :-) */ 1974179783Srrs tmr = &SCTP_BASE_INFO(addr_wq_timer); 1975167598Srrs to_ticks = SCTP_ADDRESS_TICK_DELAY; 1976163953Srrs break; 1977163953Srrs case SCTP_TIMER_TYPE_SEND: 1978163953Srrs /* Here we use the RTO timer */ 1979163953Srrs { 1980163953Srrs int rto_val; 1981163953Srrs 1982163953Srrs if ((stcb == NULL) || (net == NULL)) { 1983169420Srrs return; 1984163953Srrs } 1985163953Srrs tmr = &net->rxt_timer; 1986163953Srrs if (net->RTO == 0) { 1987163953Srrs rto_val = stcb->asoc.initial_rto; 1988163953Srrs } else { 1989163953Srrs rto_val = net->RTO; 1990163953Srrs } 1991163953Srrs to_ticks = MSEC_TO_TICKS(rto_val); 1992163953Srrs } 1993163953Srrs break; 1994163953Srrs case SCTP_TIMER_TYPE_INIT: 1995163953Srrs /* 1996163953Srrs * Here we use the INIT timer default usually about 1 1997163953Srrs * minute. 1998163953Srrs */ 1999163953Srrs if ((stcb == NULL) || (net == NULL)) { 2000169420Srrs return; 2001163953Srrs } 2002163953Srrs tmr = &net->rxt_timer; 2003163953Srrs if (net->RTO == 0) { 2004163953Srrs to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto); 2005163953Srrs } else { 2006163953Srrs to_ticks = MSEC_TO_TICKS(net->RTO); 2007163953Srrs } 2008163953Srrs break; 2009163953Srrs case SCTP_TIMER_TYPE_RECV: 2010163953Srrs /* 2011163953Srrs * Here we use the Delayed-Ack timer value from the inp 2012163953Srrs * ususually about 200ms. 2013163953Srrs */ 2014163953Srrs if (stcb == NULL) { 2015169420Srrs return; 2016163953Srrs } 2017163953Srrs tmr = &stcb->asoc.dack_timer; 2018163953Srrs to_ticks = MSEC_TO_TICKS(stcb->asoc.delayed_ack); 2019163953Srrs break; 2020163953Srrs case SCTP_TIMER_TYPE_SHUTDOWN: 2021163953Srrs /* Here we use the RTO of the destination. */ 2022163953Srrs if ((stcb == NULL) || (net == NULL)) { 2023169420Srrs return; 2024163953Srrs } 2025163953Srrs if (net->RTO == 0) { 2026163953Srrs to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto); 2027163953Srrs } else { 2028163953Srrs to_ticks = MSEC_TO_TICKS(net->RTO); 2029163953Srrs } 2030163953Srrs tmr = &net->rxt_timer; 2031163953Srrs break; 2032163953Srrs case SCTP_TIMER_TYPE_HEARTBEAT: 2033163953Srrs /* 2034163953Srrs * the net is used here so that we can add in the RTO. Even 2035163953Srrs * though we use a different timer. We also add the HB timer 2036163953Srrs * PLUS a random jitter. 2037163953Srrs */ 2038283707Stuexen if ((stcb == NULL) || (net == NULL)) { 2039169420Srrs return; 2040169420Srrs } else { 2041163953Srrs uint32_t rndval; 2042224641Stuexen uint32_t jitter; 2043163953Srrs 2044224641Stuexen if ((net->dest_state & SCTP_ADDR_NOHB) && 2045224641Stuexen !(net->dest_state & SCTP_ADDR_UNCONFIRMED)) { 2046224641Stuexen return; 2047163953Srrs } 2048224641Stuexen if (net->RTO == 0) { 2049224641Stuexen to_ticks = stcb->asoc.initial_rto; 2050224641Stuexen } else { 2051224641Stuexen to_ticks = net->RTO; 2052163953Srrs } 2053224641Stuexen rndval = sctp_select_initial_TSN(&inp->sctp_ep); 2054224641Stuexen jitter = rndval % to_ticks; 2055224641Stuexen if (jitter >= (to_ticks >> 1)) { 2056224641Stuexen to_ticks = to_ticks + (jitter - (to_ticks >> 1)); 2057224641Stuexen } else { 2058224641Stuexen to_ticks = to_ticks - jitter; 2059163953Srrs } 2060224641Stuexen if (!(net->dest_state & SCTP_ADDR_UNCONFIRMED) && 2061224641Stuexen !(net->dest_state & SCTP_ADDR_PF)) { 2062224641Stuexen to_ticks += net->heart_beat_delay; 2063163953Srrs } 2064163953Srrs /* 2065163953Srrs * Now we must convert the to_ticks that are now in 2066163953Srrs * ms to ticks. 2067163953Srrs */ 2068163953Srrs to_ticks = MSEC_TO_TICKS(to_ticks); 2069224641Stuexen tmr = &net->hb_timer; 2070163953Srrs } 2071163953Srrs break; 2072163953Srrs case SCTP_TIMER_TYPE_COOKIE: 2073163953Srrs /* 2074163953Srrs * Here we can use the RTO timer from the network since one 2075163953Srrs * RTT was compelete. If a retran happened then we will be 2076163953Srrs * using the RTO initial value. 2077163953Srrs */ 2078163953Srrs if ((stcb == NULL) || (net == NULL)) { 2079169420Srrs return; 2080163953Srrs } 2081163953Srrs if (net->RTO == 0) { 2082163953Srrs to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto); 2083163953Srrs } else { 2084163953Srrs to_ticks = MSEC_TO_TICKS(net->RTO); 2085163953Srrs } 2086163953Srrs tmr = &net->rxt_timer; 2087163953Srrs break; 2088163953Srrs case SCTP_TIMER_TYPE_NEWCOOKIE: 2089163953Srrs /* 2090163953Srrs * nothing needed but the endpoint here ususually about 60 2091163953Srrs * minutes. 2092163953Srrs */ 2093163953Srrs tmr = &inp->sctp_ep.signature_change; 2094163953Srrs to_ticks = inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_SIGNATURE]; 2095163953Srrs break; 2096163953Srrs case SCTP_TIMER_TYPE_ASOCKILL: 2097163953Srrs if (stcb == NULL) { 2098169420Srrs return; 2099163953Srrs } 2100163953Srrs tmr = &stcb->asoc.strreset_timer; 2101163953Srrs to_ticks = MSEC_TO_TICKS(SCTP_ASOC_KILL_TIMEOUT); 2102163953Srrs break; 2103163953Srrs case SCTP_TIMER_TYPE_INPKILL: 2104163953Srrs /* 2105163953Srrs * The inp is setup to die. We re-use the signature_chage 2106163953Srrs * timer since that has stopped and we are in the GONE 2107163953Srrs * state. 2108163953Srrs */ 2109163953Srrs tmr = &inp->sctp_ep.signature_change; 2110163953Srrs to_ticks = MSEC_TO_TICKS(SCTP_INP_KILL_TIMEOUT); 2111163953Srrs break; 2112163953Srrs case SCTP_TIMER_TYPE_PATHMTURAISE: 2113163953Srrs /* 2114163953Srrs * Here we use the value found in the EP for PMTU ususually 2115163953Srrs * about 10 minutes. 2116163953Srrs */ 2117283707Stuexen if ((stcb == NULL) || (net == NULL)) { 2118169420Srrs return; 2119163953Srrs } 2120225635Stuexen if (net->dest_state & SCTP_ADDR_NO_PMTUD) { 2121225635Stuexen return; 2122225635Stuexen } 2123163953Srrs to_ticks = inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_PMTU]; 2124163953Srrs tmr = &net->pmtu_timer; 2125163953Srrs break; 2126163953Srrs case SCTP_TIMER_TYPE_SHUTDOWNACK: 2127163953Srrs /* Here we use the RTO of the destination */ 2128163953Srrs if ((stcb == NULL) || (net == NULL)) { 2129169420Srrs return; 2130163953Srrs } 2131163953Srrs if (net->RTO == 0) { 2132163953Srrs to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto); 2133163953Srrs } else { 2134163953Srrs to_ticks = MSEC_TO_TICKS(net->RTO); 2135163953Srrs } 2136163953Srrs tmr = &net->rxt_timer; 2137163953Srrs break; 2138163953Srrs case SCTP_TIMER_TYPE_SHUTDOWNGUARD: 2139163953Srrs /* 2140163953Srrs * Here we use the endpoints shutdown guard timer usually 2141163953Srrs * about 3 minutes. 2142163953Srrs */ 2143283707Stuexen if (stcb == NULL) { 2144169420Srrs return; 2145163953Srrs } 2146294151Stuexen if (inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_MAXSHUTDOWN] == 0) { 2147294151Stuexen to_ticks = 5 * MSEC_TO_TICKS(stcb->asoc.maxrto); 2148294151Stuexen } else { 2149294151Stuexen to_ticks = inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_MAXSHUTDOWN]; 2150294151Stuexen } 2151163953Srrs tmr = &stcb->asoc.shut_guard_timer; 2152163953Srrs break; 2153163953Srrs case SCTP_TIMER_TYPE_STRRESET: 2154163953Srrs /* 2155171572Srrs * Here the timer comes from the stcb but its value is from 2156171572Srrs * the net's RTO. 2157163953Srrs */ 2158163953Srrs if ((stcb == NULL) || (net == NULL)) { 2159169420Srrs return; 2160163953Srrs } 2161163953Srrs if (net->RTO == 0) { 2162163953Srrs to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto); 2163163953Srrs } else { 2164163953Srrs to_ticks = MSEC_TO_TICKS(net->RTO); 2165163953Srrs } 2166163953Srrs tmr = &stcb->asoc.strreset_timer; 2167163953Srrs break; 2168163953Srrs case SCTP_TIMER_TYPE_ASCONF: 2169163953Srrs /* 2170171572Srrs * Here the timer comes from the stcb but its value is from 2171171572Srrs * the net's RTO. 2172163953Srrs */ 2173163953Srrs if ((stcb == NULL) || (net == NULL)) { 2174169420Srrs return; 2175163953Srrs } 2176163953Srrs if (net->RTO == 0) { 2177163953Srrs to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto); 2178163953Srrs } else { 2179163953Srrs to_ticks = MSEC_TO_TICKS(net->RTO); 2180163953Srrs } 2181163953Srrs tmr = &stcb->asoc.asconf_timer; 2182163953Srrs break; 2183172091Srrs case SCTP_TIMER_TYPE_PRIM_DELETED: 2184172091Srrs if ((stcb == NULL) || (net != NULL)) { 2185172091Srrs return; 2186172091Srrs } 2187172091Srrs to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto); 2188172091Srrs tmr = &stcb->asoc.delete_prim_timer; 2189172091Srrs break; 2190163953Srrs case SCTP_TIMER_TYPE_AUTOCLOSE: 2191163953Srrs if (stcb == NULL) { 2192169420Srrs return; 2193163953Srrs } 2194163953Srrs if (stcb->asoc.sctp_autoclose_ticks == 0) { 2195163953Srrs /* 2196163953Srrs * Really an error since stcb is NOT set to 2197163953Srrs * autoclose 2198163953Srrs */ 2199169420Srrs return; 2200163953Srrs } 2201163953Srrs to_ticks = stcb->asoc.sctp_autoclose_ticks; 2202163953Srrs tmr = &stcb->asoc.autoclose_timer; 2203163953Srrs break; 2204163953Srrs default: 2205169420Srrs SCTPDBG(SCTP_DEBUG_TIMER1, "%s: Unknown timer type %d\n", 2206294174Stuexen __func__, t_type); 2207169420Srrs return; 2208163953Srrs break; 2209228907Stuexen } 2210163953Srrs if ((to_ticks <= 0) || (tmr == NULL)) { 2211169420Srrs SCTPDBG(SCTP_DEBUG_TIMER1, "%s: %d:software error to_ticks:%d tmr:%p not set ??\n", 2212294174Stuexen __func__, t_type, to_ticks, (void *)tmr); 2213169420Srrs return; 2214163953Srrs } 2215165647Srrs if (SCTP_OS_TIMER_PENDING(&tmr->timer)) { 2216163953Srrs /* 2217163953Srrs * we do NOT allow you to have it already running. if it is 2218163953Srrs * we leave the current one up unchanged 2219163953Srrs */ 2220169420Srrs return; 2221163953Srrs } 2222163953Srrs /* At this point we can proceed */ 2223163953Srrs if (t_type == SCTP_TIMER_TYPE_SEND) { 2224163953Srrs stcb->asoc.num_send_timers_up++; 2225163953Srrs } 2226165220Srrs tmr->stopped_from = 0; 2227163953Srrs tmr->type = t_type; 2228163953Srrs tmr->ep = (void *)inp; 2229163953Srrs tmr->tcb = (void *)stcb; 2230163953Srrs tmr->net = (void *)net; 2231163953Srrs tmr->self = (void *)tmr; 2232197326Stuexen tmr->vnet = (void *)curvnet; 2233171943Srrs tmr->ticks = sctp_get_tick_count(); 2234169420Srrs (void)SCTP_OS_TIMER_START(&tmr->timer, to_ticks, sctp_timeout_handler, tmr); 2235169420Srrs return; 2236163953Srrs} 2237163953Srrs 2238169378Srrsvoid 2239163953Srrssctp_timer_stop(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb, 2240165220Srrs struct sctp_nets *net, uint32_t from) 2241163953Srrs{ 2242163953Srrs struct sctp_timer *tmr; 2243163953Srrs 2244163953Srrs if ((t_type != SCTP_TIMER_TYPE_ADDR_WQ) && 2245163953Srrs (inp == NULL)) 2246169378Srrs return; 2247163953Srrs 2248163953Srrs tmr = NULL; 2249163953Srrs if (stcb) { 2250163953Srrs SCTP_TCB_LOCK_ASSERT(stcb); 2251163953Srrs } 2252163953Srrs switch (t_type) { 2253170056Srrs case SCTP_TIMER_TYPE_ZERO_COPY: 2254170056Srrs tmr = &inp->sctp_ep.zero_copy_timer; 2255170056Srrs break; 2256170181Srrs case SCTP_TIMER_TYPE_ZCOPY_SENDQ: 2257170181Srrs tmr = &inp->sctp_ep.zero_copy_sendq_timer; 2258170181Srrs break; 2259163953Srrs case SCTP_TIMER_TYPE_ADDR_WQ: 2260179783Srrs tmr = &SCTP_BASE_INFO(addr_wq_timer); 2261163953Srrs break; 2262163953Srrs case SCTP_TIMER_TYPE_SEND: 2263163953Srrs if ((stcb == NULL) || (net == NULL)) { 2264169378Srrs return; 2265163953Srrs } 2266163953Srrs tmr = &net->rxt_timer; 2267163953Srrs break; 2268163953Srrs case SCTP_TIMER_TYPE_INIT: 2269163953Srrs if ((stcb == NULL) || (net == NULL)) { 2270169378Srrs return; 2271163953Srrs } 2272163953Srrs tmr = &net->rxt_timer; 2273163953Srrs break; 2274163953Srrs case SCTP_TIMER_TYPE_RECV: 2275163953Srrs if (stcb == NULL) { 2276169378Srrs return; 2277163953Srrs } 2278163953Srrs tmr = &stcb->asoc.dack_timer; 2279163953Srrs break; 2280163953Srrs case SCTP_TIMER_TYPE_SHUTDOWN: 2281163953Srrs if ((stcb == NULL) || (net == NULL)) { 2282169378Srrs return; 2283163953Srrs } 2284163953Srrs tmr = &net->rxt_timer; 2285163953Srrs break; 2286163953Srrs case SCTP_TIMER_TYPE_HEARTBEAT: 2287224641Stuexen if ((stcb == NULL) || (net == NULL)) { 2288169378Srrs return; 2289163953Srrs } 2290224641Stuexen tmr = &net->hb_timer; 2291163953Srrs break; 2292163953Srrs case SCTP_TIMER_TYPE_COOKIE: 2293163953Srrs if ((stcb == NULL) || (net == NULL)) { 2294169378Srrs return; 2295163953Srrs } 2296163953Srrs tmr = &net->rxt_timer; 2297163953Srrs break; 2298163953Srrs case SCTP_TIMER_TYPE_NEWCOOKIE: 2299163953Srrs /* nothing needed but the endpoint here */ 2300163953Srrs tmr = &inp->sctp_ep.signature_change; 2301163953Srrs /* 2302163953Srrs * We re-use the newcookie timer for the INP kill timer. We 2303163953Srrs * must assure that we do not kill it by accident. 2304163953Srrs */ 2305163953Srrs break; 2306163953Srrs case SCTP_TIMER_TYPE_ASOCKILL: 2307163953Srrs /* 2308163953Srrs * Stop the asoc kill timer. 2309163953Srrs */ 2310163953Srrs if (stcb == NULL) { 2311169378Srrs return; 2312163953Srrs } 2313163953Srrs tmr = &stcb->asoc.strreset_timer; 2314163953Srrs break; 2315163953Srrs 2316163953Srrs case SCTP_TIMER_TYPE_INPKILL: 2317163953Srrs /* 2318163953Srrs * The inp is setup to die. We re-use the signature_chage 2319163953Srrs * timer since that has stopped and we are in the GONE 2320163953Srrs * state. 2321163953Srrs */ 2322163953Srrs tmr = &inp->sctp_ep.signature_change; 2323163953Srrs break; 2324163953Srrs case SCTP_TIMER_TYPE_PATHMTURAISE: 2325163953Srrs if ((stcb == NULL) || (net == NULL)) { 2326169378Srrs return; 2327163953Srrs } 2328163953Srrs tmr = &net->pmtu_timer; 2329163953Srrs break; 2330163953Srrs case SCTP_TIMER_TYPE_SHUTDOWNACK: 2331163953Srrs if ((stcb == NULL) || (net == NULL)) { 2332169378Srrs return; 2333163953Srrs } 2334163953Srrs tmr = &net->rxt_timer; 2335163953Srrs break; 2336163953Srrs case SCTP_TIMER_TYPE_SHUTDOWNGUARD: 2337163953Srrs if (stcb == NULL) { 2338169378Srrs return; 2339163953Srrs } 2340163953Srrs tmr = &stcb->asoc.shut_guard_timer; 2341163953Srrs break; 2342163953Srrs case SCTP_TIMER_TYPE_STRRESET: 2343163953Srrs if (stcb == NULL) { 2344169378Srrs return; 2345163953Srrs } 2346163953Srrs tmr = &stcb->asoc.strreset_timer; 2347163953Srrs break; 2348163953Srrs case SCTP_TIMER_TYPE_ASCONF: 2349163953Srrs if (stcb == NULL) { 2350169378Srrs return; 2351163953Srrs } 2352163953Srrs tmr = &stcb->asoc.asconf_timer; 2353163953Srrs break; 2354172091Srrs case SCTP_TIMER_TYPE_PRIM_DELETED: 2355172091Srrs if (stcb == NULL) { 2356172091Srrs return; 2357172091Srrs } 2358172091Srrs tmr = &stcb->asoc.delete_prim_timer; 2359172091Srrs break; 2360163953Srrs case SCTP_TIMER_TYPE_AUTOCLOSE: 2361163953Srrs if (stcb == NULL) { 2362169378Srrs return; 2363163953Srrs } 2364163953Srrs tmr = &stcb->asoc.autoclose_timer; 2365163953Srrs break; 2366163953Srrs default: 2367169420Srrs SCTPDBG(SCTP_DEBUG_TIMER1, "%s: Unknown timer type %d\n", 2368294174Stuexen __func__, t_type); 2369163953Srrs break; 2370228907Stuexen } 2371163953Srrs if (tmr == NULL) { 2372169378Srrs return; 2373163953Srrs } 2374163953Srrs if ((tmr->type != t_type) && tmr->type) { 2375163953Srrs /* 2376163953Srrs * Ok we have a timer that is under joint use. Cookie timer 2377163953Srrs * per chance with the SEND timer. We therefore are NOT 2378163953Srrs * running the timer that the caller wants stopped. So just 2379163953Srrs * return. 2380163953Srrs */ 2381169378Srrs return; 2382163953Srrs } 2383169420Srrs if ((t_type == SCTP_TIMER_TYPE_SEND) && (stcb != NULL)) { 2384163953Srrs stcb->asoc.num_send_timers_up--; 2385163953Srrs if (stcb->asoc.num_send_timers_up < 0) { 2386163953Srrs stcb->asoc.num_send_timers_up = 0; 2387163953Srrs } 2388163953Srrs } 2389163953Srrs tmr->self = NULL; 2390165220Srrs tmr->stopped_from = from; 2391169378Srrs (void)SCTP_OS_TIMER_STOP(&tmr->timer); 2392169378Srrs return; 2393163953Srrs} 2394163953Srrs 2395163953Srrsuint32_t 2396163953Srrssctp_calculate_len(struct mbuf *m) 2397163953Srrs{ 2398163953Srrs uint32_t tlen = 0; 2399163953Srrs struct mbuf *at; 2400163953Srrs 2401163953Srrs at = m; 2402163953Srrs while (at) { 2403165647Srrs tlen += SCTP_BUF_LEN(at); 2404165647Srrs at = SCTP_BUF_NEXT(at); 2405163953Srrs } 2406163953Srrs return (tlen); 2407163953Srrs} 2408163953Srrs 2409163953Srrsvoid 2410163953Srrssctp_mtu_size_reset(struct sctp_inpcb *inp, 2411166023Srrs struct sctp_association *asoc, uint32_t mtu) 2412163953Srrs{ 2413163953Srrs /* 2414163953Srrs * Reset the P-MTU size on this association, this involves changing 2415163953Srrs * the asoc MTU, going through ANY chunk+overhead larger than mtu to 2416163953Srrs * allow the DF flag to be cleared. 2417163953Srrs */ 2418163953Srrs struct sctp_tmit_chunk *chk; 2419163953Srrs unsigned int eff_mtu, ovh; 2420163953Srrs 2421163953Srrs asoc->smallest_mtu = mtu; 2422163953Srrs if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) { 2423163953Srrs ovh = SCTP_MIN_OVERHEAD; 2424163953Srrs } else { 2425163953Srrs ovh = SCTP_MIN_V4_OVERHEAD; 2426163953Srrs } 2427163953Srrs eff_mtu = mtu - ovh; 2428163953Srrs TAILQ_FOREACH(chk, &asoc->send_queue, sctp_next) { 2429163953Srrs if (chk->send_size > eff_mtu) { 2430163953Srrs chk->flags |= CHUNK_FLAGS_FRAGMENT_OK; 2431163953Srrs } 2432163953Srrs } 2433163953Srrs TAILQ_FOREACH(chk, &asoc->sent_queue, sctp_next) { 2434163953Srrs if (chk->send_size > eff_mtu) { 2435163953Srrs chk->flags |= CHUNK_FLAGS_FRAGMENT_OK; 2436163953Srrs } 2437163953Srrs } 2438163953Srrs} 2439163953Srrs 2440163953Srrs 2441163953Srrs/* 2442163953Srrs * given an association and starting time of the current RTT period return 2443166675Srrs * RTO in number of msecs net should point to the current network 2444163953Srrs */ 2445218186Srrs 2446163953Srrsuint32_t 2447163953Srrssctp_calculate_rto(struct sctp_tcb *stcb, 2448163953Srrs struct sctp_association *asoc, 2449163953Srrs struct sctp_nets *net, 2450171477Srrs struct timeval *told, 2451219397Srrs int safe, int rtt_from_sack) 2452163953Srrs{ 2453171477Srrs /*- 2454163953Srrs * given an association and the starting time of the current RTT 2455166675Srrs * period (in value1/value2) return RTO in number of msecs. 2456163953Srrs */ 2457219013Stuexen int32_t rtt; /* RTT in ms */ 2458219013Stuexen uint32_t new_rto; 2459163953Srrs int first_measure = 0; 2460171477Srrs struct timeval now, then, *old; 2461163953Srrs 2462171477Srrs /* Copy it out for sparc64 */ 2463171477Srrs if (safe == sctp_align_unsafe_makecopy) { 2464171477Srrs old = &then; 2465171477Srrs memcpy(&then, told, sizeof(struct timeval)); 2466171477Srrs } else if (safe == sctp_align_safe_nocopy) { 2467171477Srrs old = told; 2468171477Srrs } else { 2469171477Srrs /* error */ 2470171477Srrs SCTP_PRINTF("Huh, bad rto calc call\n"); 2471171477Srrs return (0); 2472171477Srrs } 2473163953Srrs /************************/ 2474163953Srrs /* 1. calculate new RTT */ 2475163953Srrs /************************/ 2476163953Srrs /* get the current time */ 2477219057Srrs if (stcb->asoc.use_precise_time) { 2478219057Srrs (void)SCTP_GETPTIME_TIMEVAL(&now); 2479219057Srrs } else { 2480219057Srrs (void)SCTP_GETTIME_TIMEVAL(&now); 2481219057Srrs } 2482219013Stuexen timevalsub(&now, old); 2483219013Stuexen /* store the current RTT in us */ 2484240007Stuexen net->rtt = (uint64_t) 1000000 *(uint64_t) now.tv_sec + 2485240114Stuexen (uint64_t) now.tv_usec; 2486218039Srrs 2487271750Stuexen /* compute rtt in ms */ 2488271750Stuexen rtt = (int32_t) (net->rtt / 1000); 2489219397Srrs if ((asoc->cc_functions.sctp_rtt_calculated) && (rtt_from_sack == SCTP_RTT_FROM_DATA)) { 2490219397Srrs /* 2491219397Srrs * Tell the CC module that a new update has just occurred 2492219397Srrs * from a sack 2493219397Srrs */ 2494219397Srrs (*asoc->cc_functions.sctp_rtt_calculated) (stcb, net, &now); 2495219397Srrs } 2496219397Srrs /* 2497219397Srrs * Do we need to determine the lan? We do this only on sacks i.e. 2498219397Srrs * RTT being determined from data not non-data (HB/INIT->INITACK). 2499219397Srrs */ 2500219397Srrs if ((rtt_from_sack == SCTP_RTT_FROM_DATA) && 2501219013Stuexen (net->lan_type == SCTP_LAN_UNKNOWN)) { 2502219013Stuexen if (net->rtt > SCTP_LOCAL_LAN_RTT) { 2503218186Srrs net->lan_type = SCTP_LAN_INTERNET; 2504218186Srrs } else { 2505218186Srrs net->lan_type = SCTP_LAN_LOCAL; 2506218186Srrs } 2507218186Srrs } 2508163953Srrs /***************************/ 2509163953Srrs /* 2. update RTTVAR & SRTT */ 2510163953Srrs /***************************/ 2511219013Stuexen /*- 2512219013Stuexen * Compute the scaled average lastsa and the 2513219013Stuexen * scaled variance lastsv as described in van Jacobson 2514219013Stuexen * Paper "Congestion Avoidance and Control", Annex A. 2515219013Stuexen * 2516219013Stuexen * (net->lastsa >> SCTP_RTT_SHIFT) is the srtt 2517219013Stuexen * (net->lastsa >> SCTP_RTT_VAR_SHIFT) is the rttvar 2518219013Stuexen */ 2519170642Srrs if (net->RTO_measured) { 2520219013Stuexen rtt -= (net->lastsa >> SCTP_RTT_SHIFT); 2521219013Stuexen net->lastsa += rtt; 2522219013Stuexen if (rtt < 0) { 2523219013Stuexen rtt = -rtt; 2524219013Stuexen } 2525219013Stuexen rtt -= (net->lastsv >> SCTP_RTT_VAR_SHIFT); 2526219013Stuexen net->lastsv += rtt; 2527179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_RTTVAR_LOGGING_ENABLE) { 2528170744Srrs rto_logging(net, SCTP_LOG_RTTVAR); 2529170744Srrs } 2530163953Srrs } else { 2531163953Srrs /* First RTO measurment */ 2532170642Srrs net->RTO_measured = 1; 2533163953Srrs first_measure = 1; 2534219013Stuexen net->lastsa = rtt << SCTP_RTT_SHIFT; 2535219013Stuexen net->lastsv = (rtt / 2) << SCTP_RTT_VAR_SHIFT; 2536179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_RTTVAR_LOGGING_ENABLE) { 2537170744Srrs rto_logging(net, SCTP_LOG_INITIAL_RTT); 2538170744Srrs } 2539163953Srrs } 2540219013Stuexen if (net->lastsv == 0) { 2541219013Stuexen net->lastsv = SCTP_CLOCK_GRANULARITY; 2542219013Stuexen } 2543170428Srrs new_rto = (net->lastsa >> SCTP_RTT_SHIFT) + net->lastsv; 2544163953Srrs if ((new_rto > SCTP_SAT_NETWORK_MIN) && 2545163953Srrs (stcb->asoc.sat_network_lockout == 0)) { 2546163953Srrs stcb->asoc.sat_network = 1; 2547163953Srrs } else if ((!first_measure) && stcb->asoc.sat_network) { 2548163953Srrs stcb->asoc.sat_network = 0; 2549163953Srrs stcb->asoc.sat_network_lockout = 1; 2550163953Srrs } 2551163953Srrs /* bound it, per C6/C7 in Section 5.3.1 */ 2552163953Srrs if (new_rto < stcb->asoc.minrto) { 2553163953Srrs new_rto = stcb->asoc.minrto; 2554163953Srrs } 2555163953Srrs if (new_rto > stcb->asoc.maxrto) { 2556163953Srrs new_rto = stcb->asoc.maxrto; 2557163953Srrs } 2558168124Srrs /* we are now returning the RTO */ 2559168124Srrs return (new_rto); 2560163953Srrs} 2561163953Srrs 2562163953Srrs/* 2563163953Srrs * return a pointer to a contiguous piece of data from the given mbuf chain 2564163953Srrs * starting at 'off' for 'len' bytes. If the desired piece spans more than 2565163953Srrs * one mbuf, a copy is made at 'ptr'. caller must ensure that the buffer size 2566163953Srrs * is >= 'len' returns NULL if there there isn't 'len' bytes in the chain. 2567163953Srrs */ 2568170806Srrscaddr_t 2569163953Srrssctp_m_getptr(struct mbuf *m, int off, int len, uint8_t * in_ptr) 2570163953Srrs{ 2571163953Srrs uint32_t count; 2572163953Srrs uint8_t *ptr; 2573163953Srrs 2574163953Srrs ptr = in_ptr; 2575163953Srrs if ((off < 0) || (len <= 0)) 2576163953Srrs return (NULL); 2577163953Srrs 2578163953Srrs /* find the desired start location */ 2579163953Srrs while ((m != NULL) && (off > 0)) { 2580165647Srrs if (off < SCTP_BUF_LEN(m)) 2581163953Srrs break; 2582165647Srrs off -= SCTP_BUF_LEN(m); 2583165647Srrs m = SCTP_BUF_NEXT(m); 2584163953Srrs } 2585163953Srrs if (m == NULL) 2586163953Srrs return (NULL); 2587163953Srrs 2588163953Srrs /* is the current mbuf large enough (eg. contiguous)? */ 2589165647Srrs if ((SCTP_BUF_LEN(m) - off) >= len) { 2590163953Srrs return (mtod(m, caddr_t)+off); 2591163953Srrs } else { 2592163953Srrs /* else, it spans more than one mbuf, so save a temp copy... */ 2593163953Srrs while ((m != NULL) && (len > 0)) { 2594165647Srrs count = min(SCTP_BUF_LEN(m) - off, len); 2595163953Srrs bcopy(mtod(m, caddr_t)+off, ptr, count); 2596163953Srrs len -= count; 2597163953Srrs ptr += count; 2598163953Srrs off = 0; 2599165647Srrs m = SCTP_BUF_NEXT(m); 2600163953Srrs } 2601163953Srrs if ((m == NULL) && (len > 0)) 2602163953Srrs return (NULL); 2603163953Srrs else 2604163953Srrs return ((caddr_t)in_ptr); 2605163953Srrs } 2606163953Srrs} 2607163953Srrs 2608163953Srrs 2609166023Srrs 2610163953Srrsstruct sctp_paramhdr * 2611163953Srrssctp_get_next_param(struct mbuf *m, 2612163953Srrs int offset, 2613163953Srrs struct sctp_paramhdr *pull, 2614163953Srrs int pull_limit) 2615163953Srrs{ 2616163953Srrs /* This just provides a typed signature to Peter's Pull routine */ 2617163953Srrs return ((struct sctp_paramhdr *)sctp_m_getptr(m, offset, pull_limit, 2618163953Srrs (uint8_t *) pull)); 2619163953Srrs} 2620163953Srrs 2621163953Srrs 2622270354Stuexenstruct mbuf * 2623163953Srrssctp_add_pad_tombuf(struct mbuf *m, int padlen) 2624163953Srrs{ 2625270354Stuexen struct mbuf *m_last; 2626270354Stuexen caddr_t dp; 2627163953Srrs 2628163953Srrs if (padlen > 3) { 2629270354Stuexen return (NULL); 2630163953Srrs } 2631174387Srrs if (padlen <= M_TRAILINGSPACE(m)) { 2632163953Srrs /* 2633163953Srrs * The easy way. We hope the majority of the time we hit 2634163953Srrs * here :) 2635163953Srrs */ 2636270354Stuexen m_last = m; 2637163953Srrs } else { 2638270354Stuexen /* Hard way we must grow the mbuf chain */ 2639270354Stuexen m_last = sctp_get_mbuf_for_msg(padlen, 0, M_NOWAIT, 1, MT_DATA); 2640270354Stuexen if (m_last == NULL) { 2641270354Stuexen return (NULL); 2642163953Srrs } 2643270354Stuexen SCTP_BUF_LEN(m_last) = 0; 2644270354Stuexen SCTP_BUF_NEXT(m_last) = NULL; 2645270354Stuexen SCTP_BUF_NEXT(m) = m_last; 2646163953Srrs } 2647270354Stuexen dp = mtod(m_last, caddr_t)+SCTP_BUF_LEN(m_last); 2648270354Stuexen SCTP_BUF_LEN(m_last) += padlen; 2649270354Stuexen memset(dp, 0, padlen); 2650270354Stuexen return (m_last); 2651163953Srrs} 2652163953Srrs 2653270354Stuexenstruct mbuf * 2654163953Srrssctp_pad_lastmbuf(struct mbuf *m, int padval, struct mbuf *last_mbuf) 2655163953Srrs{ 2656163953Srrs /* find the last mbuf in chain and pad it */ 2657163953Srrs struct mbuf *m_at; 2658163953Srrs 2659270354Stuexen if (last_mbuf != NULL) { 2660163953Srrs return (sctp_add_pad_tombuf(last_mbuf, padval)); 2661163953Srrs } else { 2662236949Stuexen for (m_at = m; m_at; m_at = SCTP_BUF_NEXT(m_at)) { 2663165647Srrs if (SCTP_BUF_NEXT(m_at) == NULL) { 2664163953Srrs return (sctp_add_pad_tombuf(m_at, padval)); 2665163953Srrs } 2666163953Srrs } 2667163953Srrs } 2668270354Stuexen return (NULL); 2669163953Srrs} 2670163953Srrs 2671163953Srrsstatic void 2672235282Stuexensctp_notify_assoc_change(uint16_t state, struct sctp_tcb *stcb, 2673235403Stuexen uint16_t error, struct sctp_abort_chunk *abort, uint8_t from_peer, int so_locked 2674172090Srrs#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING) 2675172090Srrs SCTP_UNUSED 2676172090Srrs#endif 2677172090Srrs) 2678163953Srrs{ 2679163953Srrs struct mbuf *m_notify; 2680163953Srrs struct sctp_assoc_change *sac; 2681163953Srrs struct sctp_queued_to_read *control; 2682235360Stuexen size_t notif_len, abort_len; 2683235081Stuexen unsigned int i; 2684163953Srrs 2685237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2686172090Srrs struct socket *so; 2687172090Srrs 2688172090Srrs#endif 2689172090Srrs 2690294153Stuexen if (stcb == NULL) { 2691294153Stuexen return; 2692294153Stuexen } 2693235402Stuexen if (sctp_stcb_is_feature_on(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVASSOCEVNT)) { 2694235402Stuexen notif_len = sizeof(struct sctp_assoc_change); 2695235402Stuexen if (abort != NULL) { 2696258454Stuexen abort_len = ntohs(abort->ch.chunk_length); 2697235402Stuexen } else { 2698235402Stuexen abort_len = 0; 2699235402Stuexen } 2700235402Stuexen if ((state == SCTP_COMM_UP) || (state == SCTP_RESTART)) { 2701235402Stuexen notif_len += SCTP_ASSOC_SUPPORTS_MAX; 2702235402Stuexen } else if ((state == SCTP_COMM_LOST) || (state == SCTP_CANT_STR_ASSOC)) { 2703235402Stuexen notif_len += abort_len; 2704235402Stuexen } 2705243882Sglebius m_notify = sctp_get_mbuf_for_msg(notif_len, 0, M_NOWAIT, 1, MT_DATA); 2706235402Stuexen if (m_notify == NULL) { 2707235402Stuexen /* Retry with smaller value. */ 2708235402Stuexen notif_len = sizeof(struct sctp_assoc_change); 2709243882Sglebius m_notify = sctp_get_mbuf_for_msg(notif_len, 0, M_NOWAIT, 1, MT_DATA); 2710235402Stuexen if (m_notify == NULL) { 2711235402Stuexen goto set_error; 2712235402Stuexen } 2713235402Stuexen } 2714235402Stuexen SCTP_BUF_NEXT(m_notify) = NULL; 2715235402Stuexen sac = mtod(m_notify, struct sctp_assoc_change *); 2716268432Sdelphij memset(sac, 0, notif_len); 2717235402Stuexen sac->sac_type = SCTP_ASSOC_CHANGE; 2718235402Stuexen sac->sac_flags = 0; 2719235402Stuexen sac->sac_length = sizeof(struct sctp_assoc_change); 2720235402Stuexen sac->sac_state = state; 2721235402Stuexen sac->sac_error = error; 2722235402Stuexen /* XXX verify these stream counts */ 2723235402Stuexen sac->sac_outbound_streams = stcb->asoc.streamoutcnt; 2724235402Stuexen sac->sac_inbound_streams = stcb->asoc.streamincnt; 2725235402Stuexen sac->sac_assoc_id = sctp_get_associd(stcb); 2726235402Stuexen if (notif_len > sizeof(struct sctp_assoc_change)) { 2727235402Stuexen if ((state == SCTP_COMM_UP) || (state == SCTP_RESTART)) { 2728235402Stuexen i = 0; 2729270362Stuexen if (stcb->asoc.prsctp_supported == 1) { 2730235402Stuexen sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_PR; 2731235402Stuexen } 2732270362Stuexen if (stcb->asoc.auth_supported == 1) { 2733235402Stuexen sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_AUTH; 2734235402Stuexen } 2735270362Stuexen if (stcb->asoc.asconf_supported == 1) { 2736235402Stuexen sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_ASCONF; 2737235402Stuexen } 2738235402Stuexen sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_MULTIBUF; 2739270362Stuexen if (stcb->asoc.reconfig_supported == 1) { 2740235402Stuexen sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_RE_CONFIG; 2741235402Stuexen } 2742235402Stuexen sac->sac_length += i; 2743235402Stuexen } else if ((state == SCTP_COMM_LOST) || (state == SCTP_CANT_STR_ASSOC)) { 2744235402Stuexen memcpy(sac->sac_info, abort, abort_len); 2745235402Stuexen sac->sac_length += abort_len; 2746235402Stuexen } 2747235402Stuexen } 2748235402Stuexen SCTP_BUF_LEN(m_notify) = sac->sac_length; 2749235402Stuexen control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination, 2750235402Stuexen 0, 0, stcb->asoc.context, 0, 0, 0, 2751235402Stuexen m_notify); 2752235402Stuexen if (control != NULL) { 2753235402Stuexen control->length = SCTP_BUF_LEN(m_notify); 2754235402Stuexen /* not that we need this */ 2755235402Stuexen control->tail_mbuf = m_notify; 2756235402Stuexen control->spec_flags = M_NOTIFICATION; 2757235402Stuexen sctp_add_to_readq(stcb->sctp_ep, stcb, 2758235402Stuexen control, 2759235402Stuexen &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, 2760235402Stuexen so_locked); 2761235402Stuexen } else { 2762235402Stuexen sctp_m_freem(m_notify); 2763235402Stuexen } 2764235402Stuexen } 2765163953Srrs /* 2766235402Stuexen * For 1-to-1 style sockets, we send up and error when an ABORT 2767235402Stuexen * comes in. 2768163953Srrs */ 2769235402Stuexenset_error: 2770163953Srrs if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 2771163953Srrs (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) && 2772235282Stuexen ((state == SCTP_COMM_LOST) || (state == SCTP_CANT_STR_ASSOC))) { 2773247412Stuexen SOCK_LOCK(stcb->sctp_socket); 2774235403Stuexen if (from_peer) { 2775235403Stuexen if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_WAIT) { 2776235403Stuexen SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ECONNREFUSED); 2777235403Stuexen stcb->sctp_socket->so_error = ECONNREFUSED; 2778235403Stuexen } else { 2779235403Stuexen SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ECONNRESET); 2780235403Stuexen stcb->sctp_socket->so_error = ECONNRESET; 2781235403Stuexen } 2782171943Srrs } else { 2783250756Stuexen if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_WAIT) || 2784250756Stuexen (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_ECHOED)) { 2785250756Stuexen SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ETIMEDOUT); 2786250756Stuexen stcb->sctp_socket->so_error = ETIMEDOUT; 2787250756Stuexen } else { 2788250756Stuexen SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ECONNABORTED); 2789250756Stuexen stcb->sctp_socket->so_error = ECONNABORTED; 2790250756Stuexen } 2791171943Srrs } 2792235402Stuexen } 2793235402Stuexen /* Wake ANY sleepers */ 2794237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2795235402Stuexen so = SCTP_INP_SO(stcb->sctp_ep); 2796235402Stuexen if (!so_locked) { 2797235402Stuexen atomic_add_int(&stcb->asoc.refcnt, 1); 2798235402Stuexen SCTP_TCB_UNLOCK(stcb); 2799235402Stuexen SCTP_SOCKET_LOCK(so, 1); 2800235402Stuexen SCTP_TCB_LOCK(stcb); 2801235402Stuexen atomic_subtract_int(&stcb->asoc.refcnt, 1); 2802235402Stuexen if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) { 2803172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 2804235360Stuexen return; 2805235360Stuexen } 2806235360Stuexen } 2807235402Stuexen#endif 2808235402Stuexen if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 2809235402Stuexen (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) && 2810235402Stuexen ((state == SCTP_COMM_LOST) || (state == SCTP_CANT_STR_ASSOC))) { 2811247412Stuexen socantrcvmore_locked(stcb->sctp_socket); 2812235081Stuexen } 2813235402Stuexen sorwakeup(stcb->sctp_socket); 2814235402Stuexen sowwakeup(stcb->sctp_socket); 2815237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2816235402Stuexen if (!so_locked) { 2817235402Stuexen SCTP_SOCKET_UNLOCK(so, 1); 2818163953Srrs } 2819172090Srrs#endif 2820163953Srrs} 2821163953Srrs 2822163953Srrsstatic void 2823163953Srrssctp_notify_peer_addr_change(struct sctp_tcb *stcb, uint32_t state, 2824283726Stuexen struct sockaddr *sa, uint32_t error, int so_locked 2825283726Stuexen#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING) 2826283726Stuexen SCTP_UNUSED 2827283726Stuexen#endif 2828283726Stuexen) 2829163953Srrs{ 2830163953Srrs struct mbuf *m_notify; 2831163953Srrs struct sctp_paddr_change *spc; 2832163953Srrs struct sctp_queued_to_read *control; 2833163953Srrs 2834228907Stuexen if ((stcb == NULL) || 2835228907Stuexen sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVPADDREVNT)) { 2836163953Srrs /* event not enabled */ 2837163953Srrs return; 2838185694Srrs } 2839243882Sglebius m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_paddr_change), 0, M_NOWAIT, 1, MT_DATA); 2840163953Srrs if (m_notify == NULL) 2841163953Srrs return; 2842165647Srrs SCTP_BUF_LEN(m_notify) = 0; 2843163953Srrs spc = mtod(m_notify, struct sctp_paddr_change *); 2844270353Stuexen memset(spc, 0, sizeof(struct sctp_paddr_change)); 2845163953Srrs spc->spc_type = SCTP_PEER_ADDR_CHANGE; 2846163953Srrs spc->spc_flags = 0; 2847163953Srrs spc->spc_length = sizeof(struct sctp_paddr_change); 2848178251Srrs switch (sa->sa_family) { 2849221328Stuexen#ifdef INET 2850178251Srrs case AF_INET: 2851283699Stuexen#ifdef INET6 2852283699Stuexen if (sctp_is_feature_on(stcb->sctp_ep, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) { 2853283699Stuexen in6_sin_2_v4mapsin6((struct sockaddr_in *)sa, 2854283699Stuexen (struct sockaddr_in6 *)&spc->spc_aaddr); 2855283699Stuexen } else { 2856283699Stuexen memcpy(&spc->spc_aaddr, sa, sizeof(struct sockaddr_in)); 2857283699Stuexen } 2858283699Stuexen#else 2859163953Srrs memcpy(&spc->spc_aaddr, sa, sizeof(struct sockaddr_in)); 2860283699Stuexen#endif 2861178251Srrs break; 2862221328Stuexen#endif 2863178251Srrs#ifdef INET6 2864178251Srrs case AF_INET6: 2865178251Srrs { 2866178251Srrs struct sockaddr_in6 *sin6; 2867166675Srrs 2868178251Srrs memcpy(&spc->spc_aaddr, sa, sizeof(struct sockaddr_in6)); 2869166675Srrs 2870178251Srrs sin6 = (struct sockaddr_in6 *)&spc->spc_aaddr; 2871178251Srrs if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr)) { 2872178251Srrs if (sin6->sin6_scope_id == 0) { 2873178251Srrs /* recover scope_id for user */ 2874178251Srrs (void)sa6_recoverscope(sin6); 2875178251Srrs } else { 2876178251Srrs /* clear embedded scope_id for user */ 2877178251Srrs in6_clearscope(&sin6->sin6_addr); 2878178251Srrs } 2879167598Srrs } 2880178251Srrs break; 2881166675Srrs } 2882178251Srrs#endif 2883178251Srrs default: 2884178251Srrs /* TSNH */ 2885178251Srrs break; 2886163953Srrs } 2887163953Srrs spc->spc_state = state; 2888163953Srrs spc->spc_error = error; 2889163953Srrs spc->spc_assoc_id = sctp_get_associd(stcb); 2890163953Srrs 2891165647Srrs SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_paddr_change); 2892165647Srrs SCTP_BUF_NEXT(m_notify) = NULL; 2893163953Srrs 2894163953Srrs /* append to socket */ 2895163953Srrs control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination, 2896228653Stuexen 0, 0, stcb->asoc.context, 0, 0, 0, 2897163953Srrs m_notify); 2898163953Srrs if (control == NULL) { 2899163953Srrs /* no memory */ 2900163953Srrs sctp_m_freem(m_notify); 2901163953Srrs return; 2902163953Srrs } 2903165647Srrs control->length = SCTP_BUF_LEN(m_notify); 2904165647Srrs control->spec_flags = M_NOTIFICATION; 2905163953Srrs /* not that we need this */ 2906163953Srrs control->tail_mbuf = m_notify; 2907163953Srrs sctp_add_to_readq(stcb->sctp_ep, stcb, 2908163953Srrs control, 2909195918Srrs &stcb->sctp_socket->so_rcv, 1, 2910195918Srrs SCTP_READ_LOCK_NOT_HELD, 2911283726Stuexen so_locked); 2912163953Srrs} 2913163953Srrs 2914163953Srrs 2915163953Srrsstatic void 2916235416Stuexensctp_notify_send_failed(struct sctp_tcb *stcb, uint8_t sent, uint32_t error, 2917172090Srrs struct sctp_tmit_chunk *chk, int so_locked 2918172090Srrs#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING) 2919172090Srrs SCTP_UNUSED 2920172090Srrs#endif 2921172090Srrs) 2922163953Srrs{ 2923185694Srrs struct mbuf *m_notify; 2924163953Srrs struct sctp_send_failed *ssf; 2925235075Stuexen struct sctp_send_failed_event *ssfe; 2926163953Srrs struct sctp_queued_to_read *control; 2927163953Srrs int length; 2928163953Srrs 2929228907Stuexen if ((stcb == NULL) || 2930235075Stuexen (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVSENDFAILEVNT) && 2931235075Stuexen sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVNSENDFAILEVNT))) { 2932163953Srrs /* event not enabled */ 2933163953Srrs return; 2934185694Srrs } 2935235075Stuexen if (sctp_stcb_is_feature_on(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVNSENDFAILEVNT)) { 2936235075Stuexen length = sizeof(struct sctp_send_failed_event); 2937235075Stuexen } else { 2938235075Stuexen length = sizeof(struct sctp_send_failed); 2939235075Stuexen } 2940243882Sglebius m_notify = sctp_get_mbuf_for_msg(length, 0, M_NOWAIT, 1, MT_DATA); 2941163953Srrs if (m_notify == NULL) 2942163953Srrs /* no space left */ 2943163953Srrs return; 2944165647Srrs SCTP_BUF_LEN(m_notify) = 0; 2945235075Stuexen if (sctp_stcb_is_feature_on(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVNSENDFAILEVNT)) { 2946235075Stuexen ssfe = mtod(m_notify, struct sctp_send_failed_event *); 2947268432Sdelphij memset(ssfe, 0, length); 2948235075Stuexen ssfe->ssfe_type = SCTP_SEND_FAILED_EVENT; 2949235416Stuexen if (sent) { 2950235416Stuexen ssfe->ssfe_flags = SCTP_DATA_SENT; 2951235416Stuexen } else { 2952235075Stuexen ssfe->ssfe_flags = SCTP_DATA_UNSENT; 2953235416Stuexen } 2954268432Sdelphij length += chk->send_size; 2955268432Sdelphij length -= sizeof(struct sctp_data_chunk); 2956235075Stuexen ssfe->ssfe_length = length; 2957235075Stuexen ssfe->ssfe_error = error; 2958235075Stuexen /* not exactly what the user sent in, but should be close :) */ 2959235075Stuexen ssfe->ssfe_info.snd_sid = chk->rec.data.stream_number; 2960235075Stuexen ssfe->ssfe_info.snd_flags = chk->rec.data.rcv_flags; 2961235075Stuexen ssfe->ssfe_info.snd_ppid = chk->rec.data.payloadtype; 2962235075Stuexen ssfe->ssfe_info.snd_context = chk->rec.data.context; 2963235075Stuexen ssfe->ssfe_info.snd_assoc_id = sctp_get_associd(stcb); 2964235075Stuexen ssfe->ssfe_assoc_id = sctp_get_associd(stcb); 2965235075Stuexen SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_send_failed_event); 2966235075Stuexen } else { 2967235075Stuexen ssf = mtod(m_notify, struct sctp_send_failed *); 2968268432Sdelphij memset(ssf, 0, length); 2969235075Stuexen ssf->ssf_type = SCTP_SEND_FAILED; 2970235416Stuexen if (sent) { 2971235416Stuexen ssf->ssf_flags = SCTP_DATA_SENT; 2972235416Stuexen } else { 2973235075Stuexen ssf->ssf_flags = SCTP_DATA_UNSENT; 2974235416Stuexen } 2975268432Sdelphij length += chk->send_size; 2976268432Sdelphij length -= sizeof(struct sctp_data_chunk); 2977235075Stuexen ssf->ssf_length = length; 2978235075Stuexen ssf->ssf_error = error; 2979235075Stuexen /* not exactly what the user sent in, but should be close :) */ 2980235075Stuexen bzero(&ssf->ssf_info, sizeof(ssf->ssf_info)); 2981235075Stuexen ssf->ssf_info.sinfo_stream = chk->rec.data.stream_number; 2982235075Stuexen ssf->ssf_info.sinfo_ssn = chk->rec.data.stream_seq; 2983235075Stuexen ssf->ssf_info.sinfo_flags = chk->rec.data.rcv_flags; 2984235075Stuexen ssf->ssf_info.sinfo_ppid = chk->rec.data.payloadtype; 2985235075Stuexen ssf->ssf_info.sinfo_context = chk->rec.data.context; 2986235075Stuexen ssf->ssf_info.sinfo_assoc_id = sctp_get_associd(stcb); 2987235075Stuexen ssf->ssf_assoc_id = sctp_get_associd(stcb); 2988235075Stuexen SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_send_failed); 2989235075Stuexen } 2990185694Srrs if (chk->data) { 2991185694Srrs /* 2992185694Srrs * trim off the sctp chunk header(it should be there) 2993185694Srrs */ 2994185694Srrs if (chk->send_size >= sizeof(struct sctp_data_chunk)) { 2995185694Srrs m_adj(chk->data, sizeof(struct sctp_data_chunk)); 2996185694Srrs sctp_mbuf_crush(chk->data); 2997185694Srrs chk->send_size -= sizeof(struct sctp_data_chunk); 2998185694Srrs } 2999185694Srrs } 3000196260Stuexen SCTP_BUF_NEXT(m_notify) = chk->data; 3001163953Srrs /* Steal off the mbuf */ 3002163953Srrs chk->data = NULL; 3003163953Srrs /* 3004163953Srrs * For this case, we check the actual socket buffer, since the assoc 3005163953Srrs * is going away we don't want to overfill the socket buffer for a 3006163953Srrs * non-reader 3007163953Srrs */ 3008165647Srrs if (sctp_sbspace_failedmsgs(&stcb->sctp_socket->so_rcv) < SCTP_BUF_LEN(m_notify)) { 3009163953Srrs sctp_m_freem(m_notify); 3010163953Srrs return; 3011163953Srrs } 3012163953Srrs /* append to socket */ 3013163953Srrs control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination, 3014228653Stuexen 0, 0, stcb->asoc.context, 0, 0, 0, 3015163953Srrs m_notify); 3016163953Srrs if (control == NULL) { 3017163953Srrs /* no memory */ 3018163953Srrs sctp_m_freem(m_notify); 3019163953Srrs return; 3020163953Srrs } 3021165647Srrs control->spec_flags = M_NOTIFICATION; 3022163953Srrs sctp_add_to_readq(stcb->sctp_ep, stcb, 3023163953Srrs control, 3024195918Srrs &stcb->sctp_socket->so_rcv, 1, 3025195918Srrs SCTP_READ_LOCK_NOT_HELD, 3026195918Srrs so_locked); 3027163953Srrs} 3028163953Srrs 3029163953Srrs 3030163953Srrsstatic void 3031163953Srrssctp_notify_send_failed2(struct sctp_tcb *stcb, uint32_t error, 3032172090Srrs struct sctp_stream_queue_pending *sp, int so_locked 3033172090Srrs#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING) 3034172090Srrs SCTP_UNUSED 3035172090Srrs#endif 3036172090Srrs) 3037163953Srrs{ 3038163953Srrs struct mbuf *m_notify; 3039163953Srrs struct sctp_send_failed *ssf; 3040235075Stuexen struct sctp_send_failed_event *ssfe; 3041163953Srrs struct sctp_queued_to_read *control; 3042163953Srrs int length; 3043163953Srrs 3044228907Stuexen if ((stcb == NULL) || 3045235075Stuexen (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVSENDFAILEVNT) && 3046235075Stuexen sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVNSENDFAILEVNT))) { 3047163953Srrs /* event not enabled */ 3048163953Srrs return; 3049185694Srrs } 3050235075Stuexen if (sctp_stcb_is_feature_on(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVNSENDFAILEVNT)) { 3051235075Stuexen length = sizeof(struct sctp_send_failed_event); 3052235075Stuexen } else { 3053235075Stuexen length = sizeof(struct sctp_send_failed); 3054235075Stuexen } 3055243882Sglebius m_notify = sctp_get_mbuf_for_msg(length, 0, M_NOWAIT, 1, MT_DATA); 3056235075Stuexen if (m_notify == NULL) { 3057163953Srrs /* no space left */ 3058163953Srrs return; 3059235075Stuexen } 3060165647Srrs SCTP_BUF_LEN(m_notify) = 0; 3061235075Stuexen if (sctp_stcb_is_feature_on(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVNSENDFAILEVNT)) { 3062235075Stuexen ssfe = mtod(m_notify, struct sctp_send_failed_event *); 3063268432Sdelphij memset(ssfe, 0, length); 3064238458Stuexen ssfe->ssfe_type = SCTP_SEND_FAILED_EVENT; 3065235416Stuexen ssfe->ssfe_flags = SCTP_DATA_UNSENT; 3066268432Sdelphij length += sp->length; 3067235075Stuexen ssfe->ssfe_length = length; 3068235075Stuexen ssfe->ssfe_error = error; 3069235075Stuexen /* not exactly what the user sent in, but should be close :) */ 3070235075Stuexen ssfe->ssfe_info.snd_sid = sp->stream; 3071235075Stuexen if (sp->some_taken) { 3072235075Stuexen ssfe->ssfe_info.snd_flags = SCTP_DATA_LAST_FRAG; 3073235075Stuexen } else { 3074235075Stuexen ssfe->ssfe_info.snd_flags = SCTP_DATA_NOT_FRAG; 3075235075Stuexen } 3076235075Stuexen ssfe->ssfe_info.snd_ppid = sp->ppid; 3077235075Stuexen ssfe->ssfe_info.snd_context = sp->context; 3078235075Stuexen ssfe->ssfe_info.snd_assoc_id = sctp_get_associd(stcb); 3079235075Stuexen ssfe->ssfe_assoc_id = sctp_get_associd(stcb); 3080235075Stuexen SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_send_failed_event); 3081180387Srrs } else { 3082235075Stuexen ssf = mtod(m_notify, struct sctp_send_failed *); 3083268432Sdelphij memset(ssf, 0, length); 3084235075Stuexen ssf->ssf_type = SCTP_SEND_FAILED; 3085235416Stuexen ssf->ssf_flags = SCTP_DATA_UNSENT; 3086268432Sdelphij length += sp->length; 3087235075Stuexen ssf->ssf_length = length; 3088235075Stuexen ssf->ssf_error = error; 3089235075Stuexen /* not exactly what the user sent in, but should be close :) */ 3090235075Stuexen ssf->ssf_info.sinfo_stream = sp->stream; 3091242627Stuexen ssf->ssf_info.sinfo_ssn = 0; 3092235075Stuexen if (sp->some_taken) { 3093235075Stuexen ssf->ssf_info.sinfo_flags = SCTP_DATA_LAST_FRAG; 3094235075Stuexen } else { 3095235075Stuexen ssf->ssf_info.sinfo_flags = SCTP_DATA_NOT_FRAG; 3096235075Stuexen } 3097235075Stuexen ssf->ssf_info.sinfo_ppid = sp->ppid; 3098235075Stuexen ssf->ssf_info.sinfo_context = sp->context; 3099235075Stuexen ssf->ssf_info.sinfo_assoc_id = sctp_get_associd(stcb); 3100235075Stuexen ssf->ssf_assoc_id = sctp_get_associd(stcb); 3101235075Stuexen SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_send_failed); 3102180387Srrs } 3103165647Srrs SCTP_BUF_NEXT(m_notify) = sp->data; 3104163953Srrs 3105163953Srrs /* Steal off the mbuf */ 3106163953Srrs sp->data = NULL; 3107163953Srrs /* 3108163953Srrs * For this case, we check the actual socket buffer, since the assoc 3109163953Srrs * is going away we don't want to overfill the socket buffer for a 3110163953Srrs * non-reader 3111163953Srrs */ 3112165647Srrs if (sctp_sbspace_failedmsgs(&stcb->sctp_socket->so_rcv) < SCTP_BUF_LEN(m_notify)) { 3113163953Srrs sctp_m_freem(m_notify); 3114163953Srrs return; 3115163953Srrs } 3116163953Srrs /* append to socket */ 3117163953Srrs control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination, 3118228653Stuexen 0, 0, stcb->asoc.context, 0, 0, 0, 3119163953Srrs m_notify); 3120163953Srrs if (control == NULL) { 3121163953Srrs /* no memory */ 3122163953Srrs sctp_m_freem(m_notify); 3123163953Srrs return; 3124163953Srrs } 3125165647Srrs control->spec_flags = M_NOTIFICATION; 3126163953Srrs sctp_add_to_readq(stcb->sctp_ep, stcb, 3127163953Srrs control, 3128195918Srrs &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, so_locked); 3129163953Srrs} 3130163953Srrs 3131163953Srrs 3132163953Srrs 3133163953Srrsstatic void 3134228653Stuexensctp_notify_adaptation_layer(struct sctp_tcb *stcb) 3135163953Srrs{ 3136163953Srrs struct mbuf *m_notify; 3137163953Srrs struct sctp_adaptation_event *sai; 3138163953Srrs struct sctp_queued_to_read *control; 3139163953Srrs 3140228907Stuexen if ((stcb == NULL) || 3141228907Stuexen sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_ADAPTATIONEVNT)) { 3142163953Srrs /* event not enabled */ 3143163953Srrs return; 3144185694Srrs } 3145243882Sglebius m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_adaption_event), 0, M_NOWAIT, 1, MT_DATA); 3146163953Srrs if (m_notify == NULL) 3147163953Srrs /* no space left */ 3148163953Srrs return; 3149165647Srrs SCTP_BUF_LEN(m_notify) = 0; 3150163953Srrs sai = mtod(m_notify, struct sctp_adaptation_event *); 3151268432Sdelphij memset(sai, 0, sizeof(struct sctp_adaptation_event)); 3152163953Srrs sai->sai_type = SCTP_ADAPTATION_INDICATION; 3153163953Srrs sai->sai_flags = 0; 3154163953Srrs sai->sai_length = sizeof(struct sctp_adaptation_event); 3155171990Srrs sai->sai_adaptation_ind = stcb->asoc.peers_adaptation; 3156163953Srrs sai->sai_assoc_id = sctp_get_associd(stcb); 3157163953Srrs 3158165647Srrs SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_adaptation_event); 3159165647Srrs SCTP_BUF_NEXT(m_notify) = NULL; 3160163953Srrs 3161163953Srrs /* append to socket */ 3162163953Srrs control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination, 3163228653Stuexen 0, 0, stcb->asoc.context, 0, 0, 0, 3164163953Srrs m_notify); 3165163953Srrs if (control == NULL) { 3166163953Srrs /* no memory */ 3167163953Srrs sctp_m_freem(m_notify); 3168163953Srrs return; 3169163953Srrs } 3170165647Srrs control->length = SCTP_BUF_LEN(m_notify); 3171165647Srrs control->spec_flags = M_NOTIFICATION; 3172163953Srrs /* not that we need this */ 3173163953Srrs control->tail_mbuf = m_notify; 3174163953Srrs sctp_add_to_readq(stcb->sctp_ep, stcb, 3175163953Srrs control, 3176195918Srrs &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED); 3177163953Srrs} 3178163953Srrs 3179164085Srrs/* This always must be called with the read-queue LOCKED in the INP */ 3180196260Stuexenstatic void 3181171858Srrssctp_notify_partial_delivery_indication(struct sctp_tcb *stcb, uint32_t error, 3182196260Stuexen uint32_t val, int so_locked 3183196260Stuexen#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING) 3184196260Stuexen SCTP_UNUSED 3185196260Stuexen#endif 3186196260Stuexen) 3187163953Srrs{ 3188163953Srrs struct mbuf *m_notify; 3189163953Srrs struct sctp_pdapi_event *pdapi; 3190163953Srrs struct sctp_queued_to_read *control; 3191164085Srrs struct sockbuf *sb; 3192163953Srrs 3193228907Stuexen if ((stcb == NULL) || 3194228907Stuexen sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_PDAPIEVNT)) { 3195163953Srrs /* event not enabled */ 3196163953Srrs return; 3197185694Srrs } 3198209289Stuexen if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_CANT_READ) { 3199209289Stuexen return; 3200209289Stuexen } 3201243882Sglebius m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_pdapi_event), 0, M_NOWAIT, 1, MT_DATA); 3202163953Srrs if (m_notify == NULL) 3203163953Srrs /* no space left */ 3204163953Srrs return; 3205165647Srrs SCTP_BUF_LEN(m_notify) = 0; 3206163953Srrs pdapi = mtod(m_notify, struct sctp_pdapi_event *); 3207268432Sdelphij memset(pdapi, 0, sizeof(struct sctp_pdapi_event)); 3208163953Srrs pdapi->pdapi_type = SCTP_PARTIAL_DELIVERY_EVENT; 3209163953Srrs pdapi->pdapi_flags = 0; 3210163953Srrs pdapi->pdapi_length = sizeof(struct sctp_pdapi_event); 3211163953Srrs pdapi->pdapi_indication = error; 3212168943Srrs pdapi->pdapi_stream = (val >> 16); 3213168943Srrs pdapi->pdapi_seq = (val & 0x0000ffff); 3214163953Srrs pdapi->pdapi_assoc_id = sctp_get_associd(stcb); 3215163953Srrs 3216165647Srrs SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_pdapi_event); 3217165647Srrs SCTP_BUF_NEXT(m_notify) = NULL; 3218164085Srrs control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination, 3219228653Stuexen 0, 0, stcb->asoc.context, 0, 0, 0, 3220164085Srrs m_notify); 3221164085Srrs if (control == NULL) { 3222164085Srrs /* no memory */ 3223164085Srrs sctp_m_freem(m_notify); 3224164085Srrs return; 3225164085Srrs } 3226165647Srrs control->spec_flags = M_NOTIFICATION; 3227165647Srrs control->length = SCTP_BUF_LEN(m_notify); 3228164085Srrs /* not that we need this */ 3229164085Srrs control->tail_mbuf = m_notify; 3230164085Srrs control->held_length = 0; 3231164085Srrs control->length = 0; 3232164085Srrs sb = &stcb->sctp_socket->so_rcv; 3233179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) { 3234170744Srrs sctp_sblog(sb, control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBALLOC, SCTP_BUF_LEN(m_notify)); 3235170744Srrs } 3236164085Srrs sctp_sballoc(stcb, sb, m_notify); 3237179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) { 3238170744Srrs sctp_sblog(sb, control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBRESULT, 0); 3239170744Srrs } 3240165647Srrs atomic_add_int(&control->length, SCTP_BUF_LEN(m_notify)); 3241164085Srrs control->end_added = 1; 3242164085Srrs if (stcb->asoc.control_pdapi) 3243164085Srrs TAILQ_INSERT_AFTER(&stcb->sctp_ep->read_queue, stcb->asoc.control_pdapi, control, next); 3244164085Srrs else { 3245164085Srrs /* we really should not see this case */ 3246164085Srrs TAILQ_INSERT_TAIL(&stcb->sctp_ep->read_queue, control, next); 3247164085Srrs } 3248164085Srrs if (stcb->sctp_ep && stcb->sctp_socket) { 3249164085Srrs /* This should always be the case */ 3250237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 3251196260Stuexen struct socket *so; 3252196260Stuexen 3253196260Stuexen so = SCTP_INP_SO(stcb->sctp_ep); 3254196260Stuexen if (!so_locked) { 3255196260Stuexen atomic_add_int(&stcb->asoc.refcnt, 1); 3256196260Stuexen SCTP_TCB_UNLOCK(stcb); 3257196260Stuexen SCTP_SOCKET_LOCK(so, 1); 3258196260Stuexen SCTP_TCB_LOCK(stcb); 3259196260Stuexen atomic_subtract_int(&stcb->asoc.refcnt, 1); 3260196260Stuexen if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) { 3261196260Stuexen SCTP_SOCKET_UNLOCK(so, 1); 3262196260Stuexen return; 3263196260Stuexen } 3264196260Stuexen } 3265196260Stuexen#endif 3266163996Srrs sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket); 3267237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 3268196260Stuexen if (!so_locked) { 3269196260Stuexen SCTP_SOCKET_UNLOCK(so, 1); 3270196260Stuexen } 3271196260Stuexen#endif 3272163953Srrs } 3273163953Srrs} 3274163953Srrs 3275163953Srrsstatic void 3276163953Srrssctp_notify_shutdown_event(struct sctp_tcb *stcb) 3277163953Srrs{ 3278163953Srrs struct mbuf *m_notify; 3279163953Srrs struct sctp_shutdown_event *sse; 3280163953Srrs struct sctp_queued_to_read *control; 3281163953Srrs 3282163953Srrs /* 3283163953Srrs * For TCP model AND UDP connected sockets we will send an error up 3284163953Srrs * when an SHUTDOWN completes 3285163953Srrs */ 3286163953Srrs if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 3287163953Srrs (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) { 3288163953Srrs /* mark socket closed for read/write and wakeup! */ 3289237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 3290172090Srrs struct socket *so; 3291172090Srrs 3292172090Srrs so = SCTP_INP_SO(stcb->sctp_ep); 3293172090Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 3294172090Srrs SCTP_TCB_UNLOCK(stcb); 3295172090Srrs SCTP_SOCKET_LOCK(so, 1); 3296172090Srrs SCTP_TCB_LOCK(stcb); 3297172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 3298172090Srrs if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) { 3299172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 3300172090Srrs return; 3301172090Srrs } 3302172090Srrs#endif 3303163953Srrs socantsendmore(stcb->sctp_socket); 3304237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 3305172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 3306172090Srrs#endif 3307163953Srrs } 3308223132Stuexen if (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT)) { 3309163953Srrs /* event not enabled */ 3310163953Srrs return; 3311185694Srrs } 3312243882Sglebius m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_shutdown_event), 0, M_NOWAIT, 1, MT_DATA); 3313163953Srrs if (m_notify == NULL) 3314163953Srrs /* no space left */ 3315163953Srrs return; 3316163953Srrs sse = mtod(m_notify, struct sctp_shutdown_event *); 3317268432Sdelphij memset(sse, 0, sizeof(struct sctp_shutdown_event)); 3318163953Srrs sse->sse_type = SCTP_SHUTDOWN_EVENT; 3319163953Srrs sse->sse_flags = 0; 3320163953Srrs sse->sse_length = sizeof(struct sctp_shutdown_event); 3321163953Srrs sse->sse_assoc_id = sctp_get_associd(stcb); 3322163953Srrs 3323165647Srrs SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_shutdown_event); 3324165647Srrs SCTP_BUF_NEXT(m_notify) = NULL; 3325163953Srrs 3326163953Srrs /* append to socket */ 3327163953Srrs control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination, 3328228653Stuexen 0, 0, stcb->asoc.context, 0, 0, 0, 3329163953Srrs m_notify); 3330163953Srrs if (control == NULL) { 3331163953Srrs /* no memory */ 3332163953Srrs sctp_m_freem(m_notify); 3333163953Srrs return; 3334163953Srrs } 3335165647Srrs control->spec_flags = M_NOTIFICATION; 3336165647Srrs control->length = SCTP_BUF_LEN(m_notify); 3337163953Srrs /* not that we need this */ 3338163953Srrs control->tail_mbuf = m_notify; 3339163953Srrs sctp_add_to_readq(stcb->sctp_ep, stcb, 3340163953Srrs control, 3341195918Srrs &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED); 3342163953Srrs} 3343163953Srrs 3344163953Srrsstatic void 3345185694Srrssctp_notify_sender_dry_event(struct sctp_tcb *stcb, 3346185694Srrs int so_locked 3347185694Srrs#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING) 3348185694Srrs SCTP_UNUSED 3349185694Srrs#endif 3350185694Srrs) 3351185694Srrs{ 3352185694Srrs struct mbuf *m_notify; 3353185694Srrs struct sctp_sender_dry_event *event; 3354185694Srrs struct sctp_queued_to_read *control; 3355185694Srrs 3356228907Stuexen if ((stcb == NULL) || 3357228907Stuexen sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_DRYEVNT)) { 3358185694Srrs /* event not enabled */ 3359185694Srrs return; 3360185694Srrs } 3361243882Sglebius m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_sender_dry_event), 0, M_NOWAIT, 1, MT_DATA); 3362185694Srrs if (m_notify == NULL) { 3363185694Srrs /* no space left */ 3364185694Srrs return; 3365185694Srrs } 3366185694Srrs SCTP_BUF_LEN(m_notify) = 0; 3367185694Srrs event = mtod(m_notify, struct sctp_sender_dry_event *); 3368268432Sdelphij memset(event, 0, sizeof(struct sctp_sender_dry_event)); 3369185694Srrs event->sender_dry_type = SCTP_SENDER_DRY_EVENT; 3370185694Srrs event->sender_dry_flags = 0; 3371185694Srrs event->sender_dry_length = sizeof(struct sctp_sender_dry_event); 3372185694Srrs event->sender_dry_assoc_id = sctp_get_associd(stcb); 3373185694Srrs 3374185694Srrs SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_sender_dry_event); 3375185694Srrs SCTP_BUF_NEXT(m_notify) = NULL; 3376185694Srrs 3377185694Srrs /* append to socket */ 3378185694Srrs control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination, 3379228653Stuexen 0, 0, stcb->asoc.context, 0, 0, 0, 3380228653Stuexen m_notify); 3381185694Srrs if (control == NULL) { 3382185694Srrs /* no memory */ 3383185694Srrs sctp_m_freem(m_notify); 3384185694Srrs return; 3385185694Srrs } 3386185694Srrs control->length = SCTP_BUF_LEN(m_notify); 3387185694Srrs control->spec_flags = M_NOTIFICATION; 3388185694Srrs /* not that we need this */ 3389185694Srrs control->tail_mbuf = m_notify; 3390185694Srrs sctp_add_to_readq(stcb->sctp_ep, stcb, control, 3391195918Srrs &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, so_locked); 3392185694Srrs} 3393185694Srrs 3394188854Srrs 3395233660Srrsvoid 3396233660Srrssctp_notify_stream_reset_add(struct sctp_tcb *stcb, uint16_t numberin, uint16_t numberout, int flag) 3397188854Srrs{ 3398188854Srrs struct mbuf *m_notify; 3399188854Srrs struct sctp_queued_to_read *control; 3400233660Srrs struct sctp_stream_change_event *stradd; 3401188854Srrs 3402235091Stuexen if ((stcb == NULL) || 3403235091Stuexen (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_STREAM_CHANGEEVNT))) { 3404188854Srrs /* event not enabled */ 3405188854Srrs return; 3406188854Srrs } 3407233660Srrs if ((stcb->asoc.peer_req_out) && flag) { 3408233660Srrs /* Peer made the request, don't tell the local user */ 3409233660Srrs stcb->asoc.peer_req_out = 0; 3410233660Srrs return; 3411233660Srrs } 3412233660Srrs stcb->asoc.peer_req_out = 0; 3413268432Sdelphij m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_stream_change_event), 0, M_NOWAIT, 1, MT_DATA); 3414188854Srrs if (m_notify == NULL) 3415188854Srrs /* no space left */ 3416188854Srrs return; 3417188854Srrs SCTP_BUF_LEN(m_notify) = 0; 3418233660Srrs stradd = mtod(m_notify, struct sctp_stream_change_event *); 3419268432Sdelphij memset(stradd, 0, sizeof(struct sctp_stream_change_event)); 3420233660Srrs stradd->strchange_type = SCTP_STREAM_CHANGE_EVENT; 3421233660Srrs stradd->strchange_flags = flag; 3422268432Sdelphij stradd->strchange_length = sizeof(struct sctp_stream_change_event); 3423233660Srrs stradd->strchange_assoc_id = sctp_get_associd(stcb); 3424233660Srrs stradd->strchange_instrms = numberin; 3425233660Srrs stradd->strchange_outstrms = numberout; 3426268432Sdelphij SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_stream_change_event); 3427233660Srrs SCTP_BUF_NEXT(m_notify) = NULL; 3428233660Srrs if (sctp_sbspace(&stcb->asoc, &stcb->sctp_socket->so_rcv) < SCTP_BUF_LEN(m_notify)) { 3429233660Srrs /* no space */ 3430233660Srrs sctp_m_freem(m_notify); 3431233660Srrs return; 3432233660Srrs } 3433233660Srrs /* append to socket */ 3434233660Srrs control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination, 3435233660Srrs 0, 0, stcb->asoc.context, 0, 0, 0, 3436233660Srrs m_notify); 3437233660Srrs if (control == NULL) { 3438233660Srrs /* no memory */ 3439233660Srrs sctp_m_freem(m_notify); 3440233660Srrs return; 3441233660Srrs } 3442233660Srrs control->spec_flags = M_NOTIFICATION; 3443233660Srrs control->length = SCTP_BUF_LEN(m_notify); 3444233660Srrs /* not that we need this */ 3445233660Srrs control->tail_mbuf = m_notify; 3446233660Srrs sctp_add_to_readq(stcb->sctp_ep, stcb, 3447233660Srrs control, 3448233660Srrs &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED); 3449233660Srrs} 3450188854Srrs 3451233660Srrsvoid 3452233660Srrssctp_notify_stream_reset_tsn(struct sctp_tcb *stcb, uint32_t sending_tsn, uint32_t recv_tsn, int flag) 3453233660Srrs{ 3454233660Srrs struct mbuf *m_notify; 3455233660Srrs struct sctp_queued_to_read *control; 3456233660Srrs struct sctp_assoc_reset_event *strasoc; 3457233660Srrs 3458235091Stuexen if ((stcb == NULL) || 3459235091Stuexen (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_ASSOC_RESETEVNT))) { 3460233660Srrs /* event not enabled */ 3461233660Srrs return; 3462233660Srrs } 3463268432Sdelphij m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_assoc_reset_event), 0, M_NOWAIT, 1, MT_DATA); 3464233660Srrs if (m_notify == NULL) 3465233660Srrs /* no space left */ 3466233660Srrs return; 3467233660Srrs SCTP_BUF_LEN(m_notify) = 0; 3468233660Srrs strasoc = mtod(m_notify, struct sctp_assoc_reset_event *); 3469268432Sdelphij memset(strasoc, 0, sizeof(struct sctp_assoc_reset_event)); 3470233660Srrs strasoc->assocreset_type = SCTP_ASSOC_RESET_EVENT; 3471233660Srrs strasoc->assocreset_flags = flag; 3472268432Sdelphij strasoc->assocreset_length = sizeof(struct sctp_assoc_reset_event); 3473233660Srrs strasoc->assocreset_assoc_id = sctp_get_associd(stcb); 3474233660Srrs strasoc->assocreset_local_tsn = sending_tsn; 3475233660Srrs strasoc->assocreset_remote_tsn = recv_tsn; 3476268432Sdelphij SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_assoc_reset_event); 3477188854Srrs SCTP_BUF_NEXT(m_notify) = NULL; 3478188854Srrs if (sctp_sbspace(&stcb->asoc, &stcb->sctp_socket->so_rcv) < SCTP_BUF_LEN(m_notify)) { 3479188854Srrs /* no space */ 3480188854Srrs sctp_m_freem(m_notify); 3481188854Srrs return; 3482188854Srrs } 3483188854Srrs /* append to socket */ 3484188854Srrs control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination, 3485228653Stuexen 0, 0, stcb->asoc.context, 0, 0, 0, 3486188854Srrs m_notify); 3487188854Srrs if (control == NULL) { 3488188854Srrs /* no memory */ 3489188854Srrs sctp_m_freem(m_notify); 3490188854Srrs return; 3491188854Srrs } 3492188854Srrs control->spec_flags = M_NOTIFICATION; 3493188854Srrs control->length = SCTP_BUF_LEN(m_notify); 3494188854Srrs /* not that we need this */ 3495188854Srrs control->tail_mbuf = m_notify; 3496188854Srrs sctp_add_to_readq(stcb->sctp_ep, stcb, 3497188854Srrs control, 3498195918Srrs &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED); 3499188854Srrs} 3500188854Srrs 3501188854Srrs 3502233660Srrs 3503188854Srrsstatic void 3504163953Srrssctp_notify_stream_reset(struct sctp_tcb *stcb, 3505163953Srrs int number_entries, uint16_t * list, int flag) 3506163953Srrs{ 3507163953Srrs struct mbuf *m_notify; 3508163953Srrs struct sctp_queued_to_read *control; 3509163953Srrs struct sctp_stream_reset_event *strreset; 3510163953Srrs int len; 3511163953Srrs 3512235091Stuexen if ((stcb == NULL) || 3513235091Stuexen (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_STREAM_RESETEVNT))) { 3514185694Srrs /* event not enabled */ 3515169420Srrs return; 3516169420Srrs } 3517243882Sglebius m_notify = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_NOWAIT, 1, MT_DATA); 3518163953Srrs if (m_notify == NULL) 3519163953Srrs /* no space left */ 3520163953Srrs return; 3521165647Srrs SCTP_BUF_LEN(m_notify) = 0; 3522163953Srrs len = sizeof(struct sctp_stream_reset_event) + (number_entries * sizeof(uint16_t)); 3523163953Srrs if (len > M_TRAILINGSPACE(m_notify)) { 3524163953Srrs /* never enough room */ 3525163953Srrs sctp_m_freem(m_notify); 3526163953Srrs return; 3527163953Srrs } 3528163953Srrs strreset = mtod(m_notify, struct sctp_stream_reset_event *); 3529268432Sdelphij memset(strreset, 0, len); 3530163953Srrs strreset->strreset_type = SCTP_STREAM_RESET_EVENT; 3531233660Srrs strreset->strreset_flags = flag; 3532163953Srrs strreset->strreset_length = len; 3533163953Srrs strreset->strreset_assoc_id = sctp_get_associd(stcb); 3534163953Srrs if (number_entries) { 3535163953Srrs int i; 3536163953Srrs 3537163953Srrs for (i = 0; i < number_entries; i++) { 3538233660Srrs strreset->strreset_stream_list[i] = ntohs(list[i]); 3539163953Srrs } 3540163953Srrs } 3541165647Srrs SCTP_BUF_LEN(m_notify) = len; 3542165647Srrs SCTP_BUF_NEXT(m_notify) = NULL; 3543165647Srrs if (sctp_sbspace(&stcb->asoc, &stcb->sctp_socket->so_rcv) < SCTP_BUF_LEN(m_notify)) { 3544163953Srrs /* no space */ 3545163953Srrs sctp_m_freem(m_notify); 3546163953Srrs return; 3547163953Srrs } 3548163953Srrs /* append to socket */ 3549163953Srrs control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination, 3550228653Stuexen 0, 0, stcb->asoc.context, 0, 0, 0, 3551163953Srrs m_notify); 3552163953Srrs if (control == NULL) { 3553163953Srrs /* no memory */ 3554163953Srrs sctp_m_freem(m_notify); 3555163953Srrs return; 3556163953Srrs } 3557165647Srrs control->spec_flags = M_NOTIFICATION; 3558165647Srrs control->length = SCTP_BUF_LEN(m_notify); 3559163953Srrs /* not that we need this */ 3560163953Srrs control->tail_mbuf = m_notify; 3561163953Srrs sctp_add_to_readq(stcb->sctp_ep, stcb, 3562163953Srrs control, 3563195918Srrs &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED); 3564163953Srrs} 3565163953Srrs 3566163953Srrs 3567235418Stuexenstatic void 3568235418Stuexensctp_notify_remote_error(struct sctp_tcb *stcb, uint16_t error, struct sctp_error_chunk *chunk) 3569235418Stuexen{ 3570235418Stuexen struct mbuf *m_notify; 3571235418Stuexen struct sctp_remote_error *sre; 3572235418Stuexen struct sctp_queued_to_read *control; 3573235418Stuexen size_t notif_len, chunk_len; 3574235418Stuexen 3575235418Stuexen if ((stcb == NULL) || 3576235418Stuexen sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVPEERERR)) { 3577235418Stuexen return; 3578235418Stuexen } 3579235418Stuexen if (chunk != NULL) { 3580258454Stuexen chunk_len = ntohs(chunk->ch.chunk_length); 3581235418Stuexen } else { 3582235418Stuexen chunk_len = 0; 3583235418Stuexen } 3584235418Stuexen notif_len = sizeof(struct sctp_remote_error) + chunk_len; 3585243882Sglebius m_notify = sctp_get_mbuf_for_msg(notif_len, 0, M_NOWAIT, 1, MT_DATA); 3586235418Stuexen if (m_notify == NULL) { 3587235418Stuexen /* Retry with smaller value. */ 3588235418Stuexen notif_len = sizeof(struct sctp_remote_error); 3589243882Sglebius m_notify = sctp_get_mbuf_for_msg(notif_len, 0, M_NOWAIT, 1, MT_DATA); 3590235418Stuexen if (m_notify == NULL) { 3591235418Stuexen return; 3592235418Stuexen } 3593235418Stuexen } 3594235418Stuexen SCTP_BUF_NEXT(m_notify) = NULL; 3595235418Stuexen sre = mtod(m_notify, struct sctp_remote_error *); 3596270353Stuexen memset(sre, 0, notif_len); 3597235418Stuexen sre->sre_type = SCTP_REMOTE_ERROR; 3598235418Stuexen sre->sre_flags = 0; 3599235418Stuexen sre->sre_length = sizeof(struct sctp_remote_error); 3600235418Stuexen sre->sre_error = error; 3601235418Stuexen sre->sre_assoc_id = sctp_get_associd(stcb); 3602235418Stuexen if (notif_len > sizeof(struct sctp_remote_error)) { 3603235418Stuexen memcpy(sre->sre_data, chunk, chunk_len); 3604235418Stuexen sre->sre_length += chunk_len; 3605235418Stuexen } 3606235418Stuexen SCTP_BUF_LEN(m_notify) = sre->sre_length; 3607235418Stuexen control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination, 3608235418Stuexen 0, 0, stcb->asoc.context, 0, 0, 0, 3609235418Stuexen m_notify); 3610235418Stuexen if (control != NULL) { 3611235418Stuexen control->length = SCTP_BUF_LEN(m_notify); 3612235418Stuexen /* not that we need this */ 3613235418Stuexen control->tail_mbuf = m_notify; 3614235418Stuexen control->spec_flags = M_NOTIFICATION; 3615235418Stuexen sctp_add_to_readq(stcb->sctp_ep, stcb, 3616235418Stuexen control, 3617235418Stuexen &stcb->sctp_socket->so_rcv, 1, 3618235418Stuexen SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED); 3619235418Stuexen } else { 3620235418Stuexen sctp_m_freem(m_notify); 3621235418Stuexen } 3622235418Stuexen} 3623235418Stuexen 3624235418Stuexen 3625163953Srrsvoid 3626163953Srrssctp_ulp_notify(uint32_t notification, struct sctp_tcb *stcb, 3627172090Srrs uint32_t error, void *data, int so_locked 3628172090Srrs#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING) 3629172090Srrs SCTP_UNUSED 3630172090Srrs#endif 3631172090Srrs) 3632163953Srrs{ 3633185694Srrs if ((stcb == NULL) || 3634185694Srrs (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) || 3635163953Srrs (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) || 3636185694Srrs (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET)) { 3637185694Srrs /* If the socket is gone we are out of here */ 3638163953Srrs return; 3639163953Srrs } 3640188067Srrs if (stcb->sctp_socket->so_rcv.sb_state & SBS_CANTRCVMORE) { 3641188067Srrs return; 3642188067Srrs } 3643251054Stuexen if ((stcb->asoc.state & SCTP_STATE_COOKIE_WAIT) || 3644251054Stuexen (stcb->asoc.state & SCTP_STATE_COOKIE_ECHOED)) { 3645169352Srrs if ((notification == SCTP_NOTIFY_INTERFACE_DOWN) || 3646169352Srrs (notification == SCTP_NOTIFY_INTERFACE_UP) || 3647169352Srrs (notification == SCTP_NOTIFY_INTERFACE_CONFIRMED)) { 3648169352Srrs /* Don't report these in front states */ 3649169352Srrs return; 3650169352Srrs } 3651169352Srrs } 3652163953Srrs switch (notification) { 3653163953Srrs case SCTP_NOTIFY_ASSOC_UP: 3654163953Srrs if (stcb->asoc.assoc_up_sent == 0) { 3655235403Stuexen sctp_notify_assoc_change(SCTP_COMM_UP, stcb, error, NULL, 0, so_locked); 3656163953Srrs stcb->asoc.assoc_up_sent = 1; 3657163953Srrs } 3658171990Srrs if (stcb->asoc.adaptation_needed && (stcb->asoc.adaptation_sent == 0)) { 3659228653Stuexen sctp_notify_adaptation_layer(stcb); 3660171990Srrs } 3661270362Stuexen if (stcb->asoc.auth_supported == 0) { 3662185694Srrs sctp_ulp_notify(SCTP_NOTIFY_NO_PEER_AUTH, stcb, 0, 3663185694Srrs NULL, so_locked); 3664185694Srrs } 3665163953Srrs break; 3666163953Srrs case SCTP_NOTIFY_ASSOC_DOWN: 3667235403Stuexen sctp_notify_assoc_change(SCTP_SHUTDOWN_COMP, stcb, error, NULL, 0, so_locked); 3668163953Srrs break; 3669163953Srrs case SCTP_NOTIFY_INTERFACE_DOWN: 3670163953Srrs { 3671163953Srrs struct sctp_nets *net; 3672163953Srrs 3673163953Srrs net = (struct sctp_nets *)data; 3674163953Srrs sctp_notify_peer_addr_change(stcb, SCTP_ADDR_UNREACHABLE, 3675283726Stuexen (struct sockaddr *)&net->ro._l_addr, error, so_locked); 3676163953Srrs break; 3677163953Srrs } 3678163953Srrs case SCTP_NOTIFY_INTERFACE_UP: 3679163953Srrs { 3680163953Srrs struct sctp_nets *net; 3681163953Srrs 3682163953Srrs net = (struct sctp_nets *)data; 3683163953Srrs sctp_notify_peer_addr_change(stcb, SCTP_ADDR_AVAILABLE, 3684283726Stuexen (struct sockaddr *)&net->ro._l_addr, error, so_locked); 3685163953Srrs break; 3686163953Srrs } 3687163953Srrs case SCTP_NOTIFY_INTERFACE_CONFIRMED: 3688163953Srrs { 3689163953Srrs struct sctp_nets *net; 3690163953Srrs 3691163953Srrs net = (struct sctp_nets *)data; 3692163953Srrs sctp_notify_peer_addr_change(stcb, SCTP_ADDR_CONFIRMED, 3693283726Stuexen (struct sockaddr *)&net->ro._l_addr, error, so_locked); 3694163953Srrs break; 3695163953Srrs } 3696163953Srrs case SCTP_NOTIFY_SPECIAL_SP_FAIL: 3697163953Srrs sctp_notify_send_failed2(stcb, error, 3698172090Srrs (struct sctp_stream_queue_pending *)data, so_locked); 3699163953Srrs break; 3700235416Stuexen case SCTP_NOTIFY_SENT_DG_FAIL: 3701235416Stuexen sctp_notify_send_failed(stcb, 1, error, 3702172090Srrs (struct sctp_tmit_chunk *)data, so_locked); 3703163953Srrs break; 3704235416Stuexen case SCTP_NOTIFY_UNSENT_DG_FAIL: 3705235416Stuexen sctp_notify_send_failed(stcb, 0, error, 3706235416Stuexen (struct sctp_tmit_chunk *)data, so_locked); 3707235416Stuexen break; 3708163953Srrs case SCTP_NOTIFY_PARTIAL_DELVIERY_INDICATION: 3709168943Srrs { 3710168943Srrs uint32_t val; 3711168943Srrs 3712168943Srrs val = *((uint32_t *) data); 3713168943Srrs 3714196260Stuexen sctp_notify_partial_delivery_indication(stcb, error, val, so_locked); 3715196260Stuexen break; 3716168943Srrs } 3717235403Stuexen case SCTP_NOTIFY_ASSOC_LOC_ABORTED: 3718251054Stuexen if (((stcb->asoc.state & SCTP_STATE_MASK) == SCTP_STATE_COOKIE_WAIT) || 3719251054Stuexen ((stcb->asoc.state & SCTP_STATE_MASK) == SCTP_STATE_COOKIE_ECHOED)) { 3720235403Stuexen sctp_notify_assoc_change(SCTP_CANT_STR_ASSOC, stcb, error, data, 0, so_locked); 3721168709Srrs } else { 3722235403Stuexen sctp_notify_assoc_change(SCTP_COMM_LOST, stcb, error, data, 0, so_locked); 3723168709Srrs } 3724163953Srrs break; 3725235403Stuexen case SCTP_NOTIFY_ASSOC_REM_ABORTED: 3726251054Stuexen if (((stcb->asoc.state & SCTP_STATE_MASK) == SCTP_STATE_COOKIE_WAIT) || 3727251054Stuexen ((stcb->asoc.state & SCTP_STATE_MASK) == SCTP_STATE_COOKIE_ECHOED)) { 3728235403Stuexen sctp_notify_assoc_change(SCTP_CANT_STR_ASSOC, stcb, error, data, 1, so_locked); 3729235403Stuexen } else { 3730235403Stuexen sctp_notify_assoc_change(SCTP_COMM_LOST, stcb, error, data, 1, so_locked); 3731235403Stuexen } 3732235403Stuexen break; 3733163953Srrs case SCTP_NOTIFY_ASSOC_RESTART: 3734235403Stuexen sctp_notify_assoc_change(SCTP_RESTART, stcb, error, NULL, 0, so_locked); 3735270362Stuexen if (stcb->asoc.auth_supported == 0) { 3736185694Srrs sctp_ulp_notify(SCTP_NOTIFY_NO_PEER_AUTH, stcb, 0, 3737185694Srrs NULL, so_locked); 3738185694Srrs } 3739163953Srrs break; 3740163953Srrs case SCTP_NOTIFY_STR_RESET_SEND: 3741234614Stuexen sctp_notify_stream_reset(stcb, error, ((uint16_t *) data), SCTP_STREAM_RESET_OUTGOING_SSN); 3742163953Srrs break; 3743163953Srrs case SCTP_NOTIFY_STR_RESET_RECV: 3744234614Stuexen sctp_notify_stream_reset(stcb, error, ((uint16_t *) data), SCTP_STREAM_RESET_INCOMING); 3745163953Srrs break; 3746163953Srrs case SCTP_NOTIFY_STR_RESET_FAILED_OUT: 3747233660Srrs sctp_notify_stream_reset(stcb, error, ((uint16_t *) data), 3748234614Stuexen (SCTP_STREAM_RESET_OUTGOING_SSN | SCTP_STREAM_RESET_FAILED)); 3749163953Srrs break; 3750235066Stuexen case SCTP_NOTIFY_STR_RESET_DENIED_OUT: 3751235066Stuexen sctp_notify_stream_reset(stcb, error, ((uint16_t *) data), 3752235066Stuexen (SCTP_STREAM_RESET_OUTGOING_SSN | SCTP_STREAM_RESET_DENIED)); 3753235066Stuexen break; 3754163953Srrs case SCTP_NOTIFY_STR_RESET_FAILED_IN: 3755233660Srrs sctp_notify_stream_reset(stcb, error, ((uint16_t *) data), 3756234614Stuexen (SCTP_STREAM_RESET_INCOMING | SCTP_STREAM_RESET_FAILED)); 3757163953Srrs break; 3758235066Stuexen case SCTP_NOTIFY_STR_RESET_DENIED_IN: 3759235066Stuexen sctp_notify_stream_reset(stcb, error, ((uint16_t *) data), 3760235066Stuexen (SCTP_STREAM_RESET_INCOMING | SCTP_STREAM_RESET_DENIED)); 3761235066Stuexen break; 3762163953Srrs case SCTP_NOTIFY_ASCONF_ADD_IP: 3763163953Srrs sctp_notify_peer_addr_change(stcb, SCTP_ADDR_ADDED, data, 3764283726Stuexen error, so_locked); 3765163953Srrs break; 3766163953Srrs case SCTP_NOTIFY_ASCONF_DELETE_IP: 3767163953Srrs sctp_notify_peer_addr_change(stcb, SCTP_ADDR_REMOVED, data, 3768283726Stuexen error, so_locked); 3769163953Srrs break; 3770163953Srrs case SCTP_NOTIFY_ASCONF_SET_PRIMARY: 3771163953Srrs sctp_notify_peer_addr_change(stcb, SCTP_ADDR_MADE_PRIM, data, 3772283726Stuexen error, so_locked); 3773163953Srrs break; 3774163953Srrs case SCTP_NOTIFY_PEER_SHUTDOWN: 3775163953Srrs sctp_notify_shutdown_event(stcb); 3776163953Srrs break; 3777163953Srrs case SCTP_NOTIFY_AUTH_NEW_KEY: 3778234699Stuexen sctp_notify_authentication(stcb, SCTP_AUTH_NEW_KEY, error, 3779185694Srrs (uint16_t) (uintptr_t) data, 3780185694Srrs so_locked); 3781163953Srrs break; 3782185694Srrs case SCTP_NOTIFY_AUTH_FREE_KEY: 3783185694Srrs sctp_notify_authentication(stcb, SCTP_AUTH_FREE_KEY, error, 3784185694Srrs (uint16_t) (uintptr_t) data, 3785185694Srrs so_locked); 3786163953Srrs break; 3787185694Srrs case SCTP_NOTIFY_NO_PEER_AUTH: 3788185694Srrs sctp_notify_authentication(stcb, SCTP_AUTH_NO_AUTH, error, 3789185694Srrs (uint16_t) (uintptr_t) data, 3790185694Srrs so_locked); 3791185694Srrs break; 3792185694Srrs case SCTP_NOTIFY_SENDER_DRY: 3793185694Srrs sctp_notify_sender_dry_event(stcb, so_locked); 3794185694Srrs break; 3795235418Stuexen case SCTP_NOTIFY_REMOTE_ERROR: 3796235418Stuexen sctp_notify_remote_error(stcb, error, data); 3797235418Stuexen break; 3798163953Srrs default: 3799169420Srrs SCTPDBG(SCTP_DEBUG_UTIL1, "%s: unknown notification %xh (%u)\n", 3800294174Stuexen __func__, notification, notification); 3801163953Srrs break; 3802163953Srrs } /* end switch */ 3803163953Srrs} 3804163953Srrs 3805163953Srrsvoid 3806235416Stuexensctp_report_all_outbound(struct sctp_tcb *stcb, uint16_t error, int holds_lock, int so_locked 3807172090Srrs#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING) 3808172090Srrs SCTP_UNUSED 3809172090Srrs#endif 3810172090Srrs) 3811163953Srrs{ 3812163953Srrs struct sctp_association *asoc; 3813163953Srrs struct sctp_stream_out *outs; 3814216822Stuexen struct sctp_tmit_chunk *chk, *nchk; 3815216822Stuexen struct sctp_stream_queue_pending *sp, *nsp; 3816164205Srrs int i; 3817163953Srrs 3818169420Srrs if (stcb == NULL) { 3819169420Srrs return; 3820169420Srrs } 3821216822Stuexen asoc = &stcb->asoc; 3822216822Stuexen if (asoc->state & SCTP_STATE_ABOUT_TO_BE_FREED) { 3823209663Srrs /* already being freed */ 3824209663Srrs return; 3825209663Srrs } 3826163953Srrs if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) || 3827163953Srrs (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) || 3828216822Stuexen (asoc->state & SCTP_STATE_CLOSED_SOCKET)) { 3829163953Srrs return; 3830163953Srrs } 3831163953Srrs /* now through all the gunk freeing chunks */ 3832169420Srrs if (holds_lock == 0) { 3833164205Srrs SCTP_TCB_SEND_LOCK(stcb); 3834169420Srrs } 3835170462Srrs /* sent queue SHOULD be empty */ 3836216822Stuexen TAILQ_FOREACH_SAFE(chk, &asoc->sent_queue, sctp_next, nchk) { 3837216822Stuexen TAILQ_REMOVE(&asoc->sent_queue, chk, sctp_next); 3838216822Stuexen asoc->sent_queue_cnt--; 3839243157Stuexen if (chk->sent != SCTP_DATAGRAM_NR_ACKED) { 3840242714Stuexen if (asoc->strmout[chk->rec.data.stream_number].chunks_on_queues > 0) { 3841242714Stuexen asoc->strmout[chk->rec.data.stream_number].chunks_on_queues--; 3842242714Stuexen#ifdef INVARIANTS 3843242714Stuexen } else { 3844242714Stuexen panic("No chunks on the queues for sid %u.", chk->rec.data.stream_number); 3845242714Stuexen#endif 3846242714Stuexen } 3847242714Stuexen } 3848216822Stuexen if (chk->data != NULL) { 3849216822Stuexen sctp_free_bufspace(stcb, asoc, chk, 1); 3850235416Stuexen sctp_ulp_notify(SCTP_NOTIFY_SENT_DG_FAIL, stcb, 3851235416Stuexen error, chk, so_locked); 3852216822Stuexen if (chk->data) { 3853216822Stuexen sctp_m_freem(chk->data); 3854216822Stuexen chk->data = NULL; 3855163953Srrs } 3856163953Srrs } 3857221627Stuexen sctp_free_a_chunk(stcb, chk, so_locked); 3858216822Stuexen /* sa_ignore FREED_MEMORY */ 3859163953Srrs } 3860170462Srrs /* pending send queue SHOULD be empty */ 3861216822Stuexen TAILQ_FOREACH_SAFE(chk, &asoc->send_queue, sctp_next, nchk) { 3862216822Stuexen TAILQ_REMOVE(&asoc->send_queue, chk, sctp_next); 3863216822Stuexen asoc->send_queue_cnt--; 3864242714Stuexen if (asoc->strmout[chk->rec.data.stream_number].chunks_on_queues > 0) { 3865242714Stuexen asoc->strmout[chk->rec.data.stream_number].chunks_on_queues--; 3866242714Stuexen#ifdef INVARIANTS 3867242714Stuexen } else { 3868242714Stuexen panic("No chunks on the queues for sid %u.", chk->rec.data.stream_number); 3869242714Stuexen#endif 3870242714Stuexen } 3871216822Stuexen if (chk->data != NULL) { 3872216822Stuexen sctp_free_bufspace(stcb, asoc, chk, 1); 3873235416Stuexen sctp_ulp_notify(SCTP_NOTIFY_UNSENT_DG_FAIL, stcb, 3874235416Stuexen error, chk, so_locked); 3875216822Stuexen if (chk->data) { 3876216822Stuexen sctp_m_freem(chk->data); 3877216822Stuexen chk->data = NULL; 3878163953Srrs } 3879163953Srrs } 3880221627Stuexen sctp_free_a_chunk(stcb, chk, so_locked); 3881216822Stuexen /* sa_ignore FREED_MEMORY */ 3882163953Srrs } 3883216822Stuexen for (i = 0; i < asoc->streamoutcnt; i++) { 3884170462Srrs /* For each stream */ 3885216822Stuexen outs = &asoc->strmout[i]; 3886170462Srrs /* clean up any sends there */ 3887216822Stuexen asoc->locked_on_sending = NULL; 3888216822Stuexen TAILQ_FOREACH_SAFE(sp, &outs->outqueue, next, nsp) { 3889216822Stuexen asoc->stream_queue_cnt--; 3890170462Srrs TAILQ_REMOVE(&outs->outqueue, sp, next); 3891170462Srrs sctp_free_spbufspace(stcb, asoc, sp); 3892170462Srrs if (sp->data) { 3893209663Srrs sctp_ulp_notify(SCTP_NOTIFY_SPECIAL_SP_FAIL, stcb, 3894235416Stuexen error, (void *)sp, so_locked); 3895209663Srrs if (sp->data) { 3896209663Srrs sctp_m_freem(sp->data); 3897209663Srrs sp->data = NULL; 3898238550Stuexen sp->tail_mbuf = NULL; 3899238550Stuexen sp->length = 0; 3900209663Srrs } 3901170462Srrs } 3902212712Stuexen if (sp->net) { 3903170462Srrs sctp_free_remote_addr(sp->net); 3904212712Stuexen sp->net = NULL; 3905212712Stuexen } 3906170462Srrs /* Free the chunk */ 3907221627Stuexen sctp_free_a_strmoq(stcb, sp, so_locked); 3908170462Srrs /* sa_ignore FREED_MEMORY */ 3909170462Srrs } 3910170462Srrs } 3911170462Srrs 3912169420Srrs if (holds_lock == 0) { 3913164205Srrs SCTP_TCB_SEND_UNLOCK(stcb); 3914169420Srrs } 3915163953Srrs} 3916163953Srrs 3917163953Srrsvoid 3918235403Stuexensctp_abort_notification(struct sctp_tcb *stcb, uint8_t from_peer, uint16_t error, 3919235360Stuexen struct sctp_abort_chunk *abort, int so_locked 3920172090Srrs#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING) 3921172090Srrs SCTP_UNUSED 3922172090Srrs#endif 3923172090Srrs) 3924163953Srrs{ 3925169420Srrs if (stcb == NULL) { 3926169420Srrs return; 3927169420Srrs } 3928225559Stuexen if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) || 3929225559Stuexen ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) && 3930225559Stuexen (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_CONNECTED))) { 3931225559Stuexen stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_WAS_ABORTED; 3932225559Stuexen } 3933163953Srrs if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) || 3934163953Srrs (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) || 3935163953Srrs (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET)) { 3936163953Srrs return; 3937163953Srrs } 3938163953Srrs /* Tell them we lost the asoc */ 3939235416Stuexen sctp_report_all_outbound(stcb, error, 1, so_locked); 3940235403Stuexen if (from_peer) { 3941235403Stuexen sctp_ulp_notify(SCTP_NOTIFY_ASSOC_REM_ABORTED, stcb, error, abort, so_locked); 3942235403Stuexen } else { 3943235403Stuexen sctp_ulp_notify(SCTP_NOTIFY_ASSOC_LOC_ABORTED, stcb, error, abort, so_locked); 3944235403Stuexen } 3945163953Srrs} 3946163953Srrs 3947163953Srrsvoid 3948163953Srrssctp_abort_association(struct sctp_inpcb *inp, struct sctp_tcb *stcb, 3949237715Stuexen struct mbuf *m, int iphlen, 3950237715Stuexen struct sockaddr *src, struct sockaddr *dst, 3951237715Stuexen struct sctphdr *sh, struct mbuf *op_err, 3952281955Shiren uint8_t mflowtype, uint32_t mflowid, 3953179157Srrs uint32_t vrf_id, uint16_t port) 3954163953Srrs{ 3955163953Srrs uint32_t vtag; 3956163953Srrs 3957237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 3958172090Srrs struct socket *so; 3959172090Srrs 3960172090Srrs#endif 3961172090Srrs 3962163953Srrs vtag = 0; 3963163953Srrs if (stcb != NULL) { 3964163953Srrs /* We have a TCB to abort, send notification too */ 3965163953Srrs vtag = stcb->asoc.peer_vtag; 3966235403Stuexen sctp_abort_notification(stcb, 0, 0, NULL, SCTP_SO_NOT_LOCKED); 3967169352Srrs /* get the assoc vrf id and table id */ 3968169352Srrs vrf_id = stcb->asoc.vrf_id; 3969171745Srrs stcb->asoc.state |= SCTP_STATE_WAS_ABORTED; 3970163953Srrs } 3971237715Stuexen sctp_send_abort(m, iphlen, src, dst, sh, vtag, op_err, 3972284633Stuexen mflowtype, mflowid, inp->fibnum, 3973237049Stuexen vrf_id, port); 3974163953Srrs if (stcb != NULL) { 3975163953Srrs /* Ok, now lets free it */ 3976237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 3977172090Srrs so = SCTP_INP_SO(inp); 3978172090Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 3979172090Srrs SCTP_TCB_UNLOCK(stcb); 3980172090Srrs SCTP_SOCKET_LOCK(so, 1); 3981172090Srrs SCTP_TCB_LOCK(stcb); 3982172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 3983172090Srrs#endif 3984216397Stuexen SCTP_STAT_INCR_COUNTER32(sctps_aborted); 3985216397Stuexen if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) || 3986216397Stuexen (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) { 3987216397Stuexen SCTP_STAT_DECR_GAUGE32(sctps_currestab); 3988216397Stuexen } 3989283823Stuexen (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, 3990283823Stuexen SCTP_FROM_SCTPUTIL + SCTP_LOC_4); 3991237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 3992172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 3993172090Srrs#endif 3994163953Srrs } 3995163953Srrs} 3996163953Srrs 3997168859Srrs#ifdef SCTP_ASOCLOG_OF_TSNS 3998163953Srrsvoid 3999168859Srrssctp_print_out_track_log(struct sctp_tcb *stcb) 4000168859Srrs{ 4001171477Srrs#ifdef NOSIY_PRINTS 4002168859Srrs int i; 4003168859Srrs 4004169420Srrs SCTP_PRINTF("Last ep reason:%x\n", stcb->sctp_ep->last_abort_code); 4005169420Srrs SCTP_PRINTF("IN bound TSN log-aaa\n"); 4006168859Srrs if ((stcb->asoc.tsn_in_at == 0) && (stcb->asoc.tsn_in_wrapped == 0)) { 4007169420Srrs SCTP_PRINTF("None rcvd\n"); 4008168859Srrs goto none_in; 4009168859Srrs } 4010168859Srrs if (stcb->asoc.tsn_in_wrapped) { 4011168859Srrs for (i = stcb->asoc.tsn_in_at; i < SCTP_TSN_LOG_SIZE; i++) { 4012169420Srrs SCTP_PRINTF("TSN:%x strm:%d seq:%d flags:%x sz:%d\n", 4013168859Srrs stcb->asoc.in_tsnlog[i].tsn, 4014168859Srrs stcb->asoc.in_tsnlog[i].strm, 4015168859Srrs stcb->asoc.in_tsnlog[i].seq, 4016168859Srrs stcb->asoc.in_tsnlog[i].flgs, 4017168859Srrs stcb->asoc.in_tsnlog[i].sz); 4018168859Srrs } 4019168859Srrs } 4020168859Srrs if (stcb->asoc.tsn_in_at) { 4021168859Srrs for (i = 0; i < stcb->asoc.tsn_in_at; i++) { 4022169420Srrs SCTP_PRINTF("TSN:%x strm:%d seq:%d flags:%x sz:%d\n", 4023168859Srrs stcb->asoc.in_tsnlog[i].tsn, 4024168859Srrs stcb->asoc.in_tsnlog[i].strm, 4025168859Srrs stcb->asoc.in_tsnlog[i].seq, 4026168859Srrs stcb->asoc.in_tsnlog[i].flgs, 4027168859Srrs stcb->asoc.in_tsnlog[i].sz); 4028168859Srrs } 4029168859Srrs } 4030168859Srrsnone_in: 4031169420Srrs SCTP_PRINTF("OUT bound TSN log-aaa\n"); 4032169420Srrs if ((stcb->asoc.tsn_out_at == 0) && 4033169420Srrs (stcb->asoc.tsn_out_wrapped == 0)) { 4034169420Srrs SCTP_PRINTF("None sent\n"); 4035168859Srrs } 4036168859Srrs if (stcb->asoc.tsn_out_wrapped) { 4037168859Srrs for (i = stcb->asoc.tsn_out_at; i < SCTP_TSN_LOG_SIZE; i++) { 4038169420Srrs SCTP_PRINTF("TSN:%x strm:%d seq:%d flags:%x sz:%d\n", 4039168859Srrs stcb->asoc.out_tsnlog[i].tsn, 4040168859Srrs stcb->asoc.out_tsnlog[i].strm, 4041168859Srrs stcb->asoc.out_tsnlog[i].seq, 4042168859Srrs stcb->asoc.out_tsnlog[i].flgs, 4043168859Srrs stcb->asoc.out_tsnlog[i].sz); 4044168859Srrs } 4045168859Srrs } 4046168859Srrs if (stcb->asoc.tsn_out_at) { 4047168859Srrs for (i = 0; i < stcb->asoc.tsn_out_at; i++) { 4048169420Srrs SCTP_PRINTF("TSN:%x strm:%d seq:%d flags:%x sz:%d\n", 4049168859Srrs stcb->asoc.out_tsnlog[i].tsn, 4050168859Srrs stcb->asoc.out_tsnlog[i].strm, 4051168859Srrs stcb->asoc.out_tsnlog[i].seq, 4052168859Srrs stcb->asoc.out_tsnlog[i].flgs, 4053168859Srrs stcb->asoc.out_tsnlog[i].sz); 4054168859Srrs } 4055168859Srrs } 4056171477Srrs#endif 4057168859Srrs} 4058168859Srrs 4059168859Srrs#endif 4060168859Srrs 4061168859Srrsvoid 4062163953Srrssctp_abort_an_association(struct sctp_inpcb *inp, struct sctp_tcb *stcb, 4063235360Stuexen struct mbuf *op_err, 4064172090Srrs int so_locked 4065172090Srrs#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING) 4066172090Srrs SCTP_UNUSED 4067172090Srrs#endif 4068172090Srrs) 4069163953Srrs{ 4070237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 4071172090Srrs struct socket *so; 4072172090Srrs 4073172090Srrs#endif 4074172090Srrs 4075237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 4076172090Srrs so = SCTP_INP_SO(inp); 4077172090Srrs#endif 4078163953Srrs if (stcb == NULL) { 4079163953Srrs /* Got to have a TCB */ 4080163953Srrs if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) { 4081251248Stuexen if (LIST_EMPTY(&inp->sctp_asoc_list)) { 4082169380Srrs sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT, 4083169380Srrs SCTP_CALLED_DIRECTLY_NOCMPSET); 4084163953Srrs } 4085163953Srrs } 4086163953Srrs return; 4087171745Srrs } else { 4088171745Srrs stcb->asoc.state |= SCTP_STATE_WAS_ABORTED; 4089163953Srrs } 4090163953Srrs /* notify the ulp */ 4091235360Stuexen if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) { 4092235403Stuexen sctp_abort_notification(stcb, 0, 0, NULL, so_locked); 4093235360Stuexen } 4094163953Srrs /* notify the peer */ 4095172090Srrs sctp_send_abort_tcb(stcb, op_err, so_locked); 4096163953Srrs SCTP_STAT_INCR_COUNTER32(sctps_aborted); 4097163953Srrs if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) || 4098163953Srrs (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) { 4099163953Srrs SCTP_STAT_DECR_GAUGE32(sctps_currestab); 4100163953Srrs } 4101163953Srrs /* now free the asoc */ 4102168859Srrs#ifdef SCTP_ASOCLOG_OF_TSNS 4103168859Srrs sctp_print_out_track_log(stcb); 4104168859Srrs#endif 4105237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 4106172090Srrs if (!so_locked) { 4107172090Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 4108172090Srrs SCTP_TCB_UNLOCK(stcb); 4109172090Srrs SCTP_SOCKET_LOCK(so, 1); 4110172090Srrs SCTP_TCB_LOCK(stcb); 4111172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 4112172090Srrs } 4113172090Srrs#endif 4114283823Stuexen (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, 4115283823Stuexen SCTP_FROM_SCTPUTIL + SCTP_LOC_5); 4116237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 4117172090Srrs if (!so_locked) { 4118172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 4119172090Srrs } 4120172090Srrs#endif 4121163953Srrs} 4122163953Srrs 4123163953Srrsvoid 4124237715Stuexensctp_handle_ootb(struct mbuf *m, int iphlen, int offset, 4125237715Stuexen struct sockaddr *src, struct sockaddr *dst, 4126237715Stuexen struct sctphdr *sh, struct sctp_inpcb *inp, 4127267723Stuexen struct mbuf *cause, 4128284633Stuexen uint8_t mflowtype, uint32_t mflowid, uint16_t fibnum, 4129237049Stuexen uint32_t vrf_id, uint16_t port) 4130163953Srrs{ 4131163953Srrs struct sctp_chunkhdr *ch, chunk_buf; 4132163953Srrs unsigned int chk_length; 4133229805Stuexen int contains_init_chunk; 4134163953Srrs 4135163953Srrs SCTP_STAT_INCR_COUNTER32(sctps_outoftheblue); 4136163953Srrs /* Generate a TO address for future reference */ 4137163953Srrs if (inp && (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) { 4138251248Stuexen if (LIST_EMPTY(&inp->sctp_asoc_list)) { 4139169380Srrs sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT, 4140169380Srrs SCTP_CALLED_DIRECTLY_NOCMPSET); 4141163953Srrs } 4142163953Srrs } 4143229805Stuexen contains_init_chunk = 0; 4144163953Srrs ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, offset, 4145163953Srrs sizeof(*ch), (uint8_t *) & chunk_buf); 4146163953Srrs while (ch != NULL) { 4147163953Srrs chk_length = ntohs(ch->chunk_length); 4148163953Srrs if (chk_length < sizeof(*ch)) { 4149163953Srrs /* break to abort land */ 4150163953Srrs break; 4151163953Srrs } 4152163953Srrs switch (ch->chunk_type) { 4153229805Stuexen case SCTP_INIT: 4154229805Stuexen contains_init_chunk = 1; 4155229805Stuexen break; 4156163953Srrs case SCTP_PACKET_DROPPED: 4157163953Srrs /* we don't respond to pkt-dropped */ 4158163953Srrs return; 4159163953Srrs case SCTP_ABORT_ASSOCIATION: 4160163953Srrs /* we don't respond with an ABORT to an ABORT */ 4161163953Srrs return; 4162163953Srrs case SCTP_SHUTDOWN_COMPLETE: 4163163953Srrs /* 4164163953Srrs * we ignore it since we are not waiting for it and 4165163953Srrs * peer is gone 4166163953Srrs */ 4167163953Srrs return; 4168163953Srrs case SCTP_SHUTDOWN_ACK: 4169237715Stuexen sctp_send_shutdown_complete2(src, dst, sh, 4170284633Stuexen mflowtype, mflowid, fibnum, 4171237049Stuexen vrf_id, port); 4172163953Srrs return; 4173163953Srrs default: 4174163953Srrs break; 4175163953Srrs } 4176163953Srrs offset += SCTP_SIZE32(chk_length); 4177163953Srrs ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, offset, 4178163953Srrs sizeof(*ch), (uint8_t *) & chunk_buf); 4179163953Srrs } 4180229805Stuexen if ((SCTP_BASE_SYSCTL(sctp_blackhole) == 0) || 4181229805Stuexen ((SCTP_BASE_SYSCTL(sctp_blackhole) == 1) && 4182229805Stuexen (contains_init_chunk == 0))) { 4183267723Stuexen sctp_send_abort(m, iphlen, src, dst, sh, 0, cause, 4184284633Stuexen mflowtype, mflowid, fibnum, 4185237049Stuexen vrf_id, port); 4186229805Stuexen } 4187163953Srrs} 4188163953Srrs 4189163953Srrs/* 4190163953Srrs * check the inbound datagram to make sure there is not an abort inside it, 4191163953Srrs * if there is return 1, else return 0. 4192163953Srrs */ 4193163953Srrsint 4194163953Srrssctp_is_there_an_abort_here(struct mbuf *m, int iphlen, uint32_t * vtagfill) 4195163953Srrs{ 4196163953Srrs struct sctp_chunkhdr *ch; 4197163953Srrs struct sctp_init_chunk *init_chk, chunk_buf; 4198163953Srrs int offset; 4199163953Srrs unsigned int chk_length; 4200163953Srrs 4201163953Srrs offset = iphlen + sizeof(struct sctphdr); 4202163953Srrs ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, offset, sizeof(*ch), 4203163953Srrs (uint8_t *) & chunk_buf); 4204163953Srrs while (ch != NULL) { 4205163953Srrs chk_length = ntohs(ch->chunk_length); 4206163953Srrs if (chk_length < sizeof(*ch)) { 4207163953Srrs /* packet is probably corrupt */ 4208163953Srrs break; 4209163953Srrs } 4210163953Srrs /* we seem to be ok, is it an abort? */ 4211163953Srrs if (ch->chunk_type == SCTP_ABORT_ASSOCIATION) { 4212163953Srrs /* yep, tell them */ 4213163953Srrs return (1); 4214163953Srrs } 4215163953Srrs if (ch->chunk_type == SCTP_INITIATION) { 4216163953Srrs /* need to update the Vtag */ 4217163953Srrs init_chk = (struct sctp_init_chunk *)sctp_m_getptr(m, 4218163953Srrs offset, sizeof(*init_chk), (uint8_t *) & chunk_buf); 4219163953Srrs if (init_chk != NULL) { 4220163953Srrs *vtagfill = ntohl(init_chk->init.initiate_tag); 4221163953Srrs } 4222163953Srrs } 4223163953Srrs /* Nope, move to the next chunk */ 4224163953Srrs offset += SCTP_SIZE32(chk_length); 4225163953Srrs ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, offset, 4226163953Srrs sizeof(*ch), (uint8_t *) & chunk_buf); 4227163953Srrs } 4228163953Srrs return (0); 4229163953Srrs} 4230163953Srrs 4231163953Srrs/* 4232163953Srrs * currently (2/02), ifa_addr embeds scope_id's and don't have sin6_scope_id 4233163953Srrs * set (i.e. it's 0) so, create this function to compare link local scopes 4234163953Srrs */ 4235178251Srrs#ifdef INET6 4236163953Srrsuint32_t 4237163953Srrssctp_is_same_scope(struct sockaddr_in6 *addr1, struct sockaddr_in6 *addr2) 4238163953Srrs{ 4239163953Srrs struct sockaddr_in6 a, b; 4240163953Srrs 4241163953Srrs /* save copies */ 4242163953Srrs a = *addr1; 4243163953Srrs b = *addr2; 4244163953Srrs 4245163953Srrs if (a.sin6_scope_id == 0) 4246163953Srrs if (sa6_recoverscope(&a)) { 4247163953Srrs /* can't get scope, so can't match */ 4248163953Srrs return (0); 4249163953Srrs } 4250163953Srrs if (b.sin6_scope_id == 0) 4251163953Srrs if (sa6_recoverscope(&b)) { 4252163953Srrs /* can't get scope, so can't match */ 4253163953Srrs return (0); 4254163953Srrs } 4255163953Srrs if (a.sin6_scope_id != b.sin6_scope_id) 4256163953Srrs return (0); 4257163953Srrs 4258163953Srrs return (1); 4259163953Srrs} 4260163953Srrs 4261163953Srrs/* 4262163953Srrs * returns a sockaddr_in6 with embedded scope recovered and removed 4263163953Srrs */ 4264163953Srrsstruct sockaddr_in6 * 4265163953Srrssctp_recover_scope(struct sockaddr_in6 *addr, struct sockaddr_in6 *store) 4266163953Srrs{ 4267163953Srrs /* check and strip embedded scope junk */ 4268163953Srrs if (addr->sin6_family == AF_INET6) { 4269163953Srrs if (IN6_IS_SCOPE_LINKLOCAL(&addr->sin6_addr)) { 4270163953Srrs if (addr->sin6_scope_id == 0) { 4271163953Srrs *store = *addr; 4272163953Srrs if (!sa6_recoverscope(store)) { 4273163953Srrs /* use the recovered scope */ 4274163953Srrs addr = store; 4275163953Srrs } 4276166675Srrs } else { 4277163953Srrs /* else, return the original "to" addr */ 4278166675Srrs in6_clearscope(&addr->sin6_addr); 4279163953Srrs } 4280163953Srrs } 4281163953Srrs } 4282163953Srrs return (addr); 4283163953Srrs} 4284163953Srrs 4285178251Srrs#endif 4286178251Srrs 4287163953Srrs/* 4288163953Srrs * are the two addresses the same? currently a "scopeless" check returns: 1 4289163953Srrs * if same, 0 if not 4290163953Srrs */ 4291170806Srrsint 4292163953Srrssctp_cmpaddr(struct sockaddr *sa1, struct sockaddr *sa2) 4293163953Srrs{ 4294163953Srrs 4295163953Srrs /* must be valid */ 4296163953Srrs if (sa1 == NULL || sa2 == NULL) 4297163953Srrs return (0); 4298163953Srrs 4299163953Srrs /* must be the same family */ 4300163953Srrs if (sa1->sa_family != sa2->sa_family) 4301163953Srrs return (0); 4302163953Srrs 4303178251Srrs switch (sa1->sa_family) { 4304178251Srrs#ifdef INET6 4305178251Srrs case AF_INET6: 4306178251Srrs { 4307178251Srrs /* IPv6 addresses */ 4308178251Srrs struct sockaddr_in6 *sin6_1, *sin6_2; 4309163953Srrs 4310178251Srrs sin6_1 = (struct sockaddr_in6 *)sa1; 4311178251Srrs sin6_2 = (struct sockaddr_in6 *)sa2; 4312179157Srrs return (SCTP6_ARE_ADDR_EQUAL(sin6_1, 4313179157Srrs sin6_2)); 4314178251Srrs } 4315178251Srrs#endif 4316221328Stuexen#ifdef INET 4317178251Srrs case AF_INET: 4318178251Srrs { 4319178251Srrs /* IPv4 addresses */ 4320178251Srrs struct sockaddr_in *sin_1, *sin_2; 4321163953Srrs 4322178251Srrs sin_1 = (struct sockaddr_in *)sa1; 4323178251Srrs sin_2 = (struct sockaddr_in *)sa2; 4324178251Srrs return (sin_1->sin_addr.s_addr == sin_2->sin_addr.s_addr); 4325178251Srrs } 4326221328Stuexen#endif 4327178251Srrs default: 4328163953Srrs /* we don't do these... */ 4329163953Srrs return (0); 4330163953Srrs } 4331163953Srrs} 4332163953Srrs 4333163953Srrsvoid 4334163953Srrssctp_print_address(struct sockaddr *sa) 4335163953Srrs{ 4336178251Srrs#ifdef INET6 4337169420Srrs char ip6buf[INET6_ADDRSTRLEN]; 4338163953Srrs 4339178251Srrs#endif 4340163953Srrs 4341178251Srrs switch (sa->sa_family) { 4342178251Srrs#ifdef INET6 4343178251Srrs case AF_INET6: 4344178251Srrs { 4345178251Srrs struct sockaddr_in6 *sin6; 4346163953Srrs 4347178251Srrs sin6 = (struct sockaddr_in6 *)sa; 4348178251Srrs SCTP_PRINTF("IPv6 address: %s:port:%d scope:%u\n", 4349178251Srrs ip6_sprintf(ip6buf, &sin6->sin6_addr), 4350178251Srrs ntohs(sin6->sin6_port), 4351178251Srrs sin6->sin6_scope_id); 4352178251Srrs break; 4353178251Srrs } 4354178251Srrs#endif 4355221328Stuexen#ifdef INET 4356178251Srrs case AF_INET: 4357178251Srrs { 4358178251Srrs struct sockaddr_in *sin; 4359178251Srrs unsigned char *p; 4360178251Srrs 4361178251Srrs sin = (struct sockaddr_in *)sa; 4362178251Srrs p = (unsigned char *)&sin->sin_addr; 4363178251Srrs SCTP_PRINTF("IPv4 address: %u.%u.%u.%u:%d\n", 4364178251Srrs p[0], p[1], p[2], p[3], ntohs(sin->sin_port)); 4365178251Srrs break; 4366178251Srrs } 4367221328Stuexen#endif 4368178251Srrs default: 4369169420Srrs SCTP_PRINTF("?\n"); 4370178251Srrs break; 4371163953Srrs } 4372163953Srrs} 4373163953Srrs 4374163953Srrsvoid 4375163953Srrssctp_pull_off_control_to_new_inp(struct sctp_inpcb *old_inp, 4376163953Srrs struct sctp_inpcb *new_inp, 4377169208Srrs struct sctp_tcb *stcb, 4378169208Srrs int waitflags) 4379163953Srrs{ 4380163953Srrs /* 4381163953Srrs * go through our old INP and pull off any control structures that 4382163953Srrs * belong to stcb and move then to the new inp. 4383163953Srrs */ 4384163953Srrs struct socket *old_so, *new_so; 4385163953Srrs struct sctp_queued_to_read *control, *nctl; 4386163953Srrs struct sctp_readhead tmp_queue; 4387163953Srrs struct mbuf *m; 4388168299Srrs int error = 0; 4389163953Srrs 4390163953Srrs old_so = old_inp->sctp_socket; 4391163953Srrs new_so = new_inp->sctp_socket; 4392163953Srrs TAILQ_INIT(&tmp_queue); 4393169208Srrs error = sblock(&old_so->so_rcv, waitflags); 4394163953Srrs if (error) { 4395163953Srrs /* 4396163953Srrs * Gak, can't get sblock, we have a problem. data will be 4397163953Srrs * left stranded.. and we don't dare look at it since the 4398163953Srrs * other thread may be reading something. Oh well, its a 4399163953Srrs * screwed up app that does a peeloff OR a accept while 4400163953Srrs * reading from the main socket... actually its only the 4401163953Srrs * peeloff() case, since I think read will fail on a 4402163953Srrs * listening socket.. 4403163953Srrs */ 4404163953Srrs return; 4405163953Srrs } 4406163953Srrs /* lock the socket buffers */ 4407163953Srrs SCTP_INP_READ_LOCK(old_inp); 4408216822Stuexen TAILQ_FOREACH_SAFE(control, &old_inp->read_queue, next, nctl) { 4409216822Stuexen /* Pull off all for out target stcb */ 4410163953Srrs if (control->stcb == stcb) { 4411163953Srrs /* remove it we want it */ 4412163953Srrs TAILQ_REMOVE(&old_inp->read_queue, control, next); 4413163953Srrs TAILQ_INSERT_TAIL(&tmp_queue, control, next); 4414163953Srrs m = control->data; 4415163953Srrs while (m) { 4416179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) { 4417170744Srrs sctp_sblog(&old_so->so_rcv, control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBFREE, SCTP_BUF_LEN(m)); 4418170744Srrs } 4419163953Srrs sctp_sbfree(control, stcb, &old_so->so_rcv, m); 4420179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) { 4421170744Srrs sctp_sblog(&old_so->so_rcv, control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBRESULT, 0); 4422170744Srrs } 4423165647Srrs m = SCTP_BUF_NEXT(m); 4424163953Srrs } 4425163953Srrs } 4426163953Srrs } 4427163953Srrs SCTP_INP_READ_UNLOCK(old_inp); 4428163953Srrs /* Remove the sb-lock on the old socket */ 4429163953Srrs 4430163953Srrs sbunlock(&old_so->so_rcv); 4431163953Srrs /* Now we move them over to the new socket buffer */ 4432163953Srrs SCTP_INP_READ_LOCK(new_inp); 4433216822Stuexen TAILQ_FOREACH_SAFE(control, &tmp_queue, next, nctl) { 4434163953Srrs TAILQ_INSERT_TAIL(&new_inp->read_queue, control, next); 4435163953Srrs m = control->data; 4436163953Srrs while (m) { 4437179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) { 4438170744Srrs sctp_sblog(&new_so->so_rcv, control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBALLOC, SCTP_BUF_LEN(m)); 4439170744Srrs } 4440163953Srrs sctp_sballoc(stcb, &new_so->so_rcv, m); 4441179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) { 4442170744Srrs sctp_sblog(&new_so->so_rcv, control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBRESULT, 0); 4443170744Srrs } 4444165647Srrs m = SCTP_BUF_NEXT(m); 4445163953Srrs } 4446163953Srrs } 4447163953Srrs SCTP_INP_READ_UNLOCK(new_inp); 4448163953Srrs} 4449163953Srrs 4450163953Srrsvoid 4451163953Srrssctp_add_to_readq(struct sctp_inpcb *inp, 4452163953Srrs struct sctp_tcb *stcb, 4453163953Srrs struct sctp_queued_to_read *control, 4454163953Srrs struct sockbuf *sb, 4455172090Srrs int end, 4456195918Srrs int inp_read_lock_held, 4457172090Srrs int so_locked 4458172090Srrs#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING) 4459172090Srrs SCTP_UNUSED 4460172090Srrs#endif 4461172090Srrs) 4462163953Srrs{ 4463163953Srrs /* 4464163953Srrs * Here we must place the control on the end of the socket read 4465163953Srrs * queue AND increment sb_cc so that select will work properly on 4466163953Srrs * read. 4467163953Srrs */ 4468163953Srrs struct mbuf *m, *prev = NULL; 4469163953Srrs 4470164085Srrs if (inp == NULL) { 4471164085Srrs /* Gak, TSNH!! */ 4472165220Srrs#ifdef INVARIANTS 4473164085Srrs panic("Gak, inp NULL on add_to_readq"); 4474164085Srrs#endif 4475164085Srrs return; 4476164085Srrs } 4477195918Srrs if (inp_read_lock_held == 0) 4478195918Srrs SCTP_INP_READ_LOCK(inp); 4479209289Stuexen if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_CANT_READ) { 4480209289Stuexen sctp_free_remote_addr(control->whoFrom); 4481209289Stuexen if (control->data) { 4482209289Stuexen sctp_m_freem(control->data); 4483209289Stuexen control->data = NULL; 4484209289Stuexen } 4485209289Stuexen SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_readq), control); 4486209289Stuexen if (inp_read_lock_held == 0) 4487209289Stuexen SCTP_INP_READ_UNLOCK(inp); 4488209289Stuexen return; 4489209289Stuexen } 4490167598Srrs if (!(control->spec_flags & M_NOTIFICATION)) { 4491167598Srrs atomic_add_int(&inp->total_recvs, 1); 4492167598Srrs if (!control->do_not_ref_stcb) { 4493167598Srrs atomic_add_int(&stcb->total_recvs, 1); 4494167598Srrs } 4495167598Srrs } 4496163953Srrs m = control->data; 4497163953Srrs control->held_length = 0; 4498163953Srrs control->length = 0; 4499163953Srrs while (m) { 4500165647Srrs if (SCTP_BUF_LEN(m) == 0) { 4501163953Srrs /* Skip mbufs with NO length */ 4502163953Srrs if (prev == NULL) { 4503163953Srrs /* First one */ 4504163953Srrs control->data = sctp_m_free(m); 4505163953Srrs m = control->data; 4506163953Srrs } else { 4507165647Srrs SCTP_BUF_NEXT(prev) = sctp_m_free(m); 4508165647Srrs m = SCTP_BUF_NEXT(prev); 4509163953Srrs } 4510163953Srrs if (m == NULL) { 4511201758Smbr control->tail_mbuf = prev; 4512163953Srrs } 4513163953Srrs continue; 4514163953Srrs } 4515163953Srrs prev = m; 4516179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) { 4517170744Srrs sctp_sblog(sb, control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBALLOC, SCTP_BUF_LEN(m)); 4518170744Srrs } 4519163953Srrs sctp_sballoc(stcb, sb, m); 4520179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) { 4521170744Srrs sctp_sblog(sb, control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBRESULT, 0); 4522170744Srrs } 4523165647Srrs atomic_add_int(&control->length, SCTP_BUF_LEN(m)); 4524165647Srrs m = SCTP_BUF_NEXT(m); 4525163953Srrs } 4526163953Srrs if (prev != NULL) { 4527163953Srrs control->tail_mbuf = prev; 4528163953Srrs } else { 4529165647Srrs /* Everything got collapsed out?? */ 4530209289Stuexen sctp_free_remote_addr(control->whoFrom); 4531209289Stuexen SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_readq), control); 4532195918Srrs if (inp_read_lock_held == 0) 4533195918Srrs SCTP_INP_READ_UNLOCK(inp); 4534163953Srrs return; 4535163953Srrs } 4536163953Srrs if (end) { 4537163953Srrs control->end_added = 1; 4538163953Srrs } 4539163953Srrs TAILQ_INSERT_TAIL(&inp->read_queue, control, next); 4540195918Srrs if (inp_read_lock_held == 0) 4541195918Srrs SCTP_INP_READ_UNLOCK(inp); 4542163953Srrs if (inp && inp->sctp_socket) { 4543169352Srrs if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_ZERO_COPY_ACTIVE)) { 4544169352Srrs SCTP_ZERO_COPY_EVENT(inp, inp->sctp_socket); 4545172090Srrs } else { 4546237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 4547172090Srrs struct socket *so; 4548172090Srrs 4549172090Srrs so = SCTP_INP_SO(inp); 4550172090Srrs if (!so_locked) { 4551228907Stuexen if (stcb) { 4552228907Stuexen atomic_add_int(&stcb->asoc.refcnt, 1); 4553228907Stuexen SCTP_TCB_UNLOCK(stcb); 4554228907Stuexen } 4555172090Srrs SCTP_SOCKET_LOCK(so, 1); 4556228907Stuexen if (stcb) { 4557228907Stuexen SCTP_TCB_LOCK(stcb); 4558228907Stuexen atomic_subtract_int(&stcb->asoc.refcnt, 1); 4559228907Stuexen } 4560172090Srrs if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) { 4561172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 4562172090Srrs return; 4563172090Srrs } 4564172090Srrs } 4565172090Srrs#endif 4566169352Srrs sctp_sorwakeup(inp, inp->sctp_socket); 4567237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 4568172090Srrs if (!so_locked) { 4569172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 4570172090Srrs } 4571172090Srrs#endif 4572172090Srrs } 4573163953Srrs } 4574163953Srrs} 4575163953Srrs 4576163953Srrs 4577163953Srrsint 4578163953Srrssctp_append_to_readq(struct sctp_inpcb *inp, 4579163953Srrs struct sctp_tcb *stcb, 4580163953Srrs struct sctp_queued_to_read *control, 4581163953Srrs struct mbuf *m, 4582163953Srrs int end, 4583163953Srrs int ctls_cumack, 4584163953Srrs struct sockbuf *sb) 4585163953Srrs{ 4586163953Srrs /* 4587163953Srrs * A partial delivery API event is underway. OR we are appending on 4588163953Srrs * the reassembly queue. 4589163953Srrs * 4590163953Srrs * If PDAPI this means we need to add m to the end of the data. 4591163953Srrs * Increase the length in the control AND increment the sb_cc. 4592163953Srrs * Otherwise sb is NULL and all we need to do is put it at the end 4593163953Srrs * of the mbuf chain. 4594163953Srrs */ 4595163953Srrs int len = 0; 4596163953Srrs struct mbuf *mm, *tail = NULL, *prev = NULL; 4597163953Srrs 4598163953Srrs if (inp) { 4599163953Srrs SCTP_INP_READ_LOCK(inp); 4600163953Srrs } 4601163953Srrs if (control == NULL) { 4602163953Srrsget_out: 4603163953Srrs if (inp) { 4604163953Srrs SCTP_INP_READ_UNLOCK(inp); 4605163953Srrs } 4606163953Srrs return (-1); 4607163953Srrs } 4608209289Stuexen if (inp && (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_CANT_READ)) { 4609209289Stuexen SCTP_INP_READ_UNLOCK(inp); 4610228907Stuexen return (0); 4611209289Stuexen } 4612165647Srrs if (control->end_added) { 4613163953Srrs /* huh this one is complete? */ 4614163953Srrs goto get_out; 4615163953Srrs } 4616163953Srrs mm = m; 4617163953Srrs if (mm == NULL) { 4618163953Srrs goto get_out; 4619163953Srrs } 4620163953Srrs while (mm) { 4621165647Srrs if (SCTP_BUF_LEN(mm) == 0) { 4622163953Srrs /* Skip mbufs with NO lenght */ 4623163953Srrs if (prev == NULL) { 4624163953Srrs /* First one */ 4625163953Srrs m = sctp_m_free(mm); 4626163953Srrs mm = m; 4627163953Srrs } else { 4628165647Srrs SCTP_BUF_NEXT(prev) = sctp_m_free(mm); 4629165647Srrs mm = SCTP_BUF_NEXT(prev); 4630163953Srrs } 4631163953Srrs continue; 4632163953Srrs } 4633163953Srrs prev = mm; 4634165647Srrs len += SCTP_BUF_LEN(mm); 4635163953Srrs if (sb) { 4636179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) { 4637170744Srrs sctp_sblog(sb, control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBALLOC, SCTP_BUF_LEN(mm)); 4638170744Srrs } 4639163953Srrs sctp_sballoc(stcb, sb, mm); 4640179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) { 4641170744Srrs sctp_sblog(sb, control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBRESULT, 0); 4642170744Srrs } 4643163953Srrs } 4644165647Srrs mm = SCTP_BUF_NEXT(mm); 4645163953Srrs } 4646163953Srrs if (prev) { 4647163953Srrs tail = prev; 4648163953Srrs } else { 4649163953Srrs /* Really there should always be a prev */ 4650163953Srrs if (m == NULL) { 4651163953Srrs /* Huh nothing left? */ 4652165220Srrs#ifdef INVARIANTS 4653163953Srrs panic("Nothing left to add?"); 4654163953Srrs#else 4655163953Srrs goto get_out; 4656163953Srrs#endif 4657163953Srrs } 4658163953Srrs tail = m; 4659163953Srrs } 4660163953Srrs if (control->tail_mbuf) { 4661163953Srrs /* append */ 4662165647Srrs SCTP_BUF_NEXT(control->tail_mbuf) = m; 4663163953Srrs control->tail_mbuf = tail; 4664163953Srrs } else { 4665163953Srrs /* nothing there */ 4666165220Srrs#ifdef INVARIANTS 4667163953Srrs if (control->data != NULL) { 4668163953Srrs panic("This should NOT happen"); 4669163953Srrs } 4670163953Srrs#endif 4671163953Srrs control->data = m; 4672163953Srrs control->tail_mbuf = tail; 4673163953Srrs } 4674171477Srrs atomic_add_int(&control->length, len); 4675171477Srrs if (end) { 4676171477Srrs /* message is complete */ 4677171477Srrs if (stcb && (control == stcb->asoc.control_pdapi)) { 4678171477Srrs stcb->asoc.control_pdapi = NULL; 4679171477Srrs } 4680171477Srrs control->held_length = 0; 4681171477Srrs control->end_added = 1; 4682171477Srrs } 4683169420Srrs if (stcb == NULL) { 4684169420Srrs control->do_not_ref_stcb = 1; 4685169420Srrs } 4686163953Srrs /* 4687163953Srrs * When we are appending in partial delivery, the cum-ack is used 4688163953Srrs * for the actual pd-api highest tsn on this mbuf. The true cum-ack 4689163953Srrs * is populated in the outbound sinfo structure from the true cumack 4690163953Srrs * if the association exists... 4691163953Srrs */ 4692163953Srrs control->sinfo_tsn = control->sinfo_cumtsn = ctls_cumack; 4693163953Srrs if (inp) { 4694163953Srrs SCTP_INP_READ_UNLOCK(inp); 4695163953Srrs } 4696163953Srrs if (inp && inp->sctp_socket) { 4697169352Srrs if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_ZERO_COPY_ACTIVE)) { 4698169352Srrs SCTP_ZERO_COPY_EVENT(inp, inp->sctp_socket); 4699172090Srrs } else { 4700237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 4701172090Srrs struct socket *so; 4702172090Srrs 4703172090Srrs so = SCTP_INP_SO(inp); 4704228907Stuexen if (stcb) { 4705228907Stuexen atomic_add_int(&stcb->asoc.refcnt, 1); 4706228907Stuexen SCTP_TCB_UNLOCK(stcb); 4707228907Stuexen } 4708172090Srrs SCTP_SOCKET_LOCK(so, 1); 4709228907Stuexen if (stcb) { 4710228907Stuexen SCTP_TCB_LOCK(stcb); 4711228907Stuexen atomic_subtract_int(&stcb->asoc.refcnt, 1); 4712228907Stuexen } 4713172090Srrs if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) { 4714172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 4715172090Srrs return (0); 4716172090Srrs } 4717172090Srrs#endif 4718169352Srrs sctp_sorwakeup(inp, inp->sctp_socket); 4719237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 4720172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 4721172090Srrs#endif 4722172090Srrs } 4723163953Srrs } 4724163953Srrs return (0); 4725163953Srrs} 4726163953Srrs 4727163953Srrs 4728163953Srrs 4729163953Srrs/*************HOLD THIS COMMENT FOR PATCH FILE OF 4730163953Srrs *************ALTERNATE ROUTING CODE 4731163953Srrs */ 4732163953Srrs 4733163953Srrs/*************HOLD THIS COMMENT FOR END OF PATCH FILE OF 4734163953Srrs *************ALTERNATE ROUTING CODE 4735163953Srrs */ 4736163953Srrs 4737163953Srrsstruct mbuf * 4738267723Stuexensctp_generate_cause(uint16_t code, char *info) 4739163953Srrs{ 4740163953Srrs struct mbuf *m; 4741267723Stuexen struct sctp_gen_error_cause *cause; 4742267723Stuexen size_t info_len, len; 4743163953Srrs 4744267723Stuexen if ((code == 0) || (info == NULL)) { 4745267723Stuexen return (NULL); 4746163953Srrs } 4747267723Stuexen info_len = strlen(info); 4748267723Stuexen len = sizeof(struct sctp_paramhdr) + info_len; 4749267723Stuexen m = sctp_get_mbuf_for_msg(len, 0, M_NOWAIT, 1, MT_DATA); 4750267723Stuexen if (m != NULL) { 4751267723Stuexen SCTP_BUF_LEN(m) = len; 4752267723Stuexen cause = mtod(m, struct sctp_gen_error_cause *); 4753267723Stuexen cause->code = htons(code); 4754267723Stuexen cause->length = htons((uint16_t) len); 4755267723Stuexen memcpy(cause->info, info, info_len); 4756267723Stuexen } 4757163953Srrs return (m); 4758163953Srrs} 4759163953Srrs 4760267729Stuexenstruct mbuf * 4761267729Stuexensctp_generate_no_user_data_cause(uint32_t tsn) 4762267729Stuexen{ 4763267729Stuexen struct mbuf *m; 4764267729Stuexen struct sctp_error_no_user_data *no_user_data_cause; 4765267729Stuexen size_t len; 4766267729Stuexen 4767267729Stuexen len = sizeof(struct sctp_error_no_user_data); 4768267729Stuexen m = sctp_get_mbuf_for_msg(len, 0, M_NOWAIT, 1, MT_DATA); 4769267729Stuexen if (m != NULL) { 4770267729Stuexen SCTP_BUF_LEN(m) = len; 4771267729Stuexen no_user_data_cause = mtod(m, struct sctp_error_no_user_data *); 4772267729Stuexen no_user_data_cause->cause.code = htons(SCTP_CAUSE_NO_USER_DATA); 4773267729Stuexen no_user_data_cause->cause.length = htons((uint16_t) len); 4774267729Stuexen no_user_data_cause->tsn = tsn; /* tsn is passed in as NBO */ 4775267729Stuexen } 4776267729Stuexen return (m); 4777267729Stuexen} 4778267729Stuexen 4779163953Srrs#ifdef SCTP_MBCNT_LOGGING 4780163953Srrsvoid 4781163953Srrssctp_free_bufspace(struct sctp_tcb *stcb, struct sctp_association *asoc, 4782163953Srrs struct sctp_tmit_chunk *tp1, int chk_cnt) 4783163953Srrs{ 4784163953Srrs if (tp1->data == NULL) { 4785163953Srrs return; 4786163953Srrs } 4787163953Srrs asoc->chunks_on_out_queue -= chk_cnt; 4788179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBCNT_LOGGING_ENABLE) { 4789170744Srrs sctp_log_mbcnt(SCTP_LOG_MBCNT_DECREASE, 4790170744Srrs asoc->total_output_queue_size, 4791170744Srrs tp1->book_size, 4792170744Srrs 0, 4793170744Srrs tp1->mbcnt); 4794170744Srrs } 4795163953Srrs if (asoc->total_output_queue_size >= tp1->book_size) { 4796166023Srrs atomic_add_int(&asoc->total_output_queue_size, -tp1->book_size); 4797163953Srrs } else { 4798163953Srrs asoc->total_output_queue_size = 0; 4799163953Srrs } 4800163953Srrs 4801163953Srrs if (stcb->sctp_socket && (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) || 4802163953Srrs ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE)))) { 4803163953Srrs if (stcb->sctp_socket->so_snd.sb_cc >= tp1->book_size) { 4804163953Srrs stcb->sctp_socket->so_snd.sb_cc -= tp1->book_size; 4805163953Srrs } else { 4806163953Srrs stcb->sctp_socket->so_snd.sb_cc = 0; 4807163953Srrs 4808163953Srrs } 4809163953Srrs } 4810163953Srrs} 4811163953Srrs 4812163953Srrs#endif 4813163953Srrs 4814163953Srrsint 4815163953Srrssctp_release_pr_sctp_chunk(struct sctp_tcb *stcb, struct sctp_tmit_chunk *tp1, 4816235416Stuexen uint8_t sent, int so_locked 4817172090Srrs#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING) 4818172090Srrs SCTP_UNUSED 4819172090Srrs#endif 4820172090Srrs) 4821163953Srrs{ 4822189790Srrs struct sctp_stream_out *strq; 4823216822Stuexen struct sctp_tmit_chunk *chk = NULL, *tp2; 4824189790Srrs struct sctp_stream_queue_pending *sp; 4825189790Srrs uint16_t stream = 0, seq = 0; 4826189790Srrs uint8_t foundeom = 0; 4827163953Srrs int ret_sz = 0; 4828163953Srrs int notdone; 4829189790Srrs int do_wakeup_routine = 0; 4830163953Srrs 4831189790Srrs stream = tp1->rec.data.stream_number; 4832189790Srrs seq = tp1->rec.data.stream_seq; 4833270363Stuexen if (sent || !(tp1->rec.data.rcv_flags & SCTP_DATA_FIRST_FRAG)) { 4834270363Stuexen stcb->asoc.abandoned_sent[0]++; 4835270363Stuexen stcb->asoc.abandoned_sent[PR_SCTP_POLICY(tp1->flags)]++; 4836270363Stuexen stcb->asoc.strmout[stream].abandoned_sent[0]++; 4837270363Stuexen#if defined(SCTP_DETAILED_STR_STATS) 4838270363Stuexen stcb->asoc.strmout[stream].abandoned_sent[PR_SCTP_POLICY(tp1->flags)]++; 4839270363Stuexen#endif 4840270363Stuexen } else { 4841270363Stuexen stcb->asoc.abandoned_unsent[0]++; 4842270363Stuexen stcb->asoc.abandoned_unsent[PR_SCTP_POLICY(tp1->flags)]++; 4843270363Stuexen stcb->asoc.strmout[stream].abandoned_unsent[0]++; 4844270363Stuexen#if defined(SCTP_DETAILED_STR_STATS) 4845270363Stuexen stcb->asoc.strmout[stream].abandoned_unsent[PR_SCTP_POLICY(tp1->flags)]++; 4846270363Stuexen#endif 4847270363Stuexen } 4848163953Srrs do { 4849163953Srrs ret_sz += tp1->book_size; 4850189790Srrs if (tp1->data != NULL) { 4851190689Srrs if (tp1->sent < SCTP_DATAGRAM_RESEND) { 4852190689Srrs sctp_flight_size_decrease(tp1); 4853190689Srrs sctp_total_flight_decrease(stcb, tp1); 4854190689Srrs } 4855163953Srrs sctp_free_bufspace(stcb, &stcb->asoc, tp1, 1); 4856189790Srrs stcb->asoc.peers_rwnd += tp1->send_size; 4857189790Srrs stcb->asoc.peers_rwnd += SCTP_BASE_SYSCTL(sctp_peer_chunk_oh); 4858235416Stuexen if (sent) { 4859235416Stuexen sctp_ulp_notify(SCTP_NOTIFY_SENT_DG_FAIL, stcb, 0, tp1, so_locked); 4860235416Stuexen } else { 4861235416Stuexen sctp_ulp_notify(SCTP_NOTIFY_UNSENT_DG_FAIL, stcb, 0, tp1, so_locked); 4862235416Stuexen } 4863196376Stuexen if (tp1->data) { 4864196376Stuexen sctp_m_freem(tp1->data); 4865196376Stuexen tp1->data = NULL; 4866196376Stuexen } 4867189790Srrs do_wakeup_routine = 1; 4868189790Srrs if (PR_SCTP_BUF_ENABLED(tp1->flags)) { 4869189790Srrs stcb->asoc.sent_queue_cnt_removeable--; 4870172090Srrs } 4871163953Srrs } 4872190689Srrs tp1->sent = SCTP_FORWARD_TSN_SKIP; 4873163953Srrs if ((tp1->rec.data.rcv_flags & SCTP_DATA_NOT_FRAG) == 4874163953Srrs SCTP_DATA_NOT_FRAG) { 4875163953Srrs /* not frag'ed we ae done */ 4876163953Srrs notdone = 0; 4877163953Srrs foundeom = 1; 4878163953Srrs } else if (tp1->rec.data.rcv_flags & SCTP_DATA_LAST_FRAG) { 4879163953Srrs /* end of frag, we are done */ 4880163953Srrs notdone = 0; 4881163953Srrs foundeom = 1; 4882163953Srrs } else { 4883163953Srrs /* 4884163953Srrs * Its a begin or middle piece, we must mark all of 4885163953Srrs * it 4886163953Srrs */ 4887163953Srrs notdone = 1; 4888163953Srrs tp1 = TAILQ_NEXT(tp1, sctp_next); 4889163953Srrs } 4890163953Srrs } while (tp1 && notdone); 4891189790Srrs if (foundeom == 0) { 4892163953Srrs /* 4893163953Srrs * The multi-part message was scattered across the send and 4894163953Srrs * sent queue. 4895163953Srrs */ 4896216822Stuexen TAILQ_FOREACH_SAFE(tp1, &stcb->asoc.send_queue, sctp_next, tp2) { 4897216822Stuexen if ((tp1->rec.data.stream_number != stream) || 4898216822Stuexen (tp1->rec.data.stream_seq != seq)) { 4899216822Stuexen break; 4900216822Stuexen } 4901189790Srrs /* 4902189790Srrs * save to chk in case we have some on stream out 4903189790Srrs * queue. If so and we have an un-transmitted one we 4904189790Srrs * don't have to fudge the TSN. 4905189790Srrs */ 4906189790Srrs chk = tp1; 4907189790Srrs ret_sz += tp1->book_size; 4908196376Stuexen sctp_free_bufspace(stcb, &stcb->asoc, tp1, 1); 4909235416Stuexen if (sent) { 4910235416Stuexen sctp_ulp_notify(SCTP_NOTIFY_SENT_DG_FAIL, stcb, 0, tp1, so_locked); 4911235416Stuexen } else { 4912235416Stuexen sctp_ulp_notify(SCTP_NOTIFY_UNSENT_DG_FAIL, stcb, 0, tp1, so_locked); 4913235416Stuexen } 4914196376Stuexen if (tp1->data) { 4915196376Stuexen sctp_m_freem(tp1->data); 4916196376Stuexen tp1->data = NULL; 4917196376Stuexen } 4918190689Srrs /* No flight involved here book the size to 0 */ 4919190689Srrs tp1->book_size = 0; 4920189790Srrs if (tp1->rec.data.rcv_flags & SCTP_DATA_LAST_FRAG) { 4921189790Srrs foundeom = 1; 4922189790Srrs } 4923189790Srrs do_wakeup_routine = 1; 4924189790Srrs tp1->sent = SCTP_FORWARD_TSN_SKIP; 4925189790Srrs TAILQ_REMOVE(&stcb->asoc.send_queue, tp1, sctp_next); 4926189790Srrs /* 4927189790Srrs * on to the sent queue so we can wait for it to be 4928189790Srrs * passed by. 4929189790Srrs */ 4930189790Srrs TAILQ_INSERT_TAIL(&stcb->asoc.sent_queue, tp1, 4931189790Srrs sctp_next); 4932189790Srrs stcb->asoc.send_queue_cnt--; 4933189790Srrs stcb->asoc.sent_queue_cnt++; 4934163953Srrs } 4935163953Srrs } 4936189790Srrs if (foundeom == 0) { 4937189790Srrs /* 4938189790Srrs * Still no eom found. That means there is stuff left on the 4939189790Srrs * stream out queue.. yuck. 4940189790Srrs */ 4941242627Stuexen SCTP_TCB_SEND_LOCK(stcb); 4942189790Srrs strq = &stcb->asoc.strmout[stream]; 4943242627Stuexen sp = TAILQ_FIRST(&strq->outqueue); 4944242627Stuexen if (sp != NULL) { 4945242627Stuexen sp->discard_rest = 1; 4946242627Stuexen /* 4947242627Stuexen * We may need to put a chunk on the queue that 4948242627Stuexen * holds the TSN that would have been sent with the 4949242627Stuexen * LAST bit. 4950242627Stuexen */ 4951242627Stuexen if (chk == NULL) { 4952242627Stuexen /* Yep, we have to */ 4953242627Stuexen sctp_alloc_a_chunk(stcb, chk); 4954189790Srrs if (chk == NULL) { 4955189790Srrs /* 4956242627Stuexen * we are hosed. All we can do is 4957242627Stuexen * nothing.. which will cause an 4958242627Stuexen * abort if the peer is paying 4959242627Stuexen * attention. 4960189790Srrs */ 4961242627Stuexen goto oh_well; 4962189790Srrs } 4963242627Stuexen memset(chk, 0, sizeof(*chk)); 4964242627Stuexen chk->rec.data.rcv_flags = SCTP_DATA_LAST_FRAG; 4965242627Stuexen chk->sent = SCTP_FORWARD_TSN_SKIP; 4966242627Stuexen chk->asoc = &stcb->asoc; 4967242627Stuexen chk->rec.data.stream_seq = strq->next_sequence_send; 4968242627Stuexen chk->rec.data.stream_number = sp->stream; 4969242627Stuexen chk->rec.data.payloadtype = sp->ppid; 4970242627Stuexen chk->rec.data.context = sp->context; 4971242627Stuexen chk->flags = sp->act_flags; 4972283730Stuexen chk->whoTo = NULL; 4973242627Stuexen chk->rec.data.TSN_seq = atomic_fetchadd_int(&stcb->asoc.sending_seq, 1); 4974283730Stuexen strq->chunks_on_queues++; 4975242627Stuexen TAILQ_INSERT_TAIL(&stcb->asoc.sent_queue, chk, sctp_next); 4976242627Stuexen stcb->asoc.sent_queue_cnt++; 4977242627Stuexen stcb->asoc.pr_sctp_cnt++; 4978242627Stuexen } else { 4979242627Stuexen chk->rec.data.rcv_flags |= SCTP_DATA_LAST_FRAG; 4980189790Srrs } 4981242627Stuexen strq->next_sequence_send++; 4982242627Stuexen oh_well: 4983242627Stuexen if (sp->data) { 4984242627Stuexen /* 4985242627Stuexen * Pull any data to free up the SB and allow 4986242627Stuexen * sender to "add more" while we will throw 4987242627Stuexen * away :-) 4988242627Stuexen */ 4989242627Stuexen sctp_free_spbufspace(stcb, &stcb->asoc, sp); 4990242627Stuexen ret_sz += sp->length; 4991242627Stuexen do_wakeup_routine = 1; 4992242627Stuexen sp->some_taken = 1; 4993242627Stuexen sctp_m_freem(sp->data); 4994242627Stuexen sp->data = NULL; 4995242627Stuexen sp->tail_mbuf = NULL; 4996242627Stuexen sp->length = 0; 4997242627Stuexen } 4998242627Stuexen } 4999189790Srrs SCTP_TCB_SEND_UNLOCK(stcb); 5000189790Srrs } 5001189790Srrs if (do_wakeup_routine) { 5002237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 5003190689Srrs struct socket *so; 5004190689Srrs 5005189790Srrs so = SCTP_INP_SO(stcb->sctp_ep); 5006189790Srrs if (!so_locked) { 5007189790Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 5008189790Srrs SCTP_TCB_UNLOCK(stcb); 5009189790Srrs SCTP_SOCKET_LOCK(so, 1); 5010189790Srrs SCTP_TCB_LOCK(stcb); 5011189790Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 5012189790Srrs if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) { 5013189790Srrs /* assoc was freed while we were unlocked */ 5014189790Srrs SCTP_SOCKET_UNLOCK(so, 1); 5015189790Srrs return (ret_sz); 5016189790Srrs } 5017189790Srrs } 5018189790Srrs#endif 5019189790Srrs sctp_sowwakeup(stcb->sctp_ep, stcb->sctp_socket); 5020237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 5021189790Srrs if (!so_locked) { 5022189790Srrs SCTP_SOCKET_UNLOCK(so, 1); 5023189790Srrs } 5024189790Srrs#endif 5025189790Srrs } 5026163953Srrs return (ret_sz); 5027163953Srrs} 5028163953Srrs 5029163953Srrs/* 5030163953Srrs * checks to see if the given address, sa, is one that is currently known by 5031163953Srrs * the kernel note: can't distinguish the same address on multiple interfaces 5032163953Srrs * and doesn't handle multiple addresses with different zone/scope id's note: 5033163953Srrs * ifa_ifwithaddr() compares the entire sockaddr struct 5034163953Srrs */ 5035167598Srrsstruct sctp_ifa * 5036170744Srrssctp_find_ifa_in_ep(struct sctp_inpcb *inp, struct sockaddr *addr, 5037170744Srrs int holds_lock) 5038163953Srrs{ 5039167598Srrs struct sctp_laddr *laddr; 5040163953Srrs 5041169420Srrs if (holds_lock == 0) { 5042167598Srrs SCTP_INP_RLOCK(inp); 5043169420Srrs } 5044167598Srrs LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) { 5045167598Srrs if (laddr->ifa == NULL) 5046167598Srrs continue; 5047167598Srrs if (addr->sa_family != laddr->ifa->address.sa.sa_family) 5048167598Srrs continue; 5049221249Stuexen#ifdef INET 5050167598Srrs if (addr->sa_family == AF_INET) { 5051167598Srrs if (((struct sockaddr_in *)addr)->sin_addr.s_addr == 5052167598Srrs laddr->ifa->address.sin.sin_addr.s_addr) { 5053167598Srrs /* found him. */ 5054169420Srrs if (holds_lock == 0) { 5055167598Srrs SCTP_INP_RUNLOCK(inp); 5056169420Srrs } 5057167598Srrs return (laddr->ifa); 5058167598Srrs break; 5059167598Srrs } 5060178251Srrs } 5061221249Stuexen#endif 5062178251Srrs#ifdef INET6 5063178251Srrs if (addr->sa_family == AF_INET6) { 5064179157Srrs if (SCTP6_ARE_ADDR_EQUAL((struct sockaddr_in6 *)addr, 5065179157Srrs &laddr->ifa->address.sin6)) { 5066167598Srrs /* found him. */ 5067169420Srrs if (holds_lock == 0) { 5068167598Srrs SCTP_INP_RUNLOCK(inp); 5069169420Srrs } 5070167598Srrs return (laddr->ifa); 5071167598Srrs break; 5072167598Srrs } 5073167598Srrs } 5074178251Srrs#endif 5075167598Srrs } 5076169420Srrs if (holds_lock == 0) { 5077167598Srrs SCTP_INP_RUNLOCK(inp); 5078169420Srrs } 5079167598Srrs return (NULL); 5080167598Srrs} 5081163953Srrs 5082167698Srrsuint32_t 5083167698Srrssctp_get_ifa_hash_val(struct sockaddr *addr) 5084167698Srrs{ 5085221328Stuexen switch (addr->sa_family) { 5086221328Stuexen#ifdef INET 5087221328Stuexen case AF_INET: 5088221328Stuexen { 5089221328Stuexen struct sockaddr_in *sin; 5090167698Srrs 5091221328Stuexen sin = (struct sockaddr_in *)addr; 5092221328Stuexen return (sin->sin_addr.s_addr ^ (sin->sin_addr.s_addr >> 16)); 5093221328Stuexen } 5094221328Stuexen#endif 5095221328Stuexen#ifdef INET6 5096244728Stuexen case AF_INET6: 5097221328Stuexen { 5098221328Stuexen struct sockaddr_in6 *sin6; 5099221328Stuexen uint32_t hash_of_addr; 5100167698Srrs 5101221328Stuexen sin6 = (struct sockaddr_in6 *)addr; 5102221328Stuexen hash_of_addr = (sin6->sin6_addr.s6_addr32[0] + 5103221328Stuexen sin6->sin6_addr.s6_addr32[1] + 5104221328Stuexen sin6->sin6_addr.s6_addr32[2] + 5105221328Stuexen sin6->sin6_addr.s6_addr32[3]); 5106221328Stuexen hash_of_addr = (hash_of_addr ^ (hash_of_addr >> 16)); 5107221328Stuexen return (hash_of_addr); 5108221328Stuexen } 5109221328Stuexen#endif 5110221328Stuexen default: 5111221328Stuexen break; 5112167698Srrs } 5113167698Srrs return (0); 5114167698Srrs} 5115167698Srrs 5116167598Srrsstruct sctp_ifa * 5117167598Srrssctp_find_ifa_by_addr(struct sockaddr *addr, uint32_t vrf_id, int holds_lock) 5118167598Srrs{ 5119167598Srrs struct sctp_ifa *sctp_ifap; 5120167598Srrs struct sctp_vrf *vrf; 5121167698Srrs struct sctp_ifalist *hash_head; 5122167698Srrs uint32_t hash_of_addr; 5123167598Srrs 5124168299Srrs if (holds_lock == 0) 5125172218Srrs SCTP_IPI_ADDR_RLOCK(); 5126168299Srrs 5127167598Srrs vrf = sctp_find_vrf(vrf_id); 5128168299Srrs if (vrf == NULL) { 5129168299Srrs if (holds_lock == 0) 5130172218Srrs SCTP_IPI_ADDR_RUNLOCK(); 5131167598Srrs return (NULL); 5132168299Srrs } 5133167698Srrs hash_of_addr = sctp_get_ifa_hash_val(addr); 5134167598Srrs 5135169352Srrs hash_head = &vrf->vrf_addr_hash[(hash_of_addr & vrf->vrf_addr_hashmark)]; 5136168299Srrs if (hash_head == NULL) { 5137169420Srrs SCTP_PRINTF("hash_of_addr:%x mask:%x table:%x - ", 5138172218Srrs hash_of_addr, (uint32_t) vrf->vrf_addr_hashmark, 5139172218Srrs (uint32_t) (hash_of_addr & vrf->vrf_addr_hashmark)); 5140168299Srrs sctp_print_address(addr); 5141169420Srrs SCTP_PRINTF("No such bucket for address\n"); 5142168299Srrs if (holds_lock == 0) 5143172218Srrs SCTP_IPI_ADDR_RUNLOCK(); 5144168299Srrs 5145168299Srrs return (NULL); 5146168299Srrs } 5147167698Srrs LIST_FOREACH(sctp_ifap, hash_head, next_bucket) { 5148167698Srrs if (addr->sa_family != sctp_ifap->address.sa.sa_family) 5149167698Srrs continue; 5150221249Stuexen#ifdef INET 5151167698Srrs if (addr->sa_family == AF_INET) { 5152167698Srrs if (((struct sockaddr_in *)addr)->sin_addr.s_addr == 5153167698Srrs sctp_ifap->address.sin.sin_addr.s_addr) { 5154167698Srrs /* found him. */ 5155167698Srrs if (holds_lock == 0) 5156172218Srrs SCTP_IPI_ADDR_RUNLOCK(); 5157167698Srrs return (sctp_ifap); 5158167698Srrs break; 5159167698Srrs } 5160178251Srrs } 5161221249Stuexen#endif 5162178251Srrs#ifdef INET6 5163178251Srrs if (addr->sa_family == AF_INET6) { 5164179157Srrs if (SCTP6_ARE_ADDR_EQUAL((struct sockaddr_in6 *)addr, 5165179157Srrs &sctp_ifap->address.sin6)) { 5166167698Srrs /* found him. */ 5167167698Srrs if (holds_lock == 0) 5168172218Srrs SCTP_IPI_ADDR_RUNLOCK(); 5169167698Srrs return (sctp_ifap); 5170167698Srrs break; 5171167698Srrs } 5172167598Srrs } 5173178251Srrs#endif 5174167598Srrs } 5175167598Srrs if (holds_lock == 0) 5176172218Srrs SCTP_IPI_ADDR_RUNLOCK(); 5177167598Srrs return (NULL); 5178167598Srrs} 5179167598Srrs 5180163953Srrsstatic void 5181170140Srrssctp_user_rcvd(struct sctp_tcb *stcb, uint32_t * freed_so_far, int hold_rlock, 5182163953Srrs uint32_t rwnd_req) 5183163953Srrs{ 5184163953Srrs /* User pulled some data, do we need a rwnd update? */ 5185163953Srrs int r_unlocked = 0; 5186163953Srrs uint32_t dif, rwnd; 5187163953Srrs struct socket *so = NULL; 5188163953Srrs 5189163953Srrs if (stcb == NULL) 5190163953Srrs return; 5191163953Srrs 5192163996Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 5193163953Srrs 5194167736Srrs if (stcb->asoc.state & (SCTP_STATE_ABOUT_TO_BE_FREED | 5195167736Srrs SCTP_STATE_SHUTDOWN_RECEIVED | 5196170140Srrs SCTP_STATE_SHUTDOWN_ACK_SENT)) { 5197163953Srrs /* Pre-check If we are freeing no update */ 5198163953Srrs goto no_lock; 5199163953Srrs } 5200163953Srrs SCTP_INP_INCR_REF(stcb->sctp_ep); 5201163953Srrs if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) || 5202163953Srrs (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE)) { 5203163953Srrs goto out; 5204163953Srrs } 5205163953Srrs so = stcb->sctp_socket; 5206163953Srrs if (so == NULL) { 5207163953Srrs goto out; 5208163953Srrs } 5209163953Srrs atomic_add_int(&stcb->freed_by_sorcv_sincelast, *freed_so_far); 5210163953Srrs /* Have you have freed enough to look */ 5211163953Srrs *freed_so_far = 0; 5212163953Srrs /* Yep, its worth a look and the lock overhead */ 5213163953Srrs 5214163953Srrs /* Figure out what the rwnd would be */ 5215163953Srrs rwnd = sctp_calc_rwnd(stcb, &stcb->asoc); 5216163953Srrs if (rwnd >= stcb->asoc.my_last_reported_rwnd) { 5217163953Srrs dif = rwnd - stcb->asoc.my_last_reported_rwnd; 5218163953Srrs } else { 5219163953Srrs dif = 0; 5220163953Srrs } 5221163953Srrs if (dif >= rwnd_req) { 5222163953Srrs if (hold_rlock) { 5223163953Srrs SCTP_INP_READ_UNLOCK(stcb->sctp_ep); 5224163953Srrs r_unlocked = 1; 5225163953Srrs } 5226163953Srrs if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) { 5227163953Srrs /* 5228163953Srrs * One last check before we allow the guy possibly 5229163953Srrs * to get in. There is a race, where the guy has not 5230163953Srrs * reached the gate. In that case 5231163953Srrs */ 5232163953Srrs goto out; 5233163953Srrs } 5234163953Srrs SCTP_TCB_LOCK(stcb); 5235163953Srrs if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) { 5236163953Srrs /* No reports here */ 5237163953Srrs SCTP_TCB_UNLOCK(stcb); 5238163953Srrs goto out; 5239163953Srrs } 5240163953Srrs SCTP_STAT_INCR(sctps_wu_sacks_sent); 5241221627Stuexen sctp_send_sack(stcb, SCTP_SO_LOCKED); 5242185694Srrs 5243163953Srrs sctp_chunk_output(stcb->sctp_ep, stcb, 5244172090Srrs SCTP_OUTPUT_FROM_USR_RCVD, SCTP_SO_LOCKED); 5245163953Srrs /* make sure no timer is running */ 5246283823Stuexen sctp_timer_stop(SCTP_TIMER_TYPE_RECV, stcb->sctp_ep, stcb, NULL, 5247283823Stuexen SCTP_FROM_SCTPUTIL + SCTP_LOC_6); 5248163953Srrs SCTP_TCB_UNLOCK(stcb); 5249163953Srrs } else { 5250163953Srrs /* Update how much we have pending */ 5251163953Srrs stcb->freed_by_sorcv_sincelast = dif; 5252163953Srrs } 5253163953Srrsout: 5254163953Srrs if (so && r_unlocked && hold_rlock) { 5255163953Srrs SCTP_INP_READ_LOCK(stcb->sctp_ep); 5256163953Srrs } 5257163953Srrs SCTP_INP_DECR_REF(stcb->sctp_ep); 5258163953Srrsno_lock: 5259163996Srrs atomic_add_int(&stcb->asoc.refcnt, -1); 5260163953Srrs return; 5261163953Srrs} 5262163953Srrs 5263163953Srrsint 5264163953Srrssctp_sorecvmsg(struct socket *so, 5265163953Srrs struct uio *uio, 5266163953Srrs struct mbuf **mp, 5267163953Srrs struct sockaddr *from, 5268163953Srrs int fromlen, 5269163953Srrs int *msg_flags, 5270163953Srrs struct sctp_sndrcvinfo *sinfo, 5271163953Srrs int filling_sinfo) 5272163953Srrs{ 5273163953Srrs /* 5274163953Srrs * MSG flags we will look at MSG_DONTWAIT - non-blocking IO. 5275163953Srrs * MSG_PEEK - Look don't touch :-D (only valid with OUT mbuf copy 5276163953Srrs * mp=NULL thus uio is the copy method to userland) MSG_WAITALL - ?? 5277163953Srrs * On the way out we may send out any combination of: 5278163953Srrs * MSG_NOTIFICATION MSG_EOR 5279163953Srrs * 5280163953Srrs */ 5281163953Srrs struct sctp_inpcb *inp = NULL; 5282163953Srrs int my_len = 0; 5283163953Srrs int cp_len = 0, error = 0; 5284163953Srrs struct sctp_queued_to_read *control = NULL, *ctl = NULL, *nxt = NULL; 5285212713Stuexen struct mbuf *m = NULL; 5286163953Srrs struct sctp_tcb *stcb = NULL; 5287163953Srrs int wakeup_read_socket = 0; 5288163953Srrs int freecnt_applied = 0; 5289163953Srrs int out_flags = 0, in_flags = 0; 5290163953Srrs int block_allowed = 1; 5291170140Srrs uint32_t freed_so_far = 0; 5292173509Srrs uint32_t copied_so_far = 0; 5293166086Srrs int in_eeor_mode = 0; 5294163953Srrs int no_rcv_needed = 0; 5295163953Srrs uint32_t rwnd_req = 0; 5296163953Srrs int hold_sblock = 0; 5297163953Srrs int hold_rlock = 0; 5298167598Srrs int slen = 0; 5299170140Srrs uint32_t held_length = 0; 5300169236Srwatson int sockbuf_lock = 0; 5301163953Srrs 5302169352Srrs if (uio == NULL) { 5303171943Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL); 5304169352Srrs return (EINVAL); 5305169352Srrs } 5306163953Srrs if (msg_flags) { 5307163953Srrs in_flags = *msg_flags; 5308168709Srrs if (in_flags & MSG_PEEK) 5309168709Srrs SCTP_STAT_INCR(sctps_read_peeks); 5310163953Srrs } else { 5311163953Srrs in_flags = 0; 5312163953Srrs } 5313169352Srrs slen = uio->uio_resid; 5314169352Srrs 5315163953Srrs /* Pull in and set up our int flags */ 5316163953Srrs if (in_flags & MSG_OOB) { 5317163953Srrs /* Out of band's NOT supported */ 5318163953Srrs return (EOPNOTSUPP); 5319163953Srrs } 5320163953Srrs if ((in_flags & MSG_PEEK) && (mp != NULL)) { 5321171943Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL); 5322163953Srrs return (EINVAL); 5323163953Srrs } 5324163953Srrs if ((in_flags & (MSG_DONTWAIT 5325163953Srrs | MSG_NBIO 5326163953Srrs )) || 5327167598Srrs SCTP_SO_IS_NBIO(so)) { 5328163953Srrs block_allowed = 0; 5329163953Srrs } 5330163953Srrs /* setup the endpoint */ 5331163953Srrs inp = (struct sctp_inpcb *)so->so_pcb; 5332163953Srrs if (inp == NULL) { 5333171943Srrs SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTPUTIL, EFAULT); 5334163953Srrs return (EFAULT); 5335163953Srrs } 5336167736Srrs rwnd_req = (SCTP_SB_LIMIT_RCV(so) >> SCTP_RWND_HIWAT_SHIFT); 5337163953Srrs /* Must be at least a MTU's worth */ 5338163953Srrs if (rwnd_req < SCTP_MIN_RWND) 5339163953Srrs rwnd_req = SCTP_MIN_RWND; 5340163953Srrs in_eeor_mode = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXPLICIT_EOR); 5341179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_RECV_RWND_LOGGING_ENABLE) { 5342170744Srrs sctp_misc_ints(SCTP_SORECV_ENTER, 5343170744Srrs rwnd_req, in_eeor_mode, so->so_rcv.sb_cc, uio->uio_resid); 5344170744Srrs } 5345179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_RECV_RWND_LOGGING_ENABLE) { 5346170744Srrs sctp_misc_ints(SCTP_SORECV_ENTERPL, 5347170744Srrs rwnd_req, block_allowed, so->so_rcv.sb_cc, uio->uio_resid); 5348170744Srrs } 5349175845Srwatson error = sblock(&so->so_rcv, (block_allowed ? SBL_WAIT : 0)); 5350163953Srrs if (error) { 5351163953Srrs goto release_unlocked; 5352163953Srrs } 5353242680Smjg sockbuf_lock = 1; 5354163953Srrsrestart: 5355163953Srrs 5356169236Srwatson 5357163953Srrsrestart_nosblocks: 5358163953Srrs if (hold_sblock == 0) { 5359163953Srrs SOCKBUF_LOCK(&so->so_rcv); 5360163953Srrs hold_sblock = 1; 5361163953Srrs } 5362163953Srrs if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) || 5363163953Srrs (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE)) { 5364163953Srrs goto out; 5365163953Srrs } 5366235402Stuexen if ((so->so_rcv.sb_state & SBS_CANTRCVMORE) && (so->so_rcv.sb_cc == 0)) { 5367163953Srrs if (so->so_error) { 5368163953Srrs error = so->so_error; 5369166023Srrs if ((in_flags & MSG_PEEK) == 0) 5370166023Srrs so->so_error = 0; 5371174257Srrs goto out; 5372163953Srrs } else { 5373174257Srrs if (so->so_rcv.sb_cc == 0) { 5374174257Srrs /* indicate EOF */ 5375174257Srrs error = 0; 5376174257Srrs goto out; 5377174257Srrs } 5378163953Srrs } 5379163953Srrs } 5380163953Srrs if ((so->so_rcv.sb_cc <= held_length) && block_allowed) { 5381163953Srrs /* we need to wait for data */ 5382163953Srrs if ((so->so_rcv.sb_cc == 0) && 5383163953Srrs ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 5384163953Srrs (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL))) { 5385163953Srrs if ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0) { 5386163953Srrs /* 5387163953Srrs * For active open side clear flags for 5388163953Srrs * re-use passive open is blocked by 5389163953Srrs * connect. 5390163953Srrs */ 5391163953Srrs if (inp->sctp_flags & SCTP_PCB_FLAGS_WAS_ABORTED) { 5392163953Srrs /* 5393163953Srrs * You were aborted, passive side 5394163953Srrs * always hits here 5395163953Srrs */ 5396171943Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, ECONNRESET); 5397163953Srrs error = ECONNRESET; 5398163953Srrs } 5399163953Srrs so->so_state &= ~(SS_ISCONNECTING | 5400163953Srrs SS_ISDISCONNECTING | 5401163953Srrs SS_ISCONFIRMING | 5402163953Srrs SS_ISCONNECTED); 5403163953Srrs if (error == 0) { 5404163953Srrs if ((inp->sctp_flags & SCTP_PCB_FLAGS_WAS_CONNECTED) == 0) { 5405171943Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, ENOTCONN); 5406163953Srrs error = ENOTCONN; 5407163953Srrs } 5408163953Srrs } 5409163953Srrs goto out; 5410163953Srrs } 5411163953Srrs } 5412163953Srrs error = sbwait(&so->so_rcv); 5413163953Srrs if (error) { 5414163953Srrs goto out; 5415163953Srrs } 5416163953Srrs held_length = 0; 5417163953Srrs goto restart_nosblocks; 5418163953Srrs } else if (so->so_rcv.sb_cc == 0) { 5419166023Srrs if (so->so_error) { 5420166023Srrs error = so->so_error; 5421166023Srrs if ((in_flags & MSG_PEEK) == 0) 5422166023Srrs so->so_error = 0; 5423166023Srrs } else { 5424166023Srrs if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 5425166023Srrs (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) { 5426166023Srrs if ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0) { 5427166023Srrs /* 5428166023Srrs * For active open side clear flags 5429166023Srrs * for re-use passive open is 5430166023Srrs * blocked by connect. 5431166023Srrs */ 5432166023Srrs if (inp->sctp_flags & SCTP_PCB_FLAGS_WAS_ABORTED) { 5433166023Srrs /* 5434166023Srrs * You were aborted, passive 5435166023Srrs * side always hits here 5436166023Srrs */ 5437171943Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, ECONNRESET); 5438166023Srrs error = ECONNRESET; 5439166023Srrs } 5440166023Srrs so->so_state &= ~(SS_ISCONNECTING | 5441166023Srrs SS_ISDISCONNECTING | 5442166023Srrs SS_ISCONFIRMING | 5443166023Srrs SS_ISCONNECTED); 5444166023Srrs if (error == 0) { 5445166023Srrs if ((inp->sctp_flags & SCTP_PCB_FLAGS_WAS_CONNECTED) == 0) { 5446171943Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, ENOTCONN); 5447166023Srrs error = ENOTCONN; 5448166023Srrs } 5449166023Srrs } 5450166023Srrs goto out; 5451166023Srrs } 5452166023Srrs } 5453171943Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EWOULDBLOCK); 5454166023Srrs error = EWOULDBLOCK; 5455166023Srrs } 5456163953Srrs goto out; 5457163953Srrs } 5458169208Srrs if (hold_sblock == 1) { 5459169208Srrs SOCKBUF_UNLOCK(&so->so_rcv); 5460169208Srrs hold_sblock = 0; 5461169208Srrs } 5462163953Srrs /* we possibly have data we can read */ 5463169655Srrs /* sa_ignore FREED_MEMORY */ 5464163953Srrs control = TAILQ_FIRST(&inp->read_queue); 5465163953Srrs if (control == NULL) { 5466163953Srrs /* 5467163953Srrs * This could be happening since the appender did the 5468163953Srrs * increment but as not yet did the tailq insert onto the 5469163953Srrs * read_queue 5470163953Srrs */ 5471163953Srrs if (hold_rlock == 0) { 5472163953Srrs SCTP_INP_READ_LOCK(inp); 5473163953Srrs } 5474163953Srrs control = TAILQ_FIRST(&inp->read_queue); 5475163953Srrs if ((control == NULL) && (so->so_rcv.sb_cc != 0)) { 5476165220Srrs#ifdef INVARIANTS 5477163953Srrs panic("Huh, its non zero and nothing on control?"); 5478163953Srrs#endif 5479163953Srrs so->so_rcv.sb_cc = 0; 5480163953Srrs } 5481163953Srrs SCTP_INP_READ_UNLOCK(inp); 5482163953Srrs hold_rlock = 0; 5483163953Srrs goto restart; 5484163953Srrs } 5485163953Srrs if ((control->length == 0) && 5486163953Srrs (control->do_not_ref_stcb)) { 5487163953Srrs /* 5488163953Srrs * Clean up code for freeing assoc that left behind a 5489163953Srrs * pdapi.. maybe a peer in EEOR that just closed after 5490163953Srrs * sending and never indicated a EOR. 5491163953Srrs */ 5492163953Srrs if (hold_rlock == 0) { 5493163953Srrs hold_rlock = 1; 5494163953Srrs SCTP_INP_READ_LOCK(inp); 5495163953Srrs } 5496163953Srrs control->held_length = 0; 5497163953Srrs if (control->data) { 5498163953Srrs /* Hmm there is data here .. fix */ 5499170140Srrs struct mbuf *m_tmp; 5500163953Srrs int cnt = 0; 5501163953Srrs 5502170140Srrs m_tmp = control->data; 5503170140Srrs while (m_tmp) { 5504170140Srrs cnt += SCTP_BUF_LEN(m_tmp); 5505170140Srrs if (SCTP_BUF_NEXT(m_tmp) == NULL) { 5506170140Srrs control->tail_mbuf = m_tmp; 5507163953Srrs control->end_added = 1; 5508163953Srrs } 5509170140Srrs m_tmp = SCTP_BUF_NEXT(m_tmp); 5510163953Srrs } 5511163953Srrs control->length = cnt; 5512163953Srrs } else { 5513163953Srrs /* remove it */ 5514163953Srrs TAILQ_REMOVE(&inp->read_queue, control, next); 5515163953Srrs /* Add back any hiddend data */ 5516163953Srrs sctp_free_remote_addr(control->whoFrom); 5517163953Srrs sctp_free_a_readq(stcb, control); 5518163953Srrs } 5519163953Srrs if (hold_rlock) { 5520163953Srrs hold_rlock = 0; 5521163953Srrs SCTP_INP_READ_UNLOCK(inp); 5522163953Srrs } 5523163953Srrs goto restart; 5524163953Srrs } 5525196260Stuexen if ((control->length == 0) && 5526196260Stuexen (control->end_added == 1)) { 5527196260Stuexen /* 5528196260Stuexen * Do we also need to check for (control->pdapi_aborted == 5529196260Stuexen * 1)? 5530196260Stuexen */ 5531196260Stuexen if (hold_rlock == 0) { 5532196260Stuexen hold_rlock = 1; 5533196260Stuexen SCTP_INP_READ_LOCK(inp); 5534196260Stuexen } 5535196260Stuexen TAILQ_REMOVE(&inp->read_queue, control, next); 5536196260Stuexen if (control->data) { 5537196260Stuexen#ifdef INVARIANTS 5538196260Stuexen panic("control->data not null but control->length == 0"); 5539196260Stuexen#else 5540196260Stuexen SCTP_PRINTF("Strange, data left in the control buffer. Cleaning up.\n"); 5541196260Stuexen sctp_m_freem(control->data); 5542196260Stuexen control->data = NULL; 5543196260Stuexen#endif 5544196260Stuexen } 5545196260Stuexen if (control->aux_data) { 5546196260Stuexen sctp_m_free(control->aux_data); 5547196260Stuexen control->aux_data = NULL; 5548196260Stuexen } 5549196260Stuexen sctp_free_remote_addr(control->whoFrom); 5550196260Stuexen sctp_free_a_readq(stcb, control); 5551196260Stuexen if (hold_rlock) { 5552196260Stuexen hold_rlock = 0; 5553196260Stuexen SCTP_INP_READ_UNLOCK(inp); 5554196260Stuexen } 5555196260Stuexen goto restart; 5556196260Stuexen } 5557163953Srrs if (control->length == 0) { 5558163953Srrs if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE)) && 5559163953Srrs (filling_sinfo)) { 5560163953Srrs /* find a more suitable one then this */ 5561163953Srrs ctl = TAILQ_NEXT(control, next); 5562163953Srrs while (ctl) { 5563168943Srrs if ((ctl->stcb != control->stcb) && (ctl->length) && 5564168943Srrs (ctl->some_taken || 5565169352Srrs (ctl->spec_flags & M_NOTIFICATION) || 5566168943Srrs ((ctl->do_not_ref_stcb == 0) && 5567168943Srrs (ctl->stcb->asoc.strmin[ctl->sinfo_stream].delivery_started == 0))) 5568168943Srrs ) { 5569168943Srrs /*- 5570168943Srrs * If we have a different TCB next, and there is data 5571168943Srrs * present. If we have already taken some (pdapi), OR we can 5572168943Srrs * ref the tcb and no delivery as started on this stream, we 5573169352Srrs * take it. Note we allow a notification on a different 5574169352Srrs * assoc to be delivered.. 5575168943Srrs */ 5576163953Srrs control = ctl; 5577163953Srrs goto found_one; 5578168943Srrs } else if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS)) && 5579168943Srrs (ctl->length) && 5580168943Srrs ((ctl->some_taken) || 5581168943Srrs ((ctl->do_not_ref_stcb == 0) && 5582169352Srrs ((ctl->spec_flags & M_NOTIFICATION) == 0) && 5583206137Stuexen (ctl->stcb->asoc.strmin[ctl->sinfo_stream].delivery_started == 0)))) { 5584168943Srrs /*- 5585168943Srrs * If we have the same tcb, and there is data present, and we 5586168943Srrs * have the strm interleave feature present. Then if we have 5587168943Srrs * taken some (pdapi) or we can refer to tht tcb AND we have 5588168943Srrs * not started a delivery for this stream, we can take it. 5589169352Srrs * Note we do NOT allow a notificaiton on the same assoc to 5590169352Srrs * be delivered. 5591168943Srrs */ 5592168943Srrs control = ctl; 5593168943Srrs goto found_one; 5594163953Srrs } 5595163953Srrs ctl = TAILQ_NEXT(ctl, next); 5596163953Srrs } 5597163953Srrs } 5598163953Srrs /* 5599163953Srrs * if we reach here, not suitable replacement is available 5600163953Srrs * <or> fragment interleave is NOT on. So stuff the sb_cc 5601163953Srrs * into the our held count, and its time to sleep again. 5602163953Srrs */ 5603163953Srrs held_length = so->so_rcv.sb_cc; 5604163953Srrs control->held_length = so->so_rcv.sb_cc; 5605163953Srrs goto restart; 5606163953Srrs } 5607163953Srrs /* Clear the held length since there is something to read */ 5608163953Srrs control->held_length = 0; 5609163953Srrs if (hold_rlock) { 5610163953Srrs SCTP_INP_READ_UNLOCK(inp); 5611163953Srrs hold_rlock = 0; 5612163953Srrs } 5613163953Srrsfound_one: 5614163953Srrs /* 5615163953Srrs * If we reach here, control has a some data for us to read off. 5616163953Srrs * Note that stcb COULD be NULL. 5617163953Srrs */ 5618174323Srrs control->some_taken++; 5619163953Srrs if (hold_sblock) { 5620163953Srrs SOCKBUF_UNLOCK(&so->so_rcv); 5621163953Srrs hold_sblock = 0; 5622163953Srrs } 5623163953Srrs stcb = control->stcb; 5624163953Srrs if (stcb) { 5625170138Srrs if ((control->do_not_ref_stcb == 0) && 5626170138Srrs (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED)) { 5627163996Srrs if (freecnt_applied == 0) 5628163996Srrs stcb = NULL; 5629163953Srrs } else if (control->do_not_ref_stcb == 0) { 5630163953Srrs /* you can't free it on me please */ 5631163953Srrs /* 5632163953Srrs * The lock on the socket buffer protects us so the 5633163953Srrs * free code will stop. But since we used the 5634163953Srrs * socketbuf lock and the sender uses the tcb_lock 5635163953Srrs * to increment, we need to use the atomic add to 5636163953Srrs * the refcnt 5637163953Srrs */ 5638172396Srrs if (freecnt_applied) { 5639172396Srrs#ifdef INVARIANTS 5640170091Srrs panic("refcnt already incremented"); 5641172396Srrs#else 5642234995Stuexen SCTP_PRINTF("refcnt already incremented?\n"); 5643172396Srrs#endif 5644172396Srrs } else { 5645172396Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 5646172396Srrs freecnt_applied = 1; 5647172396Srrs } 5648163953Srrs /* 5649163953Srrs * Setup to remember how much we have not yet told 5650163953Srrs * the peer our rwnd has opened up. Note we grab the 5651163953Srrs * value from the tcb from last time. Note too that 5652170138Srrs * sack sending clears this when a sack is sent, 5653163953Srrs * which is fine. Once we hit the rwnd_req, we then 5654163953Srrs * will go to the sctp_user_rcvd() that will not 5655163953Srrs * lock until it KNOWs it MUST send a WUP-SACK. 5656163953Srrs */ 5657163953Srrs freed_so_far = stcb->freed_by_sorcv_sincelast; 5658163953Srrs stcb->freed_by_sorcv_sincelast = 0; 5659163953Srrs } 5660163953Srrs } 5661169352Srrs if (stcb && 5662169352Srrs ((control->spec_flags & M_NOTIFICATION) == 0) && 5663169295Srrs control->do_not_ref_stcb == 0) { 5664169208Srrs stcb->asoc.strmin[control->sinfo_stream].delivery_started = 1; 5665169208Srrs } 5666163953Srrs /* First lets get off the sinfo and sockaddr info */ 5667163953Srrs if ((sinfo) && filling_sinfo) { 5668163953Srrs memcpy(sinfo, control, sizeof(struct sctp_nonpad_sndrcvinfo)); 5669163953Srrs nxt = TAILQ_NEXT(control, next); 5670223132Stuexen if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXT_RCVINFO) || 5671223132Stuexen sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVNXTINFO)) { 5672163953Srrs struct sctp_extrcvinfo *s_extra; 5673163953Srrs 5674163953Srrs s_extra = (struct sctp_extrcvinfo *)sinfo; 5675168943Srrs if ((nxt) && 5676168943Srrs (nxt->length)) { 5677294178Stuexen s_extra->serinfo_next_flags = SCTP_NEXT_MSG_AVAIL; 5678163953Srrs if (nxt->sinfo_flags & SCTP_UNORDERED) { 5679294178Stuexen s_extra->serinfo_next_flags |= SCTP_NEXT_MSG_IS_UNORDERED; 5680163953Srrs } 5681166675Srrs if (nxt->spec_flags & M_NOTIFICATION) { 5682294178Stuexen s_extra->serinfo_next_flags |= SCTP_NEXT_MSG_IS_NOTIFICATION; 5683166675Srrs } 5684294178Stuexen s_extra->serinfo_next_aid = nxt->sinfo_assoc_id; 5685294178Stuexen s_extra->serinfo_next_length = nxt->length; 5686294178Stuexen s_extra->serinfo_next_ppid = nxt->sinfo_ppid; 5687294178Stuexen s_extra->serinfo_next_stream = nxt->sinfo_stream; 5688163953Srrs if (nxt->tail_mbuf != NULL) { 5689165647Srrs if (nxt->end_added) { 5690294178Stuexen s_extra->serinfo_next_flags |= SCTP_NEXT_MSG_ISCOMPLETE; 5691163953Srrs } 5692163953Srrs } 5693163953Srrs } else { 5694163953Srrs /* 5695163953Srrs * we explicitly 0 this, since the memcpy 5696163953Srrs * got some other things beyond the older 5697163953Srrs * sinfo_ that is on the control's structure 5698163953Srrs * :-D 5699163953Srrs */ 5700168943Srrs nxt = NULL; 5701294178Stuexen s_extra->serinfo_next_flags = SCTP_NO_NEXT_MSG; 5702294178Stuexen s_extra->serinfo_next_aid = 0; 5703294178Stuexen s_extra->serinfo_next_length = 0; 5704294178Stuexen s_extra->serinfo_next_ppid = 0; 5705294178Stuexen s_extra->serinfo_next_stream = 0; 5706163953Srrs } 5707163953Srrs } 5708163953Srrs /* 5709163953Srrs * update off the real current cum-ack, if we have an stcb. 5710163953Srrs */ 5711170138Srrs if ((control->do_not_ref_stcb == 0) && stcb) 5712163953Srrs sinfo->sinfo_cumtsn = stcb->asoc.cumulative_tsn; 5713163953Srrs /* 5714163953Srrs * mask off the high bits, we keep the actual chunk bits in 5715163953Srrs * there. 5716163953Srrs */ 5717163953Srrs sinfo->sinfo_flags &= 0x00ff; 5718170354Srrs if ((control->sinfo_flags >> 8) & SCTP_DATA_UNORDERED) { 5719170354Srrs sinfo->sinfo_flags |= SCTP_UNORDERED; 5720170354Srrs } 5721163953Srrs } 5722171477Srrs#ifdef SCTP_ASOCLOG_OF_TSNS 5723171477Srrs { 5724171477Srrs int index, newindex; 5725171477Srrs struct sctp_pcbtsn_rlog *entry; 5726171477Srrs 5727171477Srrs do { 5728171477Srrs index = inp->readlog_index; 5729171477Srrs newindex = index + 1; 5730171477Srrs if (newindex >= SCTP_READ_LOG_SIZE) { 5731171477Srrs newindex = 0; 5732171477Srrs } 5733171477Srrs } while (atomic_cmpset_int(&inp->readlog_index, index, newindex) == 0); 5734171477Srrs entry = &inp->readlog[index]; 5735171477Srrs entry->vtag = control->sinfo_assoc_id; 5736171477Srrs entry->strm = control->sinfo_stream; 5737171477Srrs entry->seq = control->sinfo_ssn; 5738171477Srrs entry->sz = control->length; 5739171477Srrs entry->flgs = control->sinfo_flags; 5740171477Srrs } 5741171477Srrs#endif 5742283699Stuexen if ((fromlen > 0) && (from != NULL)) { 5743283699Stuexen union sctp_sockstore store; 5744283699Stuexen size_t len; 5745283699Stuexen 5746233311Stuexen switch (control->whoFrom->ro._l_addr.sa.sa_family) { 5747233311Stuexen#ifdef INET6 5748233311Stuexen case AF_INET6: 5749283699Stuexen len = sizeof(struct sockaddr_in6); 5750283699Stuexen store.sin6 = control->whoFrom->ro._l_addr.sin6; 5751283699Stuexen store.sin6.sin6_port = control->port_from; 5752233311Stuexen break; 5753233311Stuexen#endif 5754167598Srrs#ifdef INET 5755233311Stuexen case AF_INET: 5756283699Stuexen#ifdef INET6 5757283699Stuexen if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) { 5758283699Stuexen len = sizeof(struct sockaddr_in6); 5759283699Stuexen in6_sin_2_v4mapsin6(&control->whoFrom->ro._l_addr.sin, 5760283699Stuexen &store.sin6); 5761283699Stuexen store.sin6.sin6_port = control->port_from; 5762283699Stuexen } else { 5763283699Stuexen len = sizeof(struct sockaddr_in); 5764283699Stuexen store.sin = control->whoFrom->ro._l_addr.sin; 5765283699Stuexen store.sin.sin_port = control->port_from; 5766283699Stuexen } 5767283699Stuexen#else 5768283699Stuexen len = sizeof(struct sockaddr_in); 5769283699Stuexen store.sin = control->whoFrom->ro._l_addr.sin; 5770283699Stuexen store.sin.sin_port = control->port_from; 5771283699Stuexen#endif 5772233311Stuexen break; 5773233311Stuexen#endif 5774233311Stuexen default: 5775283699Stuexen len = 0; 5776233311Stuexen break; 5777233311Stuexen } 5778283699Stuexen memcpy(from, &store, min((size_t)fromlen, len)); 5779238475Stuexen#ifdef INET6 5780163953Srrs { 5781233311Stuexen struct sockaddr_in6 lsa6, *from6; 5782163953Srrs 5783233311Stuexen from6 = (struct sockaddr_in6 *)from; 5784233311Stuexen sctp_recover_scope_mac(from6, (&lsa6)); 5785163953Srrs } 5786163953Srrs#endif 5787163953Srrs } 5788163953Srrs /* now copy out what data we can */ 5789163953Srrs if (mp == NULL) { 5790163953Srrs /* copy out each mbuf in the chain up to length */ 5791163953Srrsget_more_data: 5792163953Srrs m = control->data; 5793163953Srrs while (m) { 5794163953Srrs /* Move out all we can */ 5795163953Srrs cp_len = (int)uio->uio_resid; 5796165647Srrs my_len = (int)SCTP_BUF_LEN(m); 5797163953Srrs if (cp_len > my_len) { 5798163953Srrs /* not enough in this buf */ 5799163953Srrs cp_len = my_len; 5800163953Srrs } 5801163953Srrs if (hold_rlock) { 5802163953Srrs SCTP_INP_READ_UNLOCK(inp); 5803163953Srrs hold_rlock = 0; 5804163953Srrs } 5805163953Srrs if (cp_len > 0) 5806163953Srrs error = uiomove(mtod(m, char *), cp_len, uio); 5807163953Srrs /* re-read */ 5808163953Srrs if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) { 5809163953Srrs goto release; 5810163953Srrs } 5811170138Srrs if ((control->do_not_ref_stcb == 0) && stcb && 5812163953Srrs stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) { 5813163953Srrs no_rcv_needed = 1; 5814163953Srrs } 5815163953Srrs if (error) { 5816163953Srrs /* error we are out of here */ 5817163953Srrs goto release; 5818163953Srrs } 5819165647Srrs if ((SCTP_BUF_NEXT(m) == NULL) && 5820165647Srrs (cp_len >= SCTP_BUF_LEN(m)) && 5821163953Srrs ((control->end_added == 0) || 5822170138Srrs (control->end_added && 5823170138Srrs (TAILQ_NEXT(control, next) == NULL))) 5824163953Srrs ) { 5825163953Srrs SCTP_INP_READ_LOCK(inp); 5826163953Srrs hold_rlock = 1; 5827163953Srrs } 5828165647Srrs if (cp_len == SCTP_BUF_LEN(m)) { 5829165647Srrs if ((SCTP_BUF_NEXT(m) == NULL) && 5830165647Srrs (control->end_added)) { 5831163953Srrs out_flags |= MSG_EOR; 5832212225Srrs if ((control->do_not_ref_stcb == 0) && 5833212225Srrs (control->stcb != NULL) && 5834212225Srrs ((control->spec_flags & M_NOTIFICATION) == 0)) 5835168961Srrs control->stcb->asoc.strmin[control->sinfo_stream].delivery_started = 0; 5836163953Srrs } 5837165647Srrs if (control->spec_flags & M_NOTIFICATION) { 5838163953Srrs out_flags |= MSG_NOTIFICATION; 5839163953Srrs } 5840163953Srrs /* we ate up the mbuf */ 5841163953Srrs if (in_flags & MSG_PEEK) { 5842163953Srrs /* just looking */ 5843165647Srrs m = SCTP_BUF_NEXT(m); 5844163953Srrs copied_so_far += cp_len; 5845163953Srrs } else { 5846163953Srrs /* dispose of the mbuf */ 5847179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) { 5848170744Srrs sctp_sblog(&so->so_rcv, 5849170744Srrs control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBFREE, SCTP_BUF_LEN(m)); 5850170744Srrs } 5851163953Srrs sctp_sbfree(control, stcb, &so->so_rcv, m); 5852179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) { 5853170744Srrs sctp_sblog(&so->so_rcv, 5854170744Srrs control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBRESULT, 0); 5855170744Srrs } 5856163953Srrs copied_so_far += cp_len; 5857163953Srrs freed_so_far += cp_len; 5858171943Srrs freed_so_far += MSIZE; 5859171477Srrs atomic_subtract_int(&control->length, cp_len); 5860163953Srrs control->data = sctp_m_free(m); 5861163953Srrs m = control->data; 5862163953Srrs /* 5863163953Srrs * been through it all, must hold sb 5864163953Srrs * lock ok to null tail 5865163953Srrs */ 5866163953Srrs if (control->data == NULL) { 5867165220Srrs#ifdef INVARIANTS 5868163953Srrs if ((control->end_added == 0) || 5869163953Srrs (TAILQ_NEXT(control, next) == NULL)) { 5870163953Srrs /* 5871163953Srrs * If the end is not 5872163953Srrs * added, OR the 5873163953Srrs * next is NOT null 5874163953Srrs * we MUST have the 5875163953Srrs * lock. 5876163953Srrs */ 5877163953Srrs if (mtx_owned(&inp->inp_rdata_mtx) == 0) { 5878163953Srrs panic("Hmm we don't own the lock?"); 5879163953Srrs } 5880163953Srrs } 5881163953Srrs#endif 5882163953Srrs control->tail_mbuf = NULL; 5883165220Srrs#ifdef INVARIANTS 5884163953Srrs if ((control->end_added) && ((out_flags & MSG_EOR) == 0)) { 5885163953Srrs panic("end_added, nothing left and no MSG_EOR"); 5886163953Srrs } 5887163953Srrs#endif 5888163953Srrs } 5889163953Srrs } 5890163953Srrs } else { 5891163953Srrs /* Do we need to trim the mbuf? */ 5892165647Srrs if (control->spec_flags & M_NOTIFICATION) { 5893163953Srrs out_flags |= MSG_NOTIFICATION; 5894163953Srrs } 5895163953Srrs if ((in_flags & MSG_PEEK) == 0) { 5896165647Srrs SCTP_BUF_RESV_UF(m, cp_len); 5897165647Srrs SCTP_BUF_LEN(m) -= cp_len; 5898179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) { 5899170744Srrs sctp_sblog(&so->so_rcv, control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBFREE, cp_len); 5900170744Srrs } 5901163953Srrs atomic_subtract_int(&so->so_rcv.sb_cc, cp_len); 5902170138Srrs if ((control->do_not_ref_stcb == 0) && 5903170138Srrs stcb) { 5904163953Srrs atomic_subtract_int(&stcb->asoc.sb_cc, cp_len); 5905163953Srrs } 5906163953Srrs copied_so_far += cp_len; 5907163953Srrs freed_so_far += cp_len; 5908171943Srrs freed_so_far += MSIZE; 5909179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) { 5910170744Srrs sctp_sblog(&so->so_rcv, control->do_not_ref_stcb ? NULL : stcb, 5911170744Srrs SCTP_LOG_SBRESULT, 0); 5912170744Srrs } 5913171477Srrs atomic_subtract_int(&control->length, cp_len); 5914163953Srrs } else { 5915163953Srrs copied_so_far += cp_len; 5916163953Srrs } 5917163953Srrs } 5918170056Srrs if ((out_flags & MSG_EOR) || (uio->uio_resid == 0)) { 5919163953Srrs break; 5920163953Srrs } 5921163953Srrs if (((stcb) && (in_flags & MSG_PEEK) == 0) && 5922163953Srrs (control->do_not_ref_stcb == 0) && 5923163953Srrs (freed_so_far >= rwnd_req)) { 5924163953Srrs sctp_user_rcvd(stcb, &freed_so_far, hold_rlock, rwnd_req); 5925163953Srrs } 5926163953Srrs } /* end while(m) */ 5927163953Srrs /* 5928163953Srrs * At this point we have looked at it all and we either have 5929163953Srrs * a MSG_EOR/or read all the user wants... <OR> 5930163953Srrs * control->length == 0. 5931163953Srrs */ 5932170056Srrs if ((out_flags & MSG_EOR) && ((in_flags & MSG_PEEK) == 0)) { 5933163953Srrs /* we are done with this control */ 5934163953Srrs if (control->length == 0) { 5935163953Srrs if (control->data) { 5936165220Srrs#ifdef INVARIANTS 5937163953Srrs panic("control->data not null at read eor?"); 5938163953Srrs#else 5939169420Srrs SCTP_PRINTF("Strange, data left in the control buffer .. invarients would panic?\n"); 5940163953Srrs sctp_m_freem(control->data); 5941163953Srrs control->data = NULL; 5942163953Srrs#endif 5943163953Srrs } 5944163953Srrs done_with_control: 5945163953Srrs if (TAILQ_NEXT(control, next) == NULL) { 5946163953Srrs /* 5947163953Srrs * If we don't have a next we need a 5948172703Srrs * lock, if there is a next 5949172703Srrs * interrupt is filling ahead of us 5950172703Srrs * and we don't need a lock to 5951172703Srrs * remove this guy (which is the 5952172703Srrs * head of the queue). 5953163953Srrs */ 5954163953Srrs if (hold_rlock == 0) { 5955163953Srrs SCTP_INP_READ_LOCK(inp); 5956163953Srrs hold_rlock = 1; 5957163953Srrs } 5958163953Srrs } 5959163953Srrs TAILQ_REMOVE(&inp->read_queue, control, next); 5960163953Srrs /* Add back any hiddend data */ 5961163953Srrs if (control->held_length) { 5962163953Srrs held_length = 0; 5963163953Srrs control->held_length = 0; 5964163953Srrs wakeup_read_socket = 1; 5965163953Srrs } 5966169352Srrs if (control->aux_data) { 5967169352Srrs sctp_m_free(control->aux_data); 5968169352Srrs control->aux_data = NULL; 5969169352Srrs } 5970163953Srrs no_rcv_needed = control->do_not_ref_stcb; 5971163953Srrs sctp_free_remote_addr(control->whoFrom); 5972163953Srrs control->data = NULL; 5973163953Srrs sctp_free_a_readq(stcb, control); 5974163953Srrs control = NULL; 5975170138Srrs if ((freed_so_far >= rwnd_req) && 5976170138Srrs (no_rcv_needed == 0)) 5977163953Srrs sctp_user_rcvd(stcb, &freed_so_far, hold_rlock, rwnd_req); 5978163953Srrs 5979163953Srrs } else { 5980163953Srrs /* 5981163953Srrs * The user did not read all of this 5982163953Srrs * message, turn off the returned MSG_EOR 5983163953Srrs * since we are leaving more behind on the 5984163953Srrs * control to read. 5985163953Srrs */ 5986165220Srrs#ifdef INVARIANTS 5987170138Srrs if (control->end_added && 5988170138Srrs (control->data == NULL) && 5989163953Srrs (control->tail_mbuf == NULL)) { 5990163953Srrs panic("Gak, control->length is corrupt?"); 5991163953Srrs } 5992163953Srrs#endif 5993163953Srrs no_rcv_needed = control->do_not_ref_stcb; 5994163953Srrs out_flags &= ~MSG_EOR; 5995163953Srrs } 5996163953Srrs } 5997163953Srrs if (out_flags & MSG_EOR) { 5998163953Srrs goto release; 5999163953Srrs } 6000163953Srrs if ((uio->uio_resid == 0) || 6001260426Stuexen ((in_eeor_mode) && 6002260426Stuexen (copied_so_far >= (uint32_t) max(so->so_rcv.sb_lowat, 1)))) { 6003163953Srrs goto release; 6004163953Srrs } 6005163953Srrs /* 6006163953Srrs * If I hit here the receiver wants more and this message is 6007163953Srrs * NOT done (pd-api). So two questions. Can we block? if not 6008163953Srrs * we are done. Did the user NOT set MSG_WAITALL? 6009163953Srrs */ 6010163953Srrs if (block_allowed == 0) { 6011163953Srrs goto release; 6012163953Srrs } 6013163953Srrs /* 6014163953Srrs * We need to wait for more data a few things: - We don't 6015163953Srrs * sbunlock() so we don't get someone else reading. - We 6016163953Srrs * must be sure to account for the case where what is added 6017163953Srrs * is NOT to our control when we wakeup. 6018163953Srrs */ 6019163953Srrs 6020163953Srrs /* 6021163953Srrs * Do we need to tell the transport a rwnd update might be 6022163953Srrs * needed before we go to sleep? 6023163953Srrs */ 6024163953Srrs if (((stcb) && (in_flags & MSG_PEEK) == 0) && 6025163953Srrs ((freed_so_far >= rwnd_req) && 6026163953Srrs (control->do_not_ref_stcb == 0) && 6027163953Srrs (no_rcv_needed == 0))) { 6028163953Srrs sctp_user_rcvd(stcb, &freed_so_far, hold_rlock, rwnd_req); 6029163953Srrs } 6030163953Srrswait_some_more: 6031166023Srrs if (so->so_rcv.sb_state & SBS_CANTRCVMORE) { 6032163953Srrs goto release; 6033163953Srrs } 6034163953Srrs if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) 6035163953Srrs goto release; 6036163953Srrs 6037163953Srrs if (hold_rlock == 1) { 6038163953Srrs SCTP_INP_READ_UNLOCK(inp); 6039163953Srrs hold_rlock = 0; 6040163953Srrs } 6041163953Srrs if (hold_sblock == 0) { 6042163953Srrs SOCKBUF_LOCK(&so->so_rcv); 6043163953Srrs hold_sblock = 1; 6044163953Srrs } 6045172091Srrs if ((copied_so_far) && (control->length == 0) && 6046206137Stuexen (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE))) { 6047172091Srrs goto release; 6048172091Srrs } 6049163953Srrs if (so->so_rcv.sb_cc <= control->held_length) { 6050163953Srrs error = sbwait(&so->so_rcv); 6051163953Srrs if (error) { 6052163953Srrs goto release; 6053163953Srrs } 6054163953Srrs control->held_length = 0; 6055163953Srrs } 6056163953Srrs if (hold_sblock) { 6057163953Srrs SOCKBUF_UNLOCK(&so->so_rcv); 6058163953Srrs hold_sblock = 0; 6059163953Srrs } 6060163953Srrs if (control->length == 0) { 6061163953Srrs /* still nothing here */ 6062163953Srrs if (control->end_added == 1) { 6063163953Srrs /* he aborted, or is done i.e.did a shutdown */ 6064163953Srrs out_flags |= MSG_EOR; 6065168943Srrs if (control->pdapi_aborted) { 6066169295Srrs if ((control->do_not_ref_stcb == 0) && ((control->spec_flags & M_NOTIFICATION) == 0)) 6067168961Srrs control->stcb->asoc.strmin[control->sinfo_stream].delivery_started = 0; 6068168943Srrs 6069164085Srrs out_flags |= MSG_TRUNC; 6070168943Srrs } else { 6071169295Srrs if ((control->do_not_ref_stcb == 0) && ((control->spec_flags & M_NOTIFICATION) == 0)) 6072168961Srrs control->stcb->asoc.strmin[control->sinfo_stream].delivery_started = 0; 6073168943Srrs } 6074163953Srrs goto done_with_control; 6075163953Srrs } 6076163953Srrs if (so->so_rcv.sb_cc > held_length) { 6077163953Srrs control->held_length = so->so_rcv.sb_cc; 6078163953Srrs held_length = 0; 6079163953Srrs } 6080163953Srrs goto wait_some_more; 6081163953Srrs } else if (control->data == NULL) { 6082163996Srrs /* 6083163996Srrs * we must re-sync since data is probably being 6084163996Srrs * added 6085163996Srrs */ 6086163996Srrs SCTP_INP_READ_LOCK(inp); 6087163996Srrs if ((control->length > 0) && (control->data == NULL)) { 6088163996Srrs /* 6089163996Srrs * big trouble.. we have the lock and its 6090163996Srrs * corrupt? 6091163996Srrs */ 6092174323Srrs#ifdef INVARIANTS 6093163996Srrs panic("Impossible data==NULL length !=0"); 6094174323Srrs#endif 6095174323Srrs out_flags |= MSG_EOR; 6096174323Srrs out_flags |= MSG_TRUNC; 6097174323Srrs control->length = 0; 6098174323Srrs SCTP_INP_READ_UNLOCK(inp); 6099174323Srrs goto done_with_control; 6100163996Srrs } 6101163996Srrs SCTP_INP_READ_UNLOCK(inp); 6102163996Srrs /* We will fall around to get more data */ 6103163953Srrs } 6104163953Srrs goto get_more_data; 6105163953Srrs } else { 6106169352Srrs /*- 6107169352Srrs * Give caller back the mbuf chain, 6108169352Srrs * store in uio_resid the length 6109163953Srrs */ 6110169352Srrs wakeup_read_socket = 0; 6111169352Srrs if ((control->end_added == 0) || 6112169352Srrs (TAILQ_NEXT(control, next) == NULL)) { 6113169352Srrs /* Need to get rlock */ 6114169352Srrs if (hold_rlock == 0) { 6115169352Srrs SCTP_INP_READ_LOCK(inp); 6116169352Srrs hold_rlock = 1; 6117163953Srrs } 6118169352Srrs } 6119169352Srrs if (control->end_added) { 6120169352Srrs out_flags |= MSG_EOR; 6121228907Stuexen if ((control->do_not_ref_stcb == 0) && 6122228907Stuexen (control->stcb != NULL) && 6123228907Stuexen ((control->spec_flags & M_NOTIFICATION) == 0)) 6124169352Srrs control->stcb->asoc.strmin[control->sinfo_stream].delivery_started = 0; 6125169352Srrs } 6126169352Srrs if (control->spec_flags & M_NOTIFICATION) { 6127169352Srrs out_flags |= MSG_NOTIFICATION; 6128169352Srrs } 6129169352Srrs uio->uio_resid = control->length; 6130169352Srrs *mp = control->data; 6131169352Srrs m = control->data; 6132169352Srrs while (m) { 6133179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) { 6134170744Srrs sctp_sblog(&so->so_rcv, 6135170744Srrs control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBFREE, SCTP_BUF_LEN(m)); 6136170744Srrs } 6137169352Srrs sctp_sbfree(control, stcb, &so->so_rcv, m); 6138169352Srrs freed_so_far += SCTP_BUF_LEN(m); 6139171943Srrs freed_so_far += MSIZE; 6140179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) { 6141170744Srrs sctp_sblog(&so->so_rcv, 6142170744Srrs control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBRESULT, 0); 6143170744Srrs } 6144169352Srrs m = SCTP_BUF_NEXT(m); 6145163953Srrs } 6146169352Srrs control->data = control->tail_mbuf = NULL; 6147169352Srrs control->length = 0; 6148169352Srrs if (out_flags & MSG_EOR) { 6149169352Srrs /* Done with this control */ 6150169352Srrs goto done_with_control; 6151169352Srrs } 6152163953Srrs } 6153163953Srrsrelease: 6154163953Srrs if (hold_rlock == 1) { 6155163953Srrs SCTP_INP_READ_UNLOCK(inp); 6156163953Srrs hold_rlock = 0; 6157163953Srrs } 6158169236Srwatson if (hold_sblock == 1) { 6159169236Srwatson SOCKBUF_UNLOCK(&so->so_rcv); 6160169236Srwatson hold_sblock = 0; 6161163953Srrs } 6162163953Srrs sbunlock(&so->so_rcv); 6163169236Srwatson sockbuf_lock = 0; 6164163953Srrs 6165163953Srrsrelease_unlocked: 6166163953Srrs if (hold_sblock) { 6167163953Srrs SOCKBUF_UNLOCK(&so->so_rcv); 6168163953Srrs hold_sblock = 0; 6169163953Srrs } 6170163953Srrs if ((stcb) && (in_flags & MSG_PEEK) == 0) { 6171163953Srrs if ((freed_so_far >= rwnd_req) && 6172163953Srrs (control && (control->do_not_ref_stcb == 0)) && 6173163953Srrs (no_rcv_needed == 0)) 6174163953Srrs sctp_user_rcvd(stcb, &freed_so_far, hold_rlock, rwnd_req); 6175163953Srrs } 6176184031Srrsout: 6177184031Srrs if (msg_flags) { 6178174323Srrs *msg_flags = out_flags; 6179184031Srrs } 6180168943Srrs if (((out_flags & MSG_EOR) == 0) && 6181168943Srrs ((in_flags & MSG_PEEK) == 0) && 6182168943Srrs (sinfo) && 6183223132Stuexen (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXT_RCVINFO) || 6184223132Stuexen sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVNXTINFO))) { 6185168943Srrs struct sctp_extrcvinfo *s_extra; 6186168943Srrs 6187168943Srrs s_extra = (struct sctp_extrcvinfo *)sinfo; 6188294178Stuexen s_extra->serinfo_next_flags = SCTP_NO_NEXT_MSG; 6189168943Srrs } 6190163953Srrs if (hold_rlock == 1) { 6191163953Srrs SCTP_INP_READ_UNLOCK(inp); 6192163953Srrs } 6193163953Srrs if (hold_sblock) { 6194163953Srrs SOCKBUF_UNLOCK(&so->so_rcv); 6195163953Srrs } 6196169236Srwatson if (sockbuf_lock) { 6197169236Srwatson sbunlock(&so->so_rcv); 6198169236Srwatson } 6199163996Srrs if (freecnt_applied) { 6200163953Srrs /* 6201163953Srrs * The lock on the socket buffer protects us so the free 6202163953Srrs * code will stop. But since we used the socketbuf lock and 6203163953Srrs * the sender uses the tcb_lock to increment, we need to use 6204163953Srrs * the atomic add to the refcnt. 6205163953Srrs */ 6206163996Srrs if (stcb == NULL) { 6207182367Srrs#ifdef INVARIANTS 6208163996Srrs panic("stcb for refcnt has gone NULL?"); 6209182367Srrs goto stage_left; 6210182367Srrs#else 6211182367Srrs goto stage_left; 6212182367Srrs#endif 6213163996Srrs } 6214163996Srrs atomic_add_int(&stcb->asoc.refcnt, -1); 6215163953Srrs /* Save the value back for next time */ 6216163953Srrs stcb->freed_by_sorcv_sincelast = freed_so_far; 6217163953Srrs } 6218179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_RECV_RWND_LOGGING_ENABLE) { 6219170744Srrs if (stcb) { 6220170744Srrs sctp_misc_ints(SCTP_SORECV_DONE, 6221170744Srrs freed_so_far, 6222170744Srrs ((uio) ? (slen - uio->uio_resid) : slen), 6223170744Srrs stcb->asoc.my_rwnd, 6224170744Srrs so->so_rcv.sb_cc); 6225170744Srrs } else { 6226170744Srrs sctp_misc_ints(SCTP_SORECV_DONE, 6227170744Srrs freed_so_far, 6228170744Srrs ((uio) ? (slen - uio->uio_resid) : slen), 6229170744Srrs 0, 6230170744Srrs so->so_rcv.sb_cc); 6231170744Srrs } 6232163953Srrs } 6233182367Srrsstage_left: 6234163953Srrs if (wakeup_read_socket) { 6235163953Srrs sctp_sorwakeup(inp, so); 6236163953Srrs } 6237163953Srrs return (error); 6238163953Srrs} 6239163953Srrs 6240163953Srrs 6241163953Srrs#ifdef SCTP_MBUF_LOGGING 6242163953Srrsstruct mbuf * 6243163953Srrssctp_m_free(struct mbuf *m) 6244163953Srrs{ 6245179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) { 6246283708Stuexen sctp_log_mb(m, SCTP_MBUF_IFREE); 6247163953Srrs } 6248163953Srrs return (m_free(m)); 6249163953Srrs} 6250163953Srrs 6251163953Srrsvoid 6252163953Srrssctp_m_freem(struct mbuf *mb) 6253163953Srrs{ 6254163953Srrs while (mb != NULL) 6255163953Srrs mb = sctp_m_free(mb); 6256163953Srrs} 6257163953Srrs 6258163953Srrs#endif 6259163953Srrs 6260167598Srrsint 6261167598Srrssctp_dynamic_set_primary(struct sockaddr *sa, uint32_t vrf_id) 6262167598Srrs{ 6263167598Srrs /* 6264167598Srrs * Given a local address. For all associations that holds the 6265167598Srrs * address, request a peer-set-primary. 6266167598Srrs */ 6267167598Srrs struct sctp_ifa *ifa; 6268167598Srrs struct sctp_laddr *wi; 6269163953Srrs 6270167598Srrs ifa = sctp_find_ifa_by_addr(sa, vrf_id, 0); 6271167598Srrs if (ifa == NULL) { 6272171943Srrs SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTPUTIL, EADDRNOTAVAIL); 6273167598Srrs return (EADDRNOTAVAIL); 6274167598Srrs } 6275167598Srrs /* 6276167598Srrs * Now that we have the ifa we must awaken the iterator with this 6277167598Srrs * message. 6278167598Srrs */ 6279179783Srrs wi = SCTP_ZONE_GET(SCTP_BASE_INFO(ipi_zone_laddr), struct sctp_laddr); 6280167598Srrs if (wi == NULL) { 6281171943Srrs SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTPUTIL, ENOMEM); 6282167598Srrs return (ENOMEM); 6283167598Srrs } 6284167598Srrs /* Now incr the count and int wi structure */ 6285167598Srrs SCTP_INCR_LADDR_COUNT(); 6286167598Srrs bzero(wi, sizeof(*wi)); 6287170056Srrs (void)SCTP_GETTIME_TIMEVAL(&wi->start_time); 6288167598Srrs wi->ifa = ifa; 6289167598Srrs wi->action = SCTP_SET_PRIM_ADDR; 6290167598Srrs atomic_add_int(&ifa->refcount, 1); 6291167598Srrs 6292167598Srrs /* Now add it to the work queue */ 6293208160Srrs SCTP_WQ_ADDR_LOCK(); 6294167598Srrs /* 6295167598Srrs * Should this really be a tailq? As it is we will process the 6296167598Srrs * newest first :-0 6297167598Srrs */ 6298179783Srrs LIST_INSERT_HEAD(&SCTP_BASE_INFO(addr_wq), wi, sctp_nxt_addr); 6299208160Srrs SCTP_WQ_ADDR_UNLOCK(); 6300167598Srrs sctp_timer_start(SCTP_TIMER_TYPE_ADDR_WQ, 6301167598Srrs (struct sctp_inpcb *)NULL, 6302167598Srrs (struct sctp_tcb *)NULL, 6303167598Srrs (struct sctp_nets *)NULL); 6304167598Srrs return (0); 6305167598Srrs} 6306167598Srrs 6307167598Srrs 6308163953Srrsint 6309169352Srrssctp_soreceive(struct socket *so, 6310169352Srrs struct sockaddr **psa, 6311169352Srrs struct uio *uio, 6312169352Srrs struct mbuf **mp0, 6313169352Srrs struct mbuf **controlp, 6314169352Srrs int *flagsp) 6315163953Srrs{ 6316163953Srrs int error, fromlen; 6317163953Srrs uint8_t sockbuf[256]; 6318163953Srrs struct sockaddr *from; 6319163953Srrs struct sctp_extrcvinfo sinfo; 6320163953Srrs int filling_sinfo = 1; 6321163953Srrs struct sctp_inpcb *inp; 6322163953Srrs 6323163953Srrs inp = (struct sctp_inpcb *)so->so_pcb; 6324163953Srrs /* pickup the assoc we are reading from */ 6325163953Srrs if (inp == NULL) { 6326171943Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL); 6327163953Srrs return (EINVAL); 6328163953Srrs } 6329223132Stuexen if ((sctp_is_feature_off(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT) && 6330223132Stuexen sctp_is_feature_off(inp, SCTP_PCB_FLAGS_RECVRCVINFO) && 6331223132Stuexen sctp_is_feature_off(inp, SCTP_PCB_FLAGS_RECVNXTINFO)) || 6332163953Srrs (controlp == NULL)) { 6333163953Srrs /* user does not want the sndrcv ctl */ 6334163953Srrs filling_sinfo = 0; 6335163953Srrs } 6336163953Srrs if (psa) { 6337163953Srrs from = (struct sockaddr *)sockbuf; 6338163953Srrs fromlen = sizeof(sockbuf); 6339163953Srrs from->sa_len = 0; 6340163953Srrs } else { 6341163953Srrs from = NULL; 6342163953Srrs fromlen = 0; 6343163953Srrs } 6344163953Srrs 6345268432Sdelphij if (filling_sinfo) { 6346268432Sdelphij memset(&sinfo, 0, sizeof(struct sctp_extrcvinfo)); 6347268432Sdelphij } 6348163953Srrs error = sctp_sorecvmsg(so, uio, mp0, from, fromlen, flagsp, 6349163953Srrs (struct sctp_sndrcvinfo *)&sinfo, filling_sinfo); 6350268432Sdelphij if (controlp != NULL) { 6351163953Srrs /* copy back the sinfo in a CMSG format */ 6352163953Srrs if (filling_sinfo) 6353163953Srrs *controlp = sctp_build_ctl_nchunk(inp, 6354163953Srrs (struct sctp_sndrcvinfo *)&sinfo); 6355163953Srrs else 6356163953Srrs *controlp = NULL; 6357163953Srrs } 6358163953Srrs if (psa) { 6359163953Srrs /* copy back the address info */ 6360163953Srrs if (from && from->sa_len) { 6361163953Srrs *psa = sodupsockaddr(from, M_NOWAIT); 6362163953Srrs } else { 6363163953Srrs *psa = NULL; 6364163953Srrs } 6365163953Srrs } 6366163953Srrs return (error); 6367163953Srrs} 6368169352Srrs 6369169352Srrs 6370169352Srrs 6371169352Srrs 6372169352Srrs 6373169352Srrsint 6374170056Srrssctp_connectx_helper_add(struct sctp_tcb *stcb, struct sockaddr *addr, 6375170056Srrs int totaddr, int *error) 6376169352Srrs{ 6377169352Srrs int added = 0; 6378169352Srrs int i; 6379169352Srrs struct sctp_inpcb *inp; 6380169352Srrs struct sockaddr *sa; 6381169352Srrs size_t incr = 0; 6382169352Srrs 6383225571Stuexen#ifdef INET 6384225571Stuexen struct sockaddr_in *sin; 6385225571Stuexen 6386225571Stuexen#endif 6387225571Stuexen#ifdef INET6 6388225571Stuexen struct sockaddr_in6 *sin6; 6389225571Stuexen 6390225571Stuexen#endif 6391225571Stuexen 6392169352Srrs sa = addr; 6393169352Srrs inp = stcb->sctp_ep; 6394169352Srrs *error = 0; 6395169352Srrs for (i = 0; i < totaddr; i++) { 6396221328Stuexen switch (sa->sa_family) { 6397221328Stuexen#ifdef INET 6398221328Stuexen case AF_INET: 6399169352Srrs incr = sizeof(struct sockaddr_in); 6400225571Stuexen sin = (struct sockaddr_in *)sa; 6401225571Stuexen if ((sin->sin_addr.s_addr == INADDR_ANY) || 6402225571Stuexen (sin->sin_addr.s_addr == INADDR_BROADCAST) || 6403225571Stuexen IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) { 6404225571Stuexen SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, EINVAL); 6405283823Stuexen (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, 6406283823Stuexen SCTP_FROM_SCTPUTIL + SCTP_LOC_7); 6407225571Stuexen *error = EINVAL; 6408225571Stuexen goto out_now; 6409225571Stuexen } 6410224641Stuexen if (sctp_add_remote_addr(stcb, sa, NULL, SCTP_DONOT_SETSCOPE, SCTP_ADDR_IS_CONFIRMED)) { 6411169352Srrs /* assoc gone no un-lock */ 6412171943Srrs SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ENOBUFS); 6413283823Stuexen (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, 6414283823Stuexen SCTP_FROM_SCTPUTIL + SCTP_LOC_8); 6415169352Srrs *error = ENOBUFS; 6416169352Srrs goto out_now; 6417169352Srrs } 6418169352Srrs added++; 6419221328Stuexen break; 6420221328Stuexen#endif 6421221328Stuexen#ifdef INET6 6422221328Stuexen case AF_INET6: 6423169352Srrs incr = sizeof(struct sockaddr_in6); 6424225571Stuexen sin6 = (struct sockaddr_in6 *)sa; 6425225571Stuexen if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) || 6426225571Stuexen IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) { 6427225571Stuexen SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, EINVAL); 6428283823Stuexen (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, 6429283823Stuexen SCTP_FROM_SCTPUTIL + SCTP_LOC_9); 6430225571Stuexen *error = EINVAL; 6431225571Stuexen goto out_now; 6432225571Stuexen } 6433224641Stuexen if (sctp_add_remote_addr(stcb, sa, NULL, SCTP_DONOT_SETSCOPE, SCTP_ADDR_IS_CONFIRMED)) { 6434169352Srrs /* assoc gone no un-lock */ 6435171943Srrs SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ENOBUFS); 6436283823Stuexen (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, 6437283823Stuexen SCTP_FROM_SCTPUTIL + SCTP_LOC_10); 6438169352Srrs *error = ENOBUFS; 6439169352Srrs goto out_now; 6440169352Srrs } 6441169352Srrs added++; 6442221328Stuexen break; 6443221328Stuexen#endif 6444221328Stuexen default: 6445221328Stuexen break; 6446169352Srrs } 6447169352Srrs sa = (struct sockaddr *)((caddr_t)sa + incr); 6448169352Srrs } 6449169352Srrsout_now: 6450169352Srrs return (added); 6451169352Srrs} 6452169352Srrs 6453169352Srrsstruct sctp_tcb * 6454170056Srrssctp_connectx_helper_find(struct sctp_inpcb *inp, struct sockaddr *addr, 6455170056Srrs int *totaddr, int *num_v4, int *num_v6, int *error, 6456170056Srrs int limit, int *bad_addr) 6457169352Srrs{ 6458169352Srrs struct sockaddr *sa; 6459169352Srrs struct sctp_tcb *stcb = NULL; 6460169352Srrs size_t incr, at, i; 6461169352Srrs 6462169352Srrs at = incr = 0; 6463169352Srrs sa = addr; 6464221328Stuexen 6465169352Srrs *error = *num_v6 = *num_v4 = 0; 6466169352Srrs /* account and validate addresses */ 6467170140Srrs for (i = 0; i < (size_t)*totaddr; i++) { 6468221328Stuexen switch (sa->sa_family) { 6469221328Stuexen#ifdef INET 6470221328Stuexen case AF_INET: 6471169352Srrs (*num_v4) += 1; 6472169352Srrs incr = sizeof(struct sockaddr_in); 6473170056Srrs if (sa->sa_len != incr) { 6474171943Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL); 6475170056Srrs *error = EINVAL; 6476170056Srrs *bad_addr = 1; 6477170056Srrs return (NULL); 6478170056Srrs } 6479221328Stuexen break; 6480221328Stuexen#endif 6481221328Stuexen#ifdef INET6 6482221328Stuexen case AF_INET6: 6483221328Stuexen { 6484221328Stuexen struct sockaddr_in6 *sin6; 6485169352Srrs 6486221328Stuexen sin6 = (struct sockaddr_in6 *)sa; 6487221328Stuexen if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { 6488221328Stuexen /* Must be non-mapped for connectx */ 6489221328Stuexen SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL); 6490221328Stuexen *error = EINVAL; 6491221328Stuexen *bad_addr = 1; 6492221328Stuexen return (NULL); 6493221328Stuexen } 6494221328Stuexen (*num_v6) += 1; 6495221328Stuexen incr = sizeof(struct sockaddr_in6); 6496221328Stuexen if (sa->sa_len != incr) { 6497221328Stuexen SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL); 6498221328Stuexen *error = EINVAL; 6499221328Stuexen *bad_addr = 1; 6500221328Stuexen return (NULL); 6501221328Stuexen } 6502221328Stuexen break; 6503169352Srrs } 6504221328Stuexen#endif 6505221328Stuexen default: 6506169352Srrs *totaddr = i; 6507169352Srrs /* we are done */ 6508169352Srrs break; 6509169352Srrs } 6510221328Stuexen if (i == (size_t)*totaddr) { 6511221328Stuexen break; 6512221328Stuexen } 6513170056Srrs SCTP_INP_INCR_REF(inp); 6514169352Srrs stcb = sctp_findassociation_ep_addr(&inp, sa, NULL, NULL, NULL); 6515169352Srrs if (stcb != NULL) { 6516169352Srrs /* Already have or am bring up an association */ 6517169352Srrs return (stcb); 6518170056Srrs } else { 6519170056Srrs SCTP_INP_DECR_REF(inp); 6520169352Srrs } 6521170140Srrs if ((at + incr) > (size_t)limit) { 6522169352Srrs *totaddr = i; 6523169352Srrs break; 6524169352Srrs } 6525169352Srrs sa = (struct sockaddr *)((caddr_t)sa + incr); 6526169352Srrs } 6527169352Srrs return ((struct sctp_tcb *)NULL); 6528169352Srrs} 6529170606Srrs 6530170606Srrs/* 6531170606Srrs * sctp_bindx(ADD) for one address. 6532170606Srrs * assumes all arguments are valid/checked by caller. 6533170606Srrs */ 6534170606Srrsvoid 6535170606Srrssctp_bindx_add_address(struct socket *so, struct sctp_inpcb *inp, 6536170606Srrs struct sockaddr *sa, sctp_assoc_t assoc_id, 6537170606Srrs uint32_t vrf_id, int *error, void *p) 6538170606Srrs{ 6539170606Srrs struct sockaddr *addr_touse; 6540178251Srrs 6541283699Stuexen#if defined(INET) && defined(INET6) 6542170606Srrs struct sockaddr_in sin; 6543170606Srrs 6544178251Srrs#endif 6545178251Srrs 6546170606Srrs /* see if we're bound all already! */ 6547170606Srrs if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) { 6548171943Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL); 6549170606Srrs *error = EINVAL; 6550170606Srrs return; 6551170606Srrs } 6552170606Srrs addr_touse = sa; 6553221328Stuexen#ifdef INET6 6554170606Srrs if (sa->sa_family == AF_INET6) { 6555283699Stuexen#ifdef INET 6556170606Srrs struct sockaddr_in6 *sin6; 6557170606Srrs 6558283699Stuexen#endif 6559170606Srrs if (sa->sa_len != sizeof(struct sockaddr_in6)) { 6560171943Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL); 6561170606Srrs *error = EINVAL; 6562170606Srrs return; 6563170606Srrs } 6564170665Srrs if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) { 6565170665Srrs /* can only bind v6 on PF_INET6 sockets */ 6566171943Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL); 6567170665Srrs *error = EINVAL; 6568170665Srrs return; 6569170665Srrs } 6570283699Stuexen#ifdef INET 6571170606Srrs sin6 = (struct sockaddr_in6 *)addr_touse; 6572170606Srrs if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { 6573170665Srrs if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) && 6574170665Srrs SCTP_IPV6_V6ONLY(inp)) { 6575170665Srrs /* can't bind v4-mapped on PF_INET sockets */ 6576171943Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL); 6577170665Srrs *error = EINVAL; 6578170665Srrs return; 6579170665Srrs } 6580170606Srrs in6_sin6_2_sin(&sin, sin6); 6581170606Srrs addr_touse = (struct sockaddr *)&sin; 6582170606Srrs } 6583283699Stuexen#endif 6584170606Srrs } 6585170606Srrs#endif 6586221328Stuexen#ifdef INET 6587170606Srrs if (sa->sa_family == AF_INET) { 6588170606Srrs if (sa->sa_len != sizeof(struct sockaddr_in)) { 6589171943Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL); 6590170606Srrs *error = EINVAL; 6591170606Srrs return; 6592170606Srrs } 6593170665Srrs if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) && 6594170665Srrs SCTP_IPV6_V6ONLY(inp)) { 6595170665Srrs /* can't bind v4 on PF_INET sockets */ 6596171943Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL); 6597170665Srrs *error = EINVAL; 6598170665Srrs return; 6599170665Srrs } 6600170606Srrs } 6601221328Stuexen#endif 6602170606Srrs if (inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) { 6603170606Srrs if (p == NULL) { 6604170606Srrs /* Can't get proc for Net/Open BSD */ 6605171943Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL); 6606170606Srrs *error = EINVAL; 6607170606Srrs return; 6608170606Srrs } 6609171572Srrs *error = sctp_inpcb_bind(so, addr_touse, NULL, p); 6610170606Srrs return; 6611170606Srrs } 6612170606Srrs /* 6613170606Srrs * No locks required here since bind and mgmt_ep_sa all do their own 6614170606Srrs * locking. If we do something for the FIX: below we may need to 6615170606Srrs * lock in that case. 6616170606Srrs */ 6617170606Srrs if (assoc_id == 0) { 6618170606Srrs /* add the address */ 6619170606Srrs struct sctp_inpcb *lep; 6620171032Srrs struct sockaddr_in *lsin = (struct sockaddr_in *)addr_touse; 6621170606Srrs 6622171032Srrs /* validate the incoming port */ 6623171032Srrs if ((lsin->sin_port != 0) && 6624171032Srrs (lsin->sin_port != inp->sctp_lport)) { 6625171943Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL); 6626171032Srrs *error = EINVAL; 6627171032Srrs return; 6628171032Srrs } else { 6629171032Srrs /* user specified 0 port, set it to existing port */ 6630171032Srrs lsin->sin_port = inp->sctp_lport; 6631171032Srrs } 6632171032Srrs 6633170606Srrs lep = sctp_pcb_findep(addr_touse, 1, 0, vrf_id); 6634170606Srrs if (lep != NULL) { 6635170606Srrs /* 6636170606Srrs * We must decrement the refcount since we have the 6637170606Srrs * ep already and are binding. No remove going on 6638170606Srrs * here. 6639170606Srrs */ 6640181054Srrs SCTP_INP_DECR_REF(lep); 6641170606Srrs } 6642170606Srrs if (lep == inp) { 6643170606Srrs /* already bound to it.. ok */ 6644170606Srrs return; 6645170606Srrs } else if (lep == NULL) { 6646170606Srrs ((struct sockaddr_in *)addr_touse)->sin_port = 0; 6647170606Srrs *error = sctp_addr_mgmt_ep_sa(inp, addr_touse, 6648170606Srrs SCTP_ADD_IP_ADDRESS, 6649170744Srrs vrf_id, NULL); 6650170606Srrs } else { 6651170606Srrs *error = EADDRINUSE; 6652170606Srrs } 6653170606Srrs if (*error) 6654170606Srrs return; 6655170606Srrs } else { 6656170606Srrs /* 6657170606Srrs * FIX: decide whether we allow assoc based bindx 6658170606Srrs */ 6659170606Srrs } 6660170606Srrs} 6661170606Srrs 6662170606Srrs/* 6663170606Srrs * sctp_bindx(DELETE) for one address. 6664170606Srrs * assumes all arguments are valid/checked by caller. 6665170606Srrs */ 6666170606Srrsvoid 6667228653Stuexensctp_bindx_delete_address(struct sctp_inpcb *inp, 6668170606Srrs struct sockaddr *sa, sctp_assoc_t assoc_id, 6669170606Srrs uint32_t vrf_id, int *error) 6670170606Srrs{ 6671170606Srrs struct sockaddr *addr_touse; 6672178251Srrs 6673283699Stuexen#if defined(INET) && defined(INET6) 6674170606Srrs struct sockaddr_in sin; 6675170606Srrs 6676178251Srrs#endif 6677178251Srrs 6678170606Srrs /* see if we're bound all already! */ 6679170606Srrs if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) { 6680171943Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL); 6681170606Srrs *error = EINVAL; 6682170606Srrs return; 6683170606Srrs } 6684170606Srrs addr_touse = sa; 6685238475Stuexen#ifdef INET6 6686170606Srrs if (sa->sa_family == AF_INET6) { 6687283699Stuexen#ifdef INET 6688170606Srrs struct sockaddr_in6 *sin6; 6689170606Srrs 6690283699Stuexen#endif 6691283699Stuexen 6692170606Srrs if (sa->sa_len != sizeof(struct sockaddr_in6)) { 6693171943Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL); 6694170606Srrs *error = EINVAL; 6695170606Srrs return; 6696170606Srrs } 6697170665Srrs if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) { 6698170665Srrs /* can only bind v6 on PF_INET6 sockets */ 6699171943Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL); 6700170665Srrs *error = EINVAL; 6701170665Srrs return; 6702170665Srrs } 6703283699Stuexen#ifdef INET 6704170606Srrs sin6 = (struct sockaddr_in6 *)addr_touse; 6705170606Srrs if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { 6706170665Srrs if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) && 6707170665Srrs SCTP_IPV6_V6ONLY(inp)) { 6708170665Srrs /* can't bind mapped-v4 on PF_INET sockets */ 6709171943Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL); 6710170665Srrs *error = EINVAL; 6711170665Srrs return; 6712170665Srrs } 6713170606Srrs in6_sin6_2_sin(&sin, sin6); 6714170606Srrs addr_touse = (struct sockaddr *)&sin; 6715170606Srrs } 6716283699Stuexen#endif 6717170606Srrs } 6718170606Srrs#endif 6719221328Stuexen#ifdef INET 6720170606Srrs if (sa->sa_family == AF_INET) { 6721170606Srrs if (sa->sa_len != sizeof(struct sockaddr_in)) { 6722171943Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL); 6723170606Srrs *error = EINVAL; 6724170606Srrs return; 6725170606Srrs } 6726170665Srrs if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) && 6727170665Srrs SCTP_IPV6_V6ONLY(inp)) { 6728170665Srrs /* can't bind v4 on PF_INET sockets */ 6729171943Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL); 6730170665Srrs *error = EINVAL; 6731170665Srrs return; 6732170665Srrs } 6733170606Srrs } 6734221328Stuexen#endif 6735170606Srrs /* 6736170606Srrs * No lock required mgmt_ep_sa does its own locking. If the FIX: 6737170606Srrs * below is ever changed we may need to lock before calling 6738170606Srrs * association level binding. 6739170606Srrs */ 6740170606Srrs if (assoc_id == 0) { 6741170606Srrs /* delete the address */ 6742170606Srrs *error = sctp_addr_mgmt_ep_sa(inp, addr_touse, 6743170606Srrs SCTP_DEL_IP_ADDRESS, 6744170744Srrs vrf_id, NULL); 6745170606Srrs } else { 6746170606Srrs /* 6747170606Srrs * FIX: decide whether we allow assoc based bindx 6748170606Srrs */ 6749170606Srrs } 6750170606Srrs} 6751171572Srrs 6752171572Srrs/* 6753171572Srrs * returns the valid local address count for an assoc, taking into account 6754171572Srrs * all scoping rules 6755171572Srrs */ 6756171572Srrsint 6757171572Srrssctp_local_addr_count(struct sctp_tcb *stcb) 6758171572Srrs{ 6759258454Stuexen int loopback_scope; 6760258454Stuexen 6761258454Stuexen#if defined(INET) 6762258454Stuexen int ipv4_local_scope, ipv4_addr_legal; 6763258454Stuexen 6764258454Stuexen#endif 6765258454Stuexen#if defined (INET6) 6766258454Stuexen int local_scope, site_scope, ipv6_addr_legal; 6767258454Stuexen 6768258454Stuexen#endif 6769171572Srrs struct sctp_vrf *vrf; 6770171572Srrs struct sctp_ifn *sctp_ifn; 6771171572Srrs struct sctp_ifa *sctp_ifa; 6772171572Srrs int count = 0; 6773171572Srrs 6774171572Srrs /* Turn on all the appropriate scopes */ 6775246595Stuexen loopback_scope = stcb->asoc.scope.loopback_scope; 6776258454Stuexen#if defined(INET) 6777246595Stuexen ipv4_local_scope = stcb->asoc.scope.ipv4_local_scope; 6778258454Stuexen ipv4_addr_legal = stcb->asoc.scope.ipv4_addr_legal; 6779258454Stuexen#endif 6780258454Stuexen#if defined(INET6) 6781246595Stuexen local_scope = stcb->asoc.scope.local_scope; 6782246595Stuexen site_scope = stcb->asoc.scope.site_scope; 6783246595Stuexen ipv6_addr_legal = stcb->asoc.scope.ipv6_addr_legal; 6784258454Stuexen#endif 6785172218Srrs SCTP_IPI_ADDR_RLOCK(); 6786171572Srrs vrf = sctp_find_vrf(stcb->asoc.vrf_id); 6787171572Srrs if (vrf == NULL) { 6788171572Srrs /* no vrf, no addresses */ 6789172218Srrs SCTP_IPI_ADDR_RUNLOCK(); 6790171572Srrs return (0); 6791171572Srrs } 6792171572Srrs if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) { 6793171572Srrs /* 6794171572Srrs * bound all case: go through all ifns on the vrf 6795171572Srrs */ 6796171572Srrs LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) { 6797171572Srrs if ((loopback_scope == 0) && 6798171572Srrs SCTP_IFN_IS_IFT_LOOP(sctp_ifn)) { 6799171572Srrs continue; 6800171572Srrs } 6801171572Srrs LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) { 6802171572Srrs if (sctp_is_addr_restricted(stcb, sctp_ifa)) 6803171572Srrs continue; 6804178251Srrs switch (sctp_ifa->address.sa.sa_family) { 6805221328Stuexen#ifdef INET 6806178251Srrs case AF_INET: 6807178251Srrs if (ipv4_addr_legal) { 6808178251Srrs struct sockaddr_in *sin; 6809171572Srrs 6810271746Stuexen sin = &sctp_ifa->address.sin; 6811178251Srrs if (sin->sin_addr.s_addr == 0) { 6812178251Srrs /* 6813178251Srrs * skip unspecified 6814178251Srrs * addrs 6815178251Srrs */ 6816178251Srrs continue; 6817178251Srrs } 6818267769Stuexen if (prison_check_ip4(stcb->sctp_ep->ip_inp.inp.inp_cred, 6819267769Stuexen &sin->sin_addr) != 0) { 6820267769Stuexen continue; 6821267769Stuexen } 6822178251Srrs if ((ipv4_local_scope == 0) && 6823178251Srrs (IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))) { 6824178251Srrs continue; 6825178251Srrs } 6826178251Srrs /* count this one */ 6827178251Srrs count++; 6828178251Srrs } else { 6829171572Srrs continue; 6830171572Srrs } 6831178251Srrs break; 6832221328Stuexen#endif 6833178251Srrs#ifdef INET6 6834178251Srrs case AF_INET6: 6835178251Srrs if (ipv6_addr_legal) { 6836178251Srrs struct sockaddr_in6 *sin6; 6837171572Srrs 6838271746Stuexen sin6 = &sctp_ifa->address.sin6; 6839178251Srrs if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 6840171572Srrs continue; 6841178251Srrs } 6842267769Stuexen if (prison_check_ip6(stcb->sctp_ep->ip_inp.inp.inp_cred, 6843267769Stuexen &sin6->sin6_addr) != 0) { 6844267769Stuexen continue; 6845267769Stuexen } 6846178251Srrs if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { 6847178251Srrs if (local_scope == 0) 6848171572Srrs continue; 6849178251Srrs if (sin6->sin6_scope_id == 0) { 6850178251Srrs if (sa6_recoverscope(sin6) != 0) 6851178251Srrs /* 6852178251Srrs * 6853178251Srrs * bad 6854178251Srrs * 6855178251Srrs * li 6856178251Srrs * nk 6857178251Srrs * 6858178251Srrs * loc 6859178251Srrs * al 6860178251Srrs * 6861178251Srrs * add 6862178251Srrs * re 6863178251Srrs * ss 6864178251Srrs * */ 6865178251Srrs continue; 6866178251Srrs } 6867171572Srrs } 6868178251Srrs if ((site_scope == 0) && 6869178251Srrs (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr))) { 6870178251Srrs continue; 6871178251Srrs } 6872178251Srrs /* count this one */ 6873178251Srrs count++; 6874171572Srrs } 6875178251Srrs break; 6876178251Srrs#endif 6877178251Srrs default: 6878178251Srrs /* TSNH */ 6879178251Srrs break; 6880171572Srrs } 6881171572Srrs } 6882171572Srrs } 6883171572Srrs } else { 6884171572Srrs /* 6885171572Srrs * subset bound case 6886171572Srrs */ 6887171572Srrs struct sctp_laddr *laddr; 6888171572Srrs 6889171572Srrs LIST_FOREACH(laddr, &stcb->sctp_ep->sctp_addr_list, 6890171572Srrs sctp_nxt_addr) { 6891171572Srrs if (sctp_is_addr_restricted(stcb, laddr->ifa)) { 6892171572Srrs continue; 6893171572Srrs } 6894171572Srrs /* count this one */ 6895171572Srrs count++; 6896171572Srrs } 6897171572Srrs } 6898172218Srrs SCTP_IPI_ADDR_RUNLOCK(); 6899171572Srrs return (count); 6900171572Srrs} 6901171943Srrs 6902171943Srrs#if defined(SCTP_LOCAL_TRACE_BUF) 6903171943Srrs 6904171943Srrsvoid 6905172157Srrssctp_log_trace(uint32_t subsys, const char *str SCTP_UNUSED, uint32_t a, uint32_t b, uint32_t c, uint32_t d, uint32_t e, uint32_t f) 6906171943Srrs{ 6907172157Srrs uint32_t saveindex, newindex; 6908171943Srrs 6909171943Srrs do { 6910179783Srrs saveindex = SCTP_BASE_SYSCTL(sctp_log).index; 6911171943Srrs if (saveindex >= SCTP_MAX_LOGGING_SIZE) { 6912171943Srrs newindex = 1; 6913171943Srrs } else { 6914171943Srrs newindex = saveindex + 1; 6915171943Srrs } 6916179783Srrs } while (atomic_cmpset_int(&SCTP_BASE_SYSCTL(sctp_log).index, saveindex, newindex) == 0); 6917171943Srrs if (saveindex >= SCTP_MAX_LOGGING_SIZE) { 6918171943Srrs saveindex = 0; 6919171943Srrs } 6920179783Srrs SCTP_BASE_SYSCTL(sctp_log).entry[saveindex].timestamp = SCTP_GET_CYCLECOUNT; 6921179783Srrs SCTP_BASE_SYSCTL(sctp_log).entry[saveindex].subsys = subsys; 6922179783Srrs SCTP_BASE_SYSCTL(sctp_log).entry[saveindex].params[0] = a; 6923179783Srrs SCTP_BASE_SYSCTL(sctp_log).entry[saveindex].params[1] = b; 6924179783Srrs SCTP_BASE_SYSCTL(sctp_log).entry[saveindex].params[2] = c; 6925179783Srrs SCTP_BASE_SYSCTL(sctp_log).entry[saveindex].params[3] = d; 6926179783Srrs SCTP_BASE_SYSCTL(sctp_log).entry[saveindex].params[4] = e; 6927179783Srrs SCTP_BASE_SYSCTL(sctp_log).entry[saveindex].params[5] = f; 6928171943Srrs} 6929171943Srrs 6930171943Srrs#endif 6931188067Srrsstatic void 6932294140Stuexensctp_recv_udp_tunneled_packet(struct mbuf *m, int off, struct inpcb *inp, 6933277789Sbryanv const struct sockaddr *sa SCTP_UNUSED, void *ctx SCTP_UNUSED) 6934188067Srrs{ 6935188067Srrs struct ip *iph; 6936243186Stuexen 6937243186Stuexen#ifdef INET6 6938243186Stuexen struct ip6_hdr *ip6; 6939243186Stuexen 6940243186Stuexen#endif 6941188067Srrs struct mbuf *sp, *last; 6942188067Srrs struct udphdr *uhdr; 6943237229Stuexen uint16_t port; 6944188067Srrs 6945188067Srrs if ((m->m_flags & M_PKTHDR) == 0) { 6946188067Srrs /* Can't handle one that is not a pkt hdr */ 6947188067Srrs goto out; 6948188067Srrs } 6949237229Stuexen /* Pull the src port */ 6950188067Srrs iph = mtod(m, struct ip *); 6951188067Srrs uhdr = (struct udphdr *)((caddr_t)iph + off); 6952188067Srrs port = uhdr->uh_sport; 6953237229Stuexen /* 6954237229Stuexen * Split out the mbuf chain. Leave the IP header in m, place the 6955237229Stuexen * rest in the sp. 6956237229Stuexen */ 6957243882Sglebius sp = m_split(m, off, M_NOWAIT); 6958188067Srrs if (sp == NULL) { 6959188067Srrs /* Gak, drop packet, we can't do a split */ 6960188067Srrs goto out; 6961188067Srrs } 6962237229Stuexen if (sp->m_pkthdr.len < sizeof(struct udphdr) + sizeof(struct sctphdr)) { 6963237229Stuexen /* Gak, packet can't have an SCTP header in it - too small */ 6964188067Srrs m_freem(sp); 6965188067Srrs goto out; 6966188067Srrs } 6967237229Stuexen /* Now pull up the UDP header and SCTP header together */ 6968237229Stuexen sp = m_pullup(sp, sizeof(struct udphdr) + sizeof(struct sctphdr)); 6969188067Srrs if (sp == NULL) { 6970188067Srrs /* Gak pullup failed */ 6971188067Srrs goto out; 6972188067Srrs } 6973237229Stuexen /* Trim out the UDP header */ 6974188067Srrs m_adj(sp, sizeof(struct udphdr)); 6975188067Srrs 6976188067Srrs /* Now reconstruct the mbuf chain */ 6977237229Stuexen for (last = m; last->m_next; last = last->m_next); 6978188067Srrs last->m_next = sp; 6979188067Srrs m->m_pkthdr.len += sp->m_pkthdr.len; 6980294189Stuexen /* 6981294189Stuexen * The CSUM_DATA_VALID flags indicates that the HW checked the UDP 6982294189Stuexen * checksum and it was valid. Since CSUM_DATA_VALID == 6983294189Stuexen * CSUM_SCTP_VALID this would imply that the HW also verified the 6984294189Stuexen * SCTP checksum. Therefore, clear the bit. 6985294189Stuexen */ 6986294189Stuexen SCTPDBG(SCTP_DEBUG_CRCOFFLOAD, 6987294189Stuexen "sctp_recv_udp_tunneled_packet(): Packet of length %d received on %s with csum_flags 0x%b.\n", 6988294189Stuexen m->m_pkthdr.len, 6989294189Stuexen if_name(m->m_pkthdr.rcvif), 6990294189Stuexen (int)m->m_pkthdr.csum_flags, CSUM_BITS); 6991294189Stuexen m->m_pkthdr.csum_flags &= ~CSUM_DATA_VALID; 6992188067Srrs iph = mtod(m, struct ip *); 6993188067Srrs switch (iph->ip_v) { 6994221249Stuexen#ifdef INET 6995188067Srrs case IPVERSION: 6996242325Stuexen iph->ip_len = htons(ntohs(iph->ip_len) - sizeof(struct udphdr)); 6997237229Stuexen sctp_input_with_port(m, off, port); 6998237229Stuexen break; 6999221249Stuexen#endif 7000188067Srrs#ifdef INET6 7001188067Srrs case IPV6_VERSION >> 4: 7002243186Stuexen ip6 = mtod(m, struct ip6_hdr *); 7003243186Stuexen ip6->ip6_plen = htons(ntohs(ip6->ip6_plen) - sizeof(struct udphdr)); 7004243186Stuexen sctp6_input_with_port(&m, &off, port); 7005237229Stuexen break; 7006188067Srrs#endif 7007188067Srrs default: 7008237229Stuexen goto out; 7009237229Stuexen break; 7010188067Srrs } 7011188067Srrs return; 7012188067Srrsout: 7013188067Srrs m_freem(m); 7014188067Srrs} 7015188067Srrs 7016221328Stuexenvoid 7017179157Srrssctp_over_udp_stop(void) 7018179157Srrs{ 7019188067Srrs /* 7020188067Srrs * This function assumes sysctl caller holds sctp_sysctl_info_lock() 7021188067Srrs * for writting! 7022188067Srrs */ 7023243186Stuexen#ifdef INET 7024243186Stuexen if (SCTP_BASE_INFO(udp4_tun_socket) != NULL) { 7025243186Stuexen soclose(SCTP_BASE_INFO(udp4_tun_socket)); 7026243186Stuexen SCTP_BASE_INFO(udp4_tun_socket) = NULL; 7027188067Srrs } 7028243186Stuexen#endif 7029243186Stuexen#ifdef INET6 7030243186Stuexen if (SCTP_BASE_INFO(udp6_tun_socket) != NULL) { 7031243186Stuexen soclose(SCTP_BASE_INFO(udp6_tun_socket)); 7032243186Stuexen SCTP_BASE_INFO(udp6_tun_socket) = NULL; 7033243186Stuexen } 7034243186Stuexen#endif 7035179157Srrs} 7036221328Stuexen 7037221328Stuexenint 7038179157Srrssctp_over_udp_start(void) 7039179157Srrs{ 7040188067Srrs uint16_t port; 7041188067Srrs int ret; 7042243186Stuexen 7043243186Stuexen#ifdef INET 7044188067Srrs struct sockaddr_in sin; 7045188067Srrs 7046243186Stuexen#endif 7047243186Stuexen#ifdef INET6 7048243186Stuexen struct sockaddr_in6 sin6; 7049243186Stuexen 7050243186Stuexen#endif 7051188067Srrs /* 7052188067Srrs * This function assumes sysctl caller holds sctp_sysctl_info_lock() 7053188067Srrs * for writting! 7054188067Srrs */ 7055188067Srrs port = SCTP_BASE_SYSCTL(sctp_udp_tunneling_port); 7056243186Stuexen if (ntohs(port) == 0) { 7057188067Srrs /* Must have a port set */ 7058188067Srrs return (EINVAL); 7059188067Srrs } 7060243186Stuexen#ifdef INET 7061243186Stuexen if (SCTP_BASE_INFO(udp4_tun_socket) != NULL) { 7062188067Srrs /* Already running -- must stop first */ 7063188067Srrs return (EALREADY); 7064188067Srrs } 7065243186Stuexen#endif 7066243186Stuexen#ifdef INET6 7067243186Stuexen if (SCTP_BASE_INFO(udp6_tun_socket) != NULL) { 7068243186Stuexen /* Already running -- must stop first */ 7069243186Stuexen return (EALREADY); 7070243186Stuexen } 7071243186Stuexen#endif 7072243186Stuexen#ifdef INET 7073243186Stuexen if ((ret = socreate(PF_INET, &SCTP_BASE_INFO(udp4_tun_socket), 7074243186Stuexen SOCK_DGRAM, IPPROTO_UDP, 7075243186Stuexen curthread->td_ucred, curthread))) { 7076243186Stuexen sctp_over_udp_stop(); 7077188067Srrs return (ret); 7078188067Srrs } 7079243186Stuexen /* Call the special UDP hook. */ 7080243186Stuexen if ((ret = udp_set_kernel_tunneling(SCTP_BASE_INFO(udp4_tun_socket), 7081277789Sbryanv sctp_recv_udp_tunneled_packet, NULL))) { 7082243186Stuexen sctp_over_udp_stop(); 7083243186Stuexen return (ret); 7084188067Srrs } 7085243186Stuexen /* Ok, we have a socket, bind it to the port. */ 7086243186Stuexen memset(&sin, 0, sizeof(struct sockaddr_in)); 7087243186Stuexen sin.sin_len = sizeof(struct sockaddr_in); 7088188067Srrs sin.sin_family = AF_INET; 7089188067Srrs sin.sin_port = htons(port); 7090243186Stuexen if ((ret = sobind(SCTP_BASE_INFO(udp4_tun_socket), 7091243186Stuexen (struct sockaddr *)&sin, curthread))) { 7092188067Srrs sctp_over_udp_stop(); 7093188067Srrs return (ret); 7094188067Srrs } 7095243186Stuexen#endif 7096243186Stuexen#ifdef INET6 7097243186Stuexen if ((ret = socreate(PF_INET6, &SCTP_BASE_INFO(udp6_tun_socket), 7098243186Stuexen SOCK_DGRAM, IPPROTO_UDP, 7099243186Stuexen curthread->td_ucred, curthread))) { 7100243186Stuexen sctp_over_udp_stop(); 7101243186Stuexen return (ret); 7102243186Stuexen } 7103243186Stuexen /* Call the special UDP hook. */ 7104243186Stuexen if ((ret = udp_set_kernel_tunneling(SCTP_BASE_INFO(udp6_tun_socket), 7105277789Sbryanv sctp_recv_udp_tunneled_packet, NULL))) { 7106243186Stuexen sctp_over_udp_stop(); 7107243186Stuexen return (ret); 7108243186Stuexen } 7109243186Stuexen /* Ok, we have a socket, bind it to the port. */ 7110243186Stuexen memset(&sin6, 0, sizeof(struct sockaddr_in6)); 7111243186Stuexen sin6.sin6_len = sizeof(struct sockaddr_in6); 7112243186Stuexen sin6.sin6_family = AF_INET6; 7113243186Stuexen sin6.sin6_port = htons(port); 7114243186Stuexen if ((ret = sobind(SCTP_BASE_INFO(udp6_tun_socket), 7115243186Stuexen (struct sockaddr *)&sin6, curthread))) { 7116243186Stuexen sctp_over_udp_stop(); 7117243186Stuexen return (ret); 7118243186Stuexen } 7119243186Stuexen#endif 7120188067Srrs return (0); 7121179157Srrs} 7122