1163953Srrs/*- 2185694Srrs * Copyright (c) 2001-2008, by Cisco Systems, Inc. All rights reserved. 3237896Stuexen * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved. 4237896Stuexen * 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, 10231038Stuexen * 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 14231038Stuexen * 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 42252944Stuexen#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> 52252944Stuexen#include <netinet/udp.h> 53252944Stuexen#include <netinet/udp_var.h> 54252944Stuexen#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 65252932Stuexensctp_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 203252932Stuexensctp_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 220163953Srrsvoid 221163953Srrssctp_log_mb(struct mbuf *m, int from) 222163953Srrs{ 223170744Srrs struct sctp_cwnd_log sctp_clog; 224163953Srrs 225170744Srrs sctp_clog.x.mb.mp = m; 226170744Srrs sctp_clog.x.mb.mbuf_flags = (uint8_t) (SCTP_BUF_GET_FLAGS(m)); 227170744Srrs sctp_clog.x.mb.size = (uint16_t) (SCTP_BUF_LEN(m)); 228170744Srrs sctp_clog.x.mb.data = SCTP_BUF_AT(m, 0); 229165647Srrs if (SCTP_BUF_IS_EXTENDED(m)) { 230170744Srrs sctp_clog.x.mb.ext = SCTP_BUF_EXTEND_BASE(m); 231170744Srrs sctp_clog.x.mb.refcnt = (uint8_t) (SCTP_BUF_EXTEND_REFCNT(m)); 232163953Srrs } else { 233170744Srrs sctp_clog.x.mb.ext = 0; 234170744Srrs sctp_clog.x.mb.refcnt = 0; 235163953Srrs } 236171943Srrs SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x", 237170744Srrs SCTP_LOG_EVENT_MBUF, 238170744Srrs from, 239170744Srrs sctp_clog.x.misc.log1, 240170744Srrs sctp_clog.x.misc.log2, 241170744Srrs sctp_clog.x.misc.log3, 242170744Srrs sctp_clog.x.misc.log4); 243163953Srrs} 244163953Srrs 245163953Srrsvoid 246252932Stuexensctp_log_strm_del(struct sctp_queued_to_read *control, struct sctp_queued_to_read *poschk, int from) 247163953Srrs{ 248170744Srrs struct sctp_cwnd_log sctp_clog; 249163953Srrs 250163953Srrs if (control == NULL) { 251169420Srrs SCTP_PRINTF("Gak log of NULL?\n"); 252163953Srrs return; 253163953Srrs } 254170744Srrs sctp_clog.x.strlog.stcb = control->stcb; 255170744Srrs sctp_clog.x.strlog.n_tsn = control->sinfo_tsn; 256170744Srrs sctp_clog.x.strlog.n_sseq = control->sinfo_ssn; 257170744Srrs sctp_clog.x.strlog.strm = control->sinfo_stream; 258163953Srrs if (poschk != NULL) { 259170744Srrs sctp_clog.x.strlog.e_tsn = poschk->sinfo_tsn; 260170744Srrs sctp_clog.x.strlog.e_sseq = poschk->sinfo_ssn; 261163953Srrs } else { 262170744Srrs sctp_clog.x.strlog.e_tsn = 0; 263170744Srrs sctp_clog.x.strlog.e_sseq = 0; 264163953Srrs } 265171943Srrs SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x", 266170744Srrs SCTP_LOG_EVENT_STRM, 267170744Srrs from, 268170744Srrs sctp_clog.x.misc.log1, 269170744Srrs sctp_clog.x.misc.log2, 270170744Srrs sctp_clog.x.misc.log3, 271170744Srrs sctp_clog.x.misc.log4); 272163953Srrs} 273163953Srrs 274163953Srrsvoid 275163953Srrssctp_log_cwnd(struct sctp_tcb *stcb, struct sctp_nets *net, int augment, uint8_t from) 276163953Srrs{ 277170744Srrs struct sctp_cwnd_log sctp_clog; 278163953Srrs 279170744Srrs sctp_clog.x.cwnd.net = net; 280163953Srrs if (stcb->asoc.send_queue_cnt > 255) 281170744Srrs sctp_clog.x.cwnd.cnt_in_send = 255; 282163953Srrs else 283170744Srrs sctp_clog.x.cwnd.cnt_in_send = stcb->asoc.send_queue_cnt; 284163953Srrs if (stcb->asoc.stream_queue_cnt > 255) 285170744Srrs sctp_clog.x.cwnd.cnt_in_str = 255; 286163953Srrs else 287170744Srrs sctp_clog.x.cwnd.cnt_in_str = stcb->asoc.stream_queue_cnt; 288163953Srrs 289163953Srrs if (net) { 290170744Srrs sctp_clog.x.cwnd.cwnd_new_value = net->cwnd; 291170744Srrs sctp_clog.x.cwnd.inflight = net->flight_size; 292170744Srrs sctp_clog.x.cwnd.pseudo_cumack = net->pseudo_cumack; 293170744Srrs sctp_clog.x.cwnd.meets_pseudo_cumack = net->new_pseudo_cumack; 294170744Srrs sctp_clog.x.cwnd.need_new_pseudo_cumack = net->find_pseudo_cumack; 295163953Srrs } 296163953Srrs if (SCTP_CWNDLOG_PRESEND == from) { 297170744Srrs sctp_clog.x.cwnd.meets_pseudo_cumack = stcb->asoc.peers_rwnd; 298163953Srrs } 299170744Srrs sctp_clog.x.cwnd.cwnd_augment = augment; 300171943Srrs SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x", 301170744Srrs SCTP_LOG_EVENT_CWND, 302170744Srrs from, 303170744Srrs sctp_clog.x.misc.log1, 304170744Srrs sctp_clog.x.misc.log2, 305170744Srrs sctp_clog.x.misc.log3, 306170744Srrs sctp_clog.x.misc.log4); 307163953Srrs} 308163953Srrs 309163953Srrsvoid 310163953Srrssctp_log_lock(struct sctp_inpcb *inp, struct sctp_tcb *stcb, uint8_t from) 311163953Srrs{ 312170744Srrs struct sctp_cwnd_log sctp_clog; 313163953Srrs 314179141Srrs memset(&sctp_clog, 0, sizeof(sctp_clog)); 315164085Srrs if (inp) { 316170744Srrs sctp_clog.x.lock.sock = (void *)inp->sctp_socket; 317164085Srrs 318164085Srrs } else { 319170744Srrs sctp_clog.x.lock.sock = (void *)NULL; 320164085Srrs } 321170744Srrs sctp_clog.x.lock.inp = (void *)inp; 322163953Srrs if (stcb) { 323170744Srrs sctp_clog.x.lock.tcb_lock = mtx_owned(&stcb->tcb_mtx); 324163953Srrs } else { 325170744Srrs sctp_clog.x.lock.tcb_lock = SCTP_LOCK_UNKNOWN; 326163953Srrs } 327163953Srrs if (inp) { 328170744Srrs sctp_clog.x.lock.inp_lock = mtx_owned(&inp->inp_mtx); 329170744Srrs sctp_clog.x.lock.create_lock = mtx_owned(&inp->inp_create_mtx); 330163953Srrs } else { 331170744Srrs sctp_clog.x.lock.inp_lock = SCTP_LOCK_UNKNOWN; 332170744Srrs sctp_clog.x.lock.create_lock = SCTP_LOCK_UNKNOWN; 333163953Srrs } 334179783Srrs sctp_clog.x.lock.info_lock = rw_wowned(&SCTP_BASE_INFO(ipi_ep_mtx)); 335212225Srrs if (inp && (inp->sctp_socket)) { 336170744Srrs sctp_clog.x.lock.sock_lock = mtx_owned(&(inp->sctp_socket->so_rcv.sb_mtx)); 337170744Srrs sctp_clog.x.lock.sockrcvbuf_lock = mtx_owned(&(inp->sctp_socket->so_rcv.sb_mtx)); 338170744Srrs sctp_clog.x.lock.socksndbuf_lock = mtx_owned(&(inp->sctp_socket->so_snd.sb_mtx)); 339163953Srrs } else { 340170744Srrs sctp_clog.x.lock.sock_lock = SCTP_LOCK_UNKNOWN; 341170744Srrs sctp_clog.x.lock.sockrcvbuf_lock = SCTP_LOCK_UNKNOWN; 342170744Srrs sctp_clog.x.lock.socksndbuf_lock = SCTP_LOCK_UNKNOWN; 343163953Srrs } 344171943Srrs SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x", 345170744Srrs SCTP_LOG_LOCK_EVENT, 346170744Srrs from, 347170744Srrs sctp_clog.x.misc.log1, 348170744Srrs sctp_clog.x.misc.log2, 349170744Srrs sctp_clog.x.misc.log3, 350170744Srrs sctp_clog.x.misc.log4); 351163953Srrs} 352163953Srrs 353163953Srrsvoid 354163953Srrssctp_log_maxburst(struct sctp_tcb *stcb, struct sctp_nets *net, int error, int burst, uint8_t from) 355163953Srrs{ 356170744Srrs struct sctp_cwnd_log sctp_clog; 357163953Srrs 358179141Srrs memset(&sctp_clog, 0, sizeof(sctp_clog)); 359170744Srrs sctp_clog.x.cwnd.net = net; 360170744Srrs sctp_clog.x.cwnd.cwnd_new_value = error; 361170744Srrs sctp_clog.x.cwnd.inflight = net->flight_size; 362170744Srrs sctp_clog.x.cwnd.cwnd_augment = burst; 363163953Srrs if (stcb->asoc.send_queue_cnt > 255) 364170744Srrs sctp_clog.x.cwnd.cnt_in_send = 255; 365163953Srrs else 366170744Srrs sctp_clog.x.cwnd.cnt_in_send = stcb->asoc.send_queue_cnt; 367163953Srrs if (stcb->asoc.stream_queue_cnt > 255) 368170744Srrs sctp_clog.x.cwnd.cnt_in_str = 255; 369163953Srrs else 370170744Srrs sctp_clog.x.cwnd.cnt_in_str = stcb->asoc.stream_queue_cnt; 371171943Srrs SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x", 372170744Srrs SCTP_LOG_EVENT_MAXBURST, 373170744Srrs from, 374170744Srrs sctp_clog.x.misc.log1, 375170744Srrs sctp_clog.x.misc.log2, 376170744Srrs sctp_clog.x.misc.log3, 377170744Srrs sctp_clog.x.misc.log4); 378163953Srrs} 379163953Srrs 380163953Srrsvoid 381163953Srrssctp_log_rwnd(uint8_t from, uint32_t peers_rwnd, uint32_t snd_size, uint32_t overhead) 382163953Srrs{ 383170744Srrs struct sctp_cwnd_log sctp_clog; 384163953Srrs 385170744Srrs sctp_clog.x.rwnd.rwnd = peers_rwnd; 386170744Srrs sctp_clog.x.rwnd.send_size = snd_size; 387170744Srrs sctp_clog.x.rwnd.overhead = overhead; 388170744Srrs sctp_clog.x.rwnd.new_rwnd = 0; 389171943Srrs SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x", 390170744Srrs SCTP_LOG_EVENT_RWND, 391170744Srrs from, 392170744Srrs sctp_clog.x.misc.log1, 393170744Srrs sctp_clog.x.misc.log2, 394170744Srrs sctp_clog.x.misc.log3, 395170744Srrs sctp_clog.x.misc.log4); 396163953Srrs} 397163953Srrs 398163953Srrsvoid 399163953Srrssctp_log_rwnd_set(uint8_t from, uint32_t peers_rwnd, uint32_t flight_size, uint32_t overhead, uint32_t a_rwndval) 400163953Srrs{ 401170744Srrs struct sctp_cwnd_log sctp_clog; 402163953Srrs 403170744Srrs sctp_clog.x.rwnd.rwnd = peers_rwnd; 404170744Srrs sctp_clog.x.rwnd.send_size = flight_size; 405170744Srrs sctp_clog.x.rwnd.overhead = overhead; 406170744Srrs sctp_clog.x.rwnd.new_rwnd = a_rwndval; 407171943Srrs SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x", 408170744Srrs SCTP_LOG_EVENT_RWND, 409170744Srrs from, 410170744Srrs sctp_clog.x.misc.log1, 411170744Srrs sctp_clog.x.misc.log2, 412170744Srrs sctp_clog.x.misc.log3, 413170744Srrs sctp_clog.x.misc.log4); 414163953Srrs} 415163953Srrs 416163953Srrsvoid 417163953Srrssctp_log_mbcnt(uint8_t from, uint32_t total_oq, uint32_t book, uint32_t total_mbcnt_q, uint32_t mbcnt) 418163953Srrs{ 419170744Srrs struct sctp_cwnd_log sctp_clog; 420163953Srrs 421170744Srrs sctp_clog.x.mbcnt.total_queue_size = total_oq; 422170744Srrs sctp_clog.x.mbcnt.size_change = book; 423170744Srrs sctp_clog.x.mbcnt.total_queue_mb_size = total_mbcnt_q; 424170744Srrs sctp_clog.x.mbcnt.mbcnt_change = mbcnt; 425171943Srrs SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x", 426170744Srrs SCTP_LOG_EVENT_MBCNT, 427170744Srrs from, 428170744Srrs sctp_clog.x.misc.log1, 429170744Srrs sctp_clog.x.misc.log2, 430170744Srrs sctp_clog.x.misc.log3, 431170744Srrs sctp_clog.x.misc.log4); 432163953Srrs} 433163953Srrs 434163953Srrsvoid 435163953Srrssctp_misc_ints(uint8_t from, uint32_t a, uint32_t b, uint32_t c, uint32_t d) 436163953Srrs{ 437171943Srrs SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x", 438170744Srrs SCTP_LOG_MISC_EVENT, 439170744Srrs from, 440170744Srrs a, b, c, d); 441163953Srrs} 442163953Srrs 443163953Srrsvoid 444231038Stuexensctp_wakeup_log(struct sctp_tcb *stcb, uint32_t wake_cnt, int from) 445163953Srrs{ 446170744Srrs struct sctp_cwnd_log sctp_clog; 447163953Srrs 448170744Srrs sctp_clog.x.wake.stcb = (void *)stcb; 449170744Srrs sctp_clog.x.wake.wake_cnt = wake_cnt; 450170744Srrs sctp_clog.x.wake.flight = stcb->asoc.total_flight_count; 451170744Srrs sctp_clog.x.wake.send_q = stcb->asoc.send_queue_cnt; 452170744Srrs sctp_clog.x.wake.sent_q = stcb->asoc.sent_queue_cnt; 453163953Srrs 454163953Srrs if (stcb->asoc.stream_queue_cnt < 0xff) 455170744Srrs sctp_clog.x.wake.stream_qcnt = (uint8_t) stcb->asoc.stream_queue_cnt; 456163953Srrs else 457170744Srrs sctp_clog.x.wake.stream_qcnt = 0xff; 458163953Srrs 459163953Srrs if (stcb->asoc.chunks_on_out_queue < 0xff) 460170744Srrs sctp_clog.x.wake.chunks_on_oque = (uint8_t) stcb->asoc.chunks_on_out_queue; 461163953Srrs else 462170744Srrs sctp_clog.x.wake.chunks_on_oque = 0xff; 463163953Srrs 464170744Srrs sctp_clog.x.wake.sctpflags = 0; 465163953Srrs /* set in the defered mode stuff */ 466163953Srrs if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_DONT_WAKE) 467170744Srrs sctp_clog.x.wake.sctpflags |= 1; 468163953Srrs if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_WAKEOUTPUT) 469170744Srrs sctp_clog.x.wake.sctpflags |= 2; 470163953Srrs if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_WAKEINPUT) 471170744Srrs sctp_clog.x.wake.sctpflags |= 4; 472163953Srrs /* what about the sb */ 473163953Srrs if (stcb->sctp_socket) { 474163953Srrs struct socket *so = stcb->sctp_socket; 475163953Srrs 476170744Srrs sctp_clog.x.wake.sbflags = (uint8_t) ((so->so_snd.sb_flags & 0x00ff)); 477163953Srrs } else { 478170744Srrs sctp_clog.x.wake.sbflags = 0xff; 479163953Srrs } 480171943Srrs SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x", 481170744Srrs SCTP_LOG_EVENT_WAKE, 482170744Srrs from, 483170744Srrs sctp_clog.x.misc.log1, 484170744Srrs sctp_clog.x.misc.log2, 485170744Srrs sctp_clog.x.misc.log3, 486170744Srrs sctp_clog.x.misc.log4); 487163953Srrs} 488163953Srrs 489163953Srrsvoid 490231038Stuexensctp_log_block(uint8_t from, struct sctp_association *asoc, int sendlen) 491163953Srrs{ 492170744Srrs struct sctp_cwnd_log sctp_clog; 493163953Srrs 494170744Srrs sctp_clog.x.blk.onsb = asoc->total_output_queue_size; 495170744Srrs sctp_clog.x.blk.send_sent_qcnt = (uint16_t) (asoc->send_queue_cnt + asoc->sent_queue_cnt); 496170744Srrs sctp_clog.x.blk.peer_rwnd = asoc->peers_rwnd; 497170744Srrs sctp_clog.x.blk.stream_qcnt = (uint16_t) asoc->stream_queue_cnt; 498170744Srrs sctp_clog.x.blk.chunks_on_oque = (uint16_t) asoc->chunks_on_out_queue; 499170744Srrs sctp_clog.x.blk.flight_size = (uint16_t) (asoc->total_flight / 1024); 500170744Srrs sctp_clog.x.blk.sndlen = sendlen; 501171943Srrs SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x", 502170744Srrs SCTP_LOG_EVENT_BLOCK, 503170744Srrs from, 504170744Srrs sctp_clog.x.misc.log1, 505170744Srrs sctp_clog.x.misc.log2, 506170744Srrs sctp_clog.x.misc.log3, 507170744Srrs sctp_clog.x.misc.log4); 508163953Srrs} 509163953Srrs 510163953Srrsint 511231038Stuexensctp_fill_stat_log(void *optval SCTP_UNUSED, size_t *optsize SCTP_UNUSED) 512163953Srrs{ 513170744Srrs /* May need to fix this if ktrdump does not work */ 514163953Srrs return (0); 515163953Srrs} 516163953Srrs 517163953Srrs#ifdef SCTP_AUDITING_ENABLED 518163953Srrsuint8_t sctp_audit_data[SCTP_AUDIT_SIZE][2]; 519163953Srrsstatic int sctp_audit_indx = 0; 520163953Srrs 521163953Srrsstatic 522163953Srrsvoid 523163953Srrssctp_print_audit_report(void) 524163953Srrs{ 525163953Srrs int i; 526163953Srrs int cnt; 527163953Srrs 528163953Srrs cnt = 0; 529163953Srrs for (i = sctp_audit_indx; i < SCTP_AUDIT_SIZE; i++) { 530163953Srrs if ((sctp_audit_data[i][0] == 0xe0) && 531163953Srrs (sctp_audit_data[i][1] == 0x01)) { 532163953Srrs cnt = 0; 533169420Srrs SCTP_PRINTF("\n"); 534163953Srrs } else if (sctp_audit_data[i][0] == 0xf0) { 535163953Srrs cnt = 0; 536169420Srrs SCTP_PRINTF("\n"); 537163953Srrs } else if ((sctp_audit_data[i][0] == 0xc0) && 538163953Srrs (sctp_audit_data[i][1] == 0x01)) { 539169420Srrs SCTP_PRINTF("\n"); 540163953Srrs cnt = 0; 541163953Srrs } 542169420Srrs SCTP_PRINTF("%2.2x%2.2x ", (uint32_t) sctp_audit_data[i][0], 543163953Srrs (uint32_t) sctp_audit_data[i][1]); 544163953Srrs cnt++; 545163953Srrs if ((cnt % 14) == 0) 546169420Srrs SCTP_PRINTF("\n"); 547163953Srrs } 548163953Srrs for (i = 0; i < sctp_audit_indx; i++) { 549163953Srrs if ((sctp_audit_data[i][0] == 0xe0) && 550163953Srrs (sctp_audit_data[i][1] == 0x01)) { 551163953Srrs cnt = 0; 552169420Srrs SCTP_PRINTF("\n"); 553163953Srrs } else if (sctp_audit_data[i][0] == 0xf0) { 554163953Srrs cnt = 0; 555169420Srrs SCTP_PRINTF("\n"); 556163953Srrs } else if ((sctp_audit_data[i][0] == 0xc0) && 557163953Srrs (sctp_audit_data[i][1] == 0x01)) { 558169420Srrs SCTP_PRINTF("\n"); 559163953Srrs cnt = 0; 560163953Srrs } 561169420Srrs SCTP_PRINTF("%2.2x%2.2x ", (uint32_t) sctp_audit_data[i][0], 562163953Srrs (uint32_t) sctp_audit_data[i][1]); 563163953Srrs cnt++; 564163953Srrs if ((cnt % 14) == 0) 565169420Srrs SCTP_PRINTF("\n"); 566163953Srrs } 567169420Srrs SCTP_PRINTF("\n"); 568163953Srrs} 569163953Srrs 570163953Srrsvoid 571163953Srrssctp_auditing(int from, struct sctp_inpcb *inp, struct sctp_tcb *stcb, 572163953Srrs struct sctp_nets *net) 573163953Srrs{ 574163953Srrs int resend_cnt, tot_out, rep, tot_book_cnt; 575163953Srrs struct sctp_nets *lnet; 576163953Srrs struct sctp_tmit_chunk *chk; 577163953Srrs 578163953Srrs sctp_audit_data[sctp_audit_indx][0] = 0xAA; 579163953Srrs sctp_audit_data[sctp_audit_indx][1] = 0x000000ff & from; 580163953Srrs sctp_audit_indx++; 581163953Srrs if (sctp_audit_indx >= SCTP_AUDIT_SIZE) { 582163953Srrs sctp_audit_indx = 0; 583163953Srrs } 584163953Srrs if (inp == NULL) { 585163953Srrs sctp_audit_data[sctp_audit_indx][0] = 0xAF; 586163953Srrs sctp_audit_data[sctp_audit_indx][1] = 0x01; 587163953Srrs sctp_audit_indx++; 588163953Srrs if (sctp_audit_indx >= SCTP_AUDIT_SIZE) { 589163953Srrs sctp_audit_indx = 0; 590163953Srrs } 591163953Srrs return; 592163953Srrs } 593163953Srrs if (stcb == NULL) { 594163953Srrs sctp_audit_data[sctp_audit_indx][0] = 0xAF; 595163953Srrs sctp_audit_data[sctp_audit_indx][1] = 0x02; 596163953Srrs sctp_audit_indx++; 597163953Srrs if (sctp_audit_indx >= SCTP_AUDIT_SIZE) { 598163953Srrs sctp_audit_indx = 0; 599163953Srrs } 600163953Srrs return; 601163953Srrs } 602163953Srrs sctp_audit_data[sctp_audit_indx][0] = 0xA1; 603163953Srrs sctp_audit_data[sctp_audit_indx][1] = 604163953Srrs (0x000000ff & stcb->asoc.sent_queue_retran_cnt); 605163953Srrs sctp_audit_indx++; 606163953Srrs if (sctp_audit_indx >= SCTP_AUDIT_SIZE) { 607163953Srrs sctp_audit_indx = 0; 608163953Srrs } 609163953Srrs rep = 0; 610163953Srrs tot_book_cnt = 0; 611163953Srrs resend_cnt = tot_out = 0; 612163953Srrs TAILQ_FOREACH(chk, &stcb->asoc.sent_queue, sctp_next) { 613163953Srrs if (chk->sent == SCTP_DATAGRAM_RESEND) { 614163953Srrs resend_cnt++; 615163953Srrs } else if (chk->sent < SCTP_DATAGRAM_RESEND) { 616163953Srrs tot_out += chk->book_size; 617163953Srrs tot_book_cnt++; 618163953Srrs } 619163953Srrs } 620163953Srrs if (resend_cnt != stcb->asoc.sent_queue_retran_cnt) { 621163953Srrs sctp_audit_data[sctp_audit_indx][0] = 0xAF; 622163953Srrs sctp_audit_data[sctp_audit_indx][1] = 0xA1; 623163953Srrs sctp_audit_indx++; 624163953Srrs if (sctp_audit_indx >= SCTP_AUDIT_SIZE) { 625163953Srrs sctp_audit_indx = 0; 626163953Srrs } 627169420Srrs SCTP_PRINTF("resend_cnt:%d asoc-tot:%d\n", 628163953Srrs resend_cnt, stcb->asoc.sent_queue_retran_cnt); 629163953Srrs rep = 1; 630163953Srrs stcb->asoc.sent_queue_retran_cnt = resend_cnt; 631163953Srrs sctp_audit_data[sctp_audit_indx][0] = 0xA2; 632163953Srrs sctp_audit_data[sctp_audit_indx][1] = 633163953Srrs (0x000000ff & stcb->asoc.sent_queue_retran_cnt); 634163953Srrs sctp_audit_indx++; 635163953Srrs if (sctp_audit_indx >= SCTP_AUDIT_SIZE) { 636163953Srrs sctp_audit_indx = 0; 637163953Srrs } 638163953Srrs } 639163953Srrs if (tot_out != stcb->asoc.total_flight) { 640163953Srrs sctp_audit_data[sctp_audit_indx][0] = 0xAF; 641163953Srrs sctp_audit_data[sctp_audit_indx][1] = 0xA2; 642163953Srrs sctp_audit_indx++; 643163953Srrs if (sctp_audit_indx >= SCTP_AUDIT_SIZE) { 644163953Srrs sctp_audit_indx = 0; 645163953Srrs } 646163953Srrs rep = 1; 647169420Srrs SCTP_PRINTF("tot_flt:%d asoc_tot:%d\n", tot_out, 648163953Srrs (int)stcb->asoc.total_flight); 649163953Srrs stcb->asoc.total_flight = tot_out; 650163953Srrs } 651163953Srrs if (tot_book_cnt != stcb->asoc.total_flight_count) { 652163953Srrs sctp_audit_data[sctp_audit_indx][0] = 0xAF; 653163953Srrs sctp_audit_data[sctp_audit_indx][1] = 0xA5; 654163953Srrs sctp_audit_indx++; 655163953Srrs if (sctp_audit_indx >= SCTP_AUDIT_SIZE) { 656163953Srrs sctp_audit_indx = 0; 657163953Srrs } 658163953Srrs rep = 1; 659207099Stuexen SCTP_PRINTF("tot_flt_book:%d\n", tot_book_cnt); 660163953Srrs 661163953Srrs stcb->asoc.total_flight_count = tot_book_cnt; 662163953Srrs } 663163953Srrs tot_out = 0; 664163953Srrs TAILQ_FOREACH(lnet, &stcb->asoc.nets, sctp_next) { 665163953Srrs tot_out += lnet->flight_size; 666163953Srrs } 667163953Srrs if (tot_out != stcb->asoc.total_flight) { 668163953Srrs sctp_audit_data[sctp_audit_indx][0] = 0xAF; 669163953Srrs sctp_audit_data[sctp_audit_indx][1] = 0xA3; 670163953Srrs sctp_audit_indx++; 671163953Srrs if (sctp_audit_indx >= SCTP_AUDIT_SIZE) { 672163953Srrs sctp_audit_indx = 0; 673163953Srrs } 674163953Srrs rep = 1; 675169420Srrs SCTP_PRINTF("real flight:%d net total was %d\n", 676163953Srrs stcb->asoc.total_flight, tot_out); 677163953Srrs /* now corrective action */ 678163953Srrs TAILQ_FOREACH(lnet, &stcb->asoc.nets, sctp_next) { 679163953Srrs 680163953Srrs tot_out = 0; 681163953Srrs TAILQ_FOREACH(chk, &stcb->asoc.sent_queue, sctp_next) { 682163953Srrs if ((chk->whoTo == lnet) && 683163953Srrs (chk->sent < SCTP_DATAGRAM_RESEND)) { 684163953Srrs tot_out += chk->book_size; 685163953Srrs } 686163953Srrs } 687163953Srrs if (lnet->flight_size != tot_out) { 688207099Stuexen SCTP_PRINTF("net:%p flight was %d corrected to %d\n", 689252927Stuexen (void *)lnet, lnet->flight_size, 690169420Srrs tot_out); 691163953Srrs lnet->flight_size = tot_out; 692163953Srrs } 693163953Srrs } 694163953Srrs } 695163953Srrs if (rep) { 696163953Srrs sctp_print_audit_report(); 697163953Srrs } 698163953Srrs} 699163953Srrs 700163953Srrsvoid 701163953Srrssctp_audit_log(uint8_t ev, uint8_t fd) 702163953Srrs{ 703163953Srrs 704163953Srrs sctp_audit_data[sctp_audit_indx][0] = ev; 705163953Srrs sctp_audit_data[sctp_audit_indx][1] = fd; 706163953Srrs sctp_audit_indx++; 707163953Srrs if (sctp_audit_indx >= SCTP_AUDIT_SIZE) { 708163953Srrs sctp_audit_indx = 0; 709163953Srrs } 710163953Srrs} 711163953Srrs 712163953Srrs#endif 713163953Srrs 714163953Srrs/* 715214918Stuexen * sctp_stop_timers_for_shutdown() should be called 716214918Stuexen * when entering the SHUTDOWN_SENT or SHUTDOWN_ACK_SENT 717214918Stuexen * state to make sure that all timers are stopped. 718214918Stuexen */ 719214918Stuexenvoid 720214918Stuexensctp_stop_timers_for_shutdown(struct sctp_tcb *stcb) 721214918Stuexen{ 722214918Stuexen struct sctp_association *asoc; 723214918Stuexen struct sctp_nets *net; 724214918Stuexen 725214918Stuexen asoc = &stcb->asoc; 726214918Stuexen 727214918Stuexen (void)SCTP_OS_TIMER_STOP(&asoc->dack_timer.timer); 728214918Stuexen (void)SCTP_OS_TIMER_STOP(&asoc->strreset_timer.timer); 729214918Stuexen (void)SCTP_OS_TIMER_STOP(&asoc->asconf_timer.timer); 730214918Stuexen (void)SCTP_OS_TIMER_STOP(&asoc->autoclose_timer.timer); 731214918Stuexen (void)SCTP_OS_TIMER_STOP(&asoc->delayed_event_timer.timer); 732214918Stuexen TAILQ_FOREACH(net, &asoc->nets, sctp_next) { 733214918Stuexen (void)SCTP_OS_TIMER_STOP(&net->pmtu_timer.timer); 734224641Stuexen (void)SCTP_OS_TIMER_STOP(&net->hb_timer.timer); 735214918Stuexen } 736214918Stuexen} 737214918Stuexen 738214918Stuexen/* 739163953Srrs * a list of sizes based on typical mtu's, used only if next hop size not 740163953Srrs * returned. 741163953Srrs */ 742214939Stuexenstatic uint32_t sctp_mtu_sizes[] = { 743163953Srrs 68, 744163953Srrs 296, 745163953Srrs 508, 746163953Srrs 512, 747163953Srrs 544, 748163953Srrs 576, 749163953Srrs 1006, 750163953Srrs 1492, 751163953Srrs 1500, 752163953Srrs 1536, 753163953Srrs 2002, 754163953Srrs 2048, 755163953Srrs 4352, 756163953Srrs 4464, 757163953Srrs 8166, 758163953Srrs 17914, 759163953Srrs 32000, 760163953Srrs 65535 761163953Srrs}; 762163953Srrs 763214939Stuexen/* 764214939Stuexen * Return the largest MTU smaller than val. If there is no 765214939Stuexen * entry, just return val. 766214939Stuexen */ 767214939Stuexenuint32_t 768214939Stuexensctp_get_prev_mtu(uint32_t val) 769163953Srrs{ 770214939Stuexen uint32_t i; 771163953Srrs 772214939Stuexen if (val <= sctp_mtu_sizes[0]) { 773214939Stuexen return (val); 774214939Stuexen } 775214939Stuexen for (i = 1; i < (sizeof(sctp_mtu_sizes) / sizeof(uint32_t)); i++) { 776214939Stuexen if (val <= sctp_mtu_sizes[i]) { 777163953Srrs break; 778163953Srrs } 779163953Srrs } 780214939Stuexen return (sctp_mtu_sizes[i - 1]); 781163953Srrs} 782163953Srrs 783214939Stuexen/* 784214939Stuexen * Return the smallest MTU larger than val. If there is no 785214939Stuexen * entry, just return val. 786214939Stuexen */ 787214939Stuexenuint32_t 788231038Stuexensctp_get_next_mtu(uint32_t val) 789214939Stuexen{ 790214939Stuexen /* select another MTU that is just bigger than this one */ 791214939Stuexen uint32_t i; 792214939Stuexen 793214939Stuexen for (i = 0; i < (sizeof(sctp_mtu_sizes) / sizeof(uint32_t)); i++) { 794214939Stuexen if (val < sctp_mtu_sizes[i]) { 795214939Stuexen return (sctp_mtu_sizes[i]); 796214939Stuexen } 797214939Stuexen } 798214939Stuexen return (val); 799214939Stuexen} 800214939Stuexen 801163953Srrsvoid 802163953Srrssctp_fill_random_store(struct sctp_pcb *m) 803163953Srrs{ 804163953Srrs /* 805163953Srrs * Here we use the MD5/SHA-1 to hash with our good randomNumbers and 806163953Srrs * our counter. The result becomes our good random numbers and we 807163953Srrs * then setup to give these out. Note that we do no locking to 808163953Srrs * protect this. This is ok, since if competing folks call this we 809169352Srrs * will get more gobbled gook in the random store which is what we 810163953Srrs * want. There is a danger that two guys will use the same random 811163953Srrs * numbers, but thats ok too since that is random as well :-> 812163953Srrs */ 813163953Srrs m->store_at = 0; 814169420Srrs (void)sctp_hmac(SCTP_HMAC, (uint8_t *) m->random_numbers, 815163953Srrs sizeof(m->random_numbers), (uint8_t *) & m->random_counter, 816163953Srrs sizeof(m->random_counter), (uint8_t *) m->random_store); 817163953Srrs m->random_counter++; 818163953Srrs} 819163953Srrs 820163953Srrsuint32_t 821172091Srrssctp_select_initial_TSN(struct sctp_pcb *inp) 822163953Srrs{ 823163953Srrs /* 824163953Srrs * A true implementation should use random selection process to get 825163953Srrs * the initial stream sequence number, using RFC1750 as a good 826163953Srrs * guideline 827163953Srrs */ 828165647Srrs uint32_t x, *xp; 829163953Srrs uint8_t *p; 830172091Srrs int store_at, new_store; 831163953Srrs 832172091Srrs if (inp->initial_sequence_debug != 0) { 833163953Srrs uint32_t ret; 834163953Srrs 835172091Srrs ret = inp->initial_sequence_debug; 836172091Srrs inp->initial_sequence_debug++; 837163953Srrs return (ret); 838163953Srrs } 839172091Srrsretry: 840172091Srrs store_at = inp->store_at; 841172091Srrs new_store = store_at + sizeof(uint32_t); 842172091Srrs if (new_store >= (SCTP_SIGNATURE_SIZE - 3)) { 843172091Srrs new_store = 0; 844172091Srrs } 845172091Srrs if (!atomic_cmpset_int(&inp->store_at, store_at, new_store)) { 846172091Srrs goto retry; 847172091Srrs } 848172091Srrs if (new_store == 0) { 849163953Srrs /* Refill the random store */ 850172091Srrs sctp_fill_random_store(inp); 851163953Srrs } 852172091Srrs p = &inp->random_store[store_at]; 853165647Srrs xp = (uint32_t *) p; 854163953Srrs x = *xp; 855163953Srrs return (x); 856163953Srrs} 857163953Srrs 858163953Srrsuint32_t 859231038Stuexensctp_select_a_tag(struct sctp_inpcb *inp, uint16_t lport, uint16_t rport, int check) 860163953Srrs{ 861231038Stuexen uint32_t x; 862163953Srrs struct timeval now; 863163953Srrs 864231038Stuexen if (check) { 865231038Stuexen (void)SCTP_GETTIME_TIMEVAL(&now); 866231038Stuexen } 867231038Stuexen for (;;) { 868172091Srrs x = sctp_select_initial_TSN(&inp->sctp_ep); 869163953Srrs if (x == 0) { 870163953Srrs /* we never use 0 */ 871163953Srrs continue; 872163953Srrs } 873231038Stuexen if (!check || sctp_is_vtag_good(x, lport, rport, &now)) { 874231038Stuexen break; 875163953Srrs } 876163953Srrs } 877163953Srrs return (x); 878163953Srrs} 879163953Srrs 880163953Srrsint 881252961Stuexensctp_init_asoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, 882206137Stuexen uint32_t override_tag, uint32_t vrf_id) 883163953Srrs{ 884170138Srrs struct sctp_association *asoc; 885170138Srrs 886163953Srrs /* 887163953Srrs * Anything set to zero is taken care of by the allocation routine's 888163953Srrs * bzero 889163953Srrs */ 890163953Srrs 891163953Srrs /* 892163953Srrs * Up front select what scoping to apply on addresses I tell my peer 893163953Srrs * Not sure what to do with these right now, we will need to come up 894163953Srrs * with a way to set them. We may need to pass them through from the 895163953Srrs * caller in the sctp_aloc_assoc() function. 896163953Srrs */ 897163953Srrs int i; 898163953Srrs 899170138Srrs asoc = &stcb->asoc; 900163953Srrs /* init all variables to a known value. */ 901171943Srrs SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_INUSE); 902252961Stuexen asoc->max_burst = inp->sctp_ep.max_burst; 903252961Stuexen asoc->fr_max_burst = inp->sctp_ep.fr_max_burst; 904252961Stuexen asoc->heart_beat_delay = TICKS_TO_MSEC(inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT]); 905252961Stuexen asoc->cookie_life = inp->sctp_ep.def_cookie_life; 906252961Stuexen asoc->sctp_cmt_on_off = inp->sctp_cmt_on_off; 907252961Stuexen asoc->ecn_allowed = inp->sctp_ecn_enable; 908185694Srrs asoc->sctp_nr_sack_on_off = (uint8_t) SCTP_BASE_SYSCTL(sctp_nr_sack_on_off); 909224641Stuexen asoc->sctp_cmt_pf = (uint8_t) 0; 910252961Stuexen asoc->sctp_frag_point = inp->sctp_frag_point; 911252961Stuexen asoc->sctp_features = inp->sctp_features; 912252961Stuexen asoc->default_dscp = inp->sctp_ep.default_dscp; 913167598Srrs#ifdef INET6 914252961Stuexen if (inp->sctp_ep.default_flowlabel) { 915252961Stuexen asoc->default_flowlabel = inp->sctp_ep.default_flowlabel; 916225549Stuexen } else { 917252961Stuexen if (inp->ip_inp.inp.inp_flags & IN6P_AUTOFLOWLABEL) { 918252961Stuexen asoc->default_flowlabel = sctp_select_initial_TSN(&inp->sctp_ep); 919225549Stuexen asoc->default_flowlabel &= 0x000fffff; 920225549Stuexen asoc->default_flowlabel |= 0x80000000; 921225549Stuexen } else { 922225549Stuexen asoc->default_flowlabel = 0; 923225549Stuexen } 924225549Stuexen } 925163953Srrs#endif 926174257Srrs asoc->sb_send_resv = 0; 927163953Srrs if (override_tag) { 928185694Srrs asoc->my_vtag = override_tag; 929163953Srrs } else { 930252961Stuexen asoc->my_vtag = sctp_select_a_tag(inp, stcb->sctp_ep->sctp_lport, stcb->rport, 1); 931163953Srrs } 932164144Srrs /* Get the nonce tags */ 933252961Stuexen asoc->my_vtag_nonce = sctp_select_a_tag(inp, stcb->sctp_ep->sctp_lport, stcb->rport, 0); 934252961Stuexen asoc->peer_vtag_nonce = sctp_select_a_tag(inp, stcb->sctp_ep->sctp_lport, stcb->rport, 0); 935167598Srrs asoc->vrf_id = vrf_id; 936164144Srrs 937171477Srrs#ifdef SCTP_ASOCLOG_OF_TSNS 938171477Srrs asoc->tsn_in_at = 0; 939171477Srrs asoc->tsn_out_at = 0; 940171477Srrs asoc->tsn_in_wrapped = 0; 941171477Srrs asoc->tsn_out_wrapped = 0; 942171477Srrs asoc->cumack_log_at = 0; 943172703Srrs asoc->cumack_log_atsnt = 0; 944171477Srrs#endif 945171477Srrs#ifdef SCTP_FS_SPEC_LOG 946171477Srrs asoc->fs_index = 0; 947171477Srrs#endif 948163953Srrs asoc->refcnt = 0; 949163953Srrs asoc->assoc_up_sent = 0; 950163953Srrs asoc->asconf_seq_out = asoc->str_reset_seq_out = asoc->init_seq_number = asoc->sending_seq = 951252961Stuexen sctp_select_initial_TSN(&inp->sctp_ep); 952179157Srrs asoc->asconf_seq_out_acked = asoc->asconf_seq_out - 1; 953163953Srrs /* we are optimisitic here */ 954163953Srrs asoc->peer_supports_pktdrop = 1; 955185694Srrs asoc->peer_supports_nat = 0; 956163953Srrs asoc->sent_queue_retran_cnt = 0; 957163953Srrs 958163953Srrs /* for CMT */ 959190689Srrs asoc->last_net_cmt_send_started = NULL; 960163953Srrs 961163953Srrs /* This will need to be adjusted */ 962163953Srrs asoc->last_acked_seq = asoc->init_seq_number - 1; 963163953Srrs asoc->advanced_peer_ack_point = asoc->last_acked_seq; 964163953Srrs asoc->asconf_seq_in = asoc->last_acked_seq; 965163953Srrs 966163953Srrs /* here we are different, we hold the next one we expect */ 967163953Srrs asoc->str_reset_seq_in = asoc->last_acked_seq + 1; 968163953Srrs 969252961Stuexen asoc->initial_init_rto_max = inp->sctp_ep.initial_init_rto_max; 970252961Stuexen asoc->initial_rto = inp->sctp_ep.initial_rto; 971163953Srrs 972252961Stuexen asoc->max_init_times = inp->sctp_ep.max_init_times; 973252961Stuexen asoc->max_send_times = inp->sctp_ep.max_send_times; 974252961Stuexen asoc->def_net_failure = inp->sctp_ep.def_net_failure; 975252961Stuexen asoc->def_net_pf_threshold = inp->sctp_ep.def_net_pf_threshold; 976163953Srrs asoc->free_chunk_cnt = 0; 977163953Srrs 978163953Srrs asoc->iam_blocking = 0; 979252961Stuexen asoc->context = inp->sctp_context; 980252961Stuexen asoc->local_strreset_support = inp->local_strreset_support; 981252961Stuexen asoc->def_send = inp->def_send; 982252961Stuexen asoc->delayed_ack = TICKS_TO_MSEC(inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV]); 983252961Stuexen asoc->sack_freq = inp->sctp_ep.sctp_sack_freq; 984163953Srrs asoc->pr_sctp_cnt = 0; 985163953Srrs asoc->total_output_queue_size = 0; 986163953Srrs 987252961Stuexen if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) { 988252961Stuexen asoc->scope.ipv6_addr_legal = 1; 989252961Stuexen if (SCTP_IPV6_V6ONLY(inp) == 0) { 990252961Stuexen asoc->scope.ipv4_addr_legal = 1; 991163953Srrs } else { 992252961Stuexen asoc->scope.ipv4_addr_legal = 0; 993163953Srrs } 994163953Srrs } else { 995252961Stuexen asoc->scope.ipv6_addr_legal = 0; 996252961Stuexen asoc->scope.ipv4_addr_legal = 1; 997163953Srrs } 998163953Srrs 999252961Stuexen asoc->my_rwnd = max(SCTP_SB_LIMIT_RCV(inp->sctp_socket), SCTP_MINIMAL_RWND); 1000252961Stuexen asoc->peers_rwnd = SCTP_SB_LIMIT_RCV(inp->sctp_socket); 1001163953Srrs 1002252961Stuexen asoc->smallest_mtu = inp->sctp_frag_point; 1003252961Stuexen asoc->minrto = inp->sctp_ep.sctp_minrto; 1004252961Stuexen asoc->maxrto = inp->sctp_ep.sctp_maxrto; 1005163953Srrs 1006163953Srrs asoc->locked_on_sending = NULL; 1007163953Srrs asoc->stream_locked_on = 0; 1008163953Srrs asoc->ecn_echo_cnt_onq = 0; 1009163953Srrs asoc->stream_locked = 0; 1010163953Srrs 1011167598Srrs asoc->send_sack = 1; 1012167598Srrs 1013167598Srrs LIST_INIT(&asoc->sctp_restricted_addrs); 1014167598Srrs 1015163953Srrs TAILQ_INIT(&asoc->nets); 1016163953Srrs TAILQ_INIT(&asoc->pending_reply_queue); 1017171990Srrs TAILQ_INIT(&asoc->asconf_ack_sent); 1018163953Srrs /* Setup to fill the hb random cache at first HB */ 1019163953Srrs asoc->hb_random_idx = 4; 1020163953Srrs 1021252961Stuexen asoc->sctp_autoclose_ticks = inp->sctp_ep.auto_close_time; 1022163953Srrs 1023252961Stuexen stcb->asoc.congestion_control_module = inp->sctp_ep.sctp_default_cc_module; 1024252961Stuexen stcb->asoc.cc_functions = sctp_cc_functions[inp->sctp_ep.sctp_default_cc_module]; 1025171440Srrs 1026252961Stuexen stcb->asoc.stream_scheduling_module = inp->sctp_ep.sctp_default_ss_module; 1027252961Stuexen stcb->asoc.ss_functions = sctp_ss_functions[inp->sctp_ep.sctp_default_ss_module]; 1028217760Stuexen 1029171440Srrs /* 1030163953Srrs * Now the stream parameters, here we allocate space for all streams 1031163953Srrs * that we request by default. 1032163953Srrs */ 1033188854Srrs asoc->strm_realoutsize = asoc->streamoutcnt = asoc->pre_open_streams = 1034252961Stuexen inp->sctp_ep.pre_open_stream_count; 1035163953Srrs SCTP_MALLOC(asoc->strmout, struct sctp_stream_out *, 1036163953Srrs asoc->streamoutcnt * sizeof(struct sctp_stream_out), 1037170091Srrs SCTP_M_STRMO); 1038163953Srrs if (asoc->strmout == NULL) { 1039163953Srrs /* big trouble no memory */ 1040171943Srrs SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ENOMEM); 1041163953Srrs return (ENOMEM); 1042163953Srrs } 1043163953Srrs for (i = 0; i < asoc->streamoutcnt; i++) { 1044163953Srrs /* 1045163953Srrs * inbound side must be set to 0xffff, also NOTE when we get 1046163953Srrs * the INIT-ACK back (for INIT sender) we MUST reduce the 1047163953Srrs * count (streamoutcnt) but first check if we sent to any of 1048163953Srrs * the upper streams that were dropped (if some were). Those 1049163953Srrs * that were dropped must be notified to the upper layer as 1050163953Srrs * failed to send. 1051163953Srrs */ 1052252940Stuexen asoc->strmout[i].next_sequence_send = 0x0; 1053163953Srrs TAILQ_INIT(&asoc->strmout[i].outqueue); 1054252943Stuexen asoc->strmout[i].chunks_on_queues = 0; 1055163953Srrs asoc->strmout[i].stream_no = i; 1056163953Srrs asoc->strmout[i].last_msg_incomplete = 0; 1057218241Stuexen asoc->ss_functions.sctp_ss_init_stream(&asoc->strmout[i], NULL); 1058163953Srrs } 1059217760Stuexen asoc->ss_functions.sctp_ss_init(stcb, asoc, 0); 1060217760Stuexen 1061163953Srrs /* Now the mapping array */ 1062163953Srrs asoc->mapping_array_size = SCTP_INITIAL_MAPPING_ARRAY; 1063163953Srrs SCTP_MALLOC(asoc->mapping_array, uint8_t *, asoc->mapping_array_size, 1064170091Srrs SCTP_M_MAP); 1065163953Srrs if (asoc->mapping_array == NULL) { 1066170091Srrs SCTP_FREE(asoc->strmout, SCTP_M_STRMO); 1067171943Srrs SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ENOMEM); 1068163953Srrs return (ENOMEM); 1069163953Srrs } 1070163953Srrs memset(asoc->mapping_array, 0, asoc->mapping_array_size); 1071206137Stuexen SCTP_MALLOC(asoc->nr_mapping_array, uint8_t *, asoc->mapping_array_size, 1072185694Srrs SCTP_M_MAP); 1073193089Srrs if (asoc->nr_mapping_array == NULL) { 1074193089Srrs SCTP_FREE(asoc->strmout, SCTP_M_STRMO); 1075193089Srrs SCTP_FREE(asoc->mapping_array, SCTP_M_MAP); 1076193089Srrs SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ENOMEM); 1077193089Srrs return (ENOMEM); 1078193089Srrs } 1079206137Stuexen memset(asoc->nr_mapping_array, 0, asoc->mapping_array_size); 1080185694Srrs 1081163953Srrs /* Now the init of the other outqueues */ 1082163953Srrs TAILQ_INIT(&asoc->free_chunks); 1083163953Srrs TAILQ_INIT(&asoc->control_send_queue); 1084179157Srrs TAILQ_INIT(&asoc->asconf_send_queue); 1085163953Srrs TAILQ_INIT(&asoc->send_queue); 1086163953Srrs TAILQ_INIT(&asoc->sent_queue); 1087163953Srrs TAILQ_INIT(&asoc->reasmqueue); 1088163953Srrs TAILQ_INIT(&asoc->resetHead); 1089252961Stuexen asoc->max_inbound_streams = inp->sctp_ep.max_open_streams_intome; 1090163953Srrs TAILQ_INIT(&asoc->asconf_queue); 1091163953Srrs /* authentication fields */ 1092163953Srrs asoc->authinfo.random = NULL; 1093185694Srrs asoc->authinfo.active_keyid = 0; 1094163953Srrs asoc->authinfo.assoc_key = NULL; 1095163953Srrs asoc->authinfo.assoc_keyid = 0; 1096163953Srrs asoc->authinfo.recv_key = NULL; 1097163953Srrs asoc->authinfo.recv_keyid = 0; 1098163953Srrs LIST_INIT(&asoc->shared_keys); 1099166675Srrs asoc->marked_retrans = 0; 1100252961Stuexen asoc->port = inp->sctp_ep.port; 1101166675Srrs asoc->timoinit = 0; 1102166675Srrs asoc->timodata = 0; 1103166675Srrs asoc->timosack = 0; 1104166675Srrs asoc->timoshutdown = 0; 1105166675Srrs asoc->timoheartbeat = 0; 1106166675Srrs asoc->timocookie = 0; 1107166675Srrs asoc->timoshutdownack = 0; 1108169378Srrs (void)SCTP_GETTIME_TIMEVAL(&asoc->start_time); 1109169378Srrs asoc->discontinuity_time = asoc->start_time; 1110170931Srrs /* 1111170931Srrs * sa_ignore MEMLEAK {memory is put in the assoc mapping array and 1112205627Srrs * freed later when the association is freed. 1113170931Srrs */ 1114163953Srrs return (0); 1115163953Srrs} 1116163953Srrs 1117205502Srrsvoid 1118205502Srrssctp_print_mapping_array(struct sctp_association *asoc) 1119205502Srrs{ 1120206281Stuexen unsigned int i, limit; 1121205502Srrs 1122235164Stuexen SCTP_PRINTF("Mapping array size: %d, baseTSN: %8.8x, cumAck: %8.8x, highestTSN: (%8.8x, %8.8x).\n", 1123205502Srrs asoc->mapping_array_size, 1124205502Srrs asoc->mapping_array_base_tsn, 1125205502Srrs asoc->cumulative_tsn, 1126206281Stuexen asoc->highest_tsn_inside_map, 1127206281Stuexen asoc->highest_tsn_inside_nr_map); 1128206281Stuexen for (limit = asoc->mapping_array_size; limit > 1; limit--) { 1129231039Stuexen if (asoc->mapping_array[limit - 1] != 0) { 1130205627Srrs break; 1131205627Srrs } 1132205627Srrs } 1133235164Stuexen SCTP_PRINTF("Renegable mapping array (last %d entries are zero):\n", asoc->mapping_array_size - limit); 1134205627Srrs for (i = 0; i < limit; i++) { 1135235164Stuexen SCTP_PRINTF("%2.2x%c", asoc->mapping_array[i], ((i + 1) % 16) ? ' ' : '\n'); 1136205502Srrs } 1137206281Stuexen if (limit % 16) 1138235164Stuexen SCTP_PRINTF("\n"); 1139206281Stuexen for (limit = asoc->mapping_array_size; limit > 1; limit--) { 1140206281Stuexen if (asoc->nr_mapping_array[limit - 1]) { 1141205627Srrs break; 1142205627Srrs } 1143205627Srrs } 1144235164Stuexen SCTP_PRINTF("Non renegable mapping array (last %d entries are zero):\n", asoc->mapping_array_size - limit); 1145205627Srrs for (i = 0; i < limit; i++) { 1146235164Stuexen SCTP_PRINTF("%2.2x%c", asoc->nr_mapping_array[i], ((i + 1) % 16) ? ' ' : '\n'); 1147205627Srrs } 1148206281Stuexen if (limit % 16) 1149235164Stuexen SCTP_PRINTF("\n"); 1150205502Srrs} 1151205502Srrs 1152163953Srrsint 1153170138Srrssctp_expand_mapping_array(struct sctp_association *asoc, uint32_t needed) 1154163953Srrs{ 1155163953Srrs /* mapping array needs to grow */ 1156206137Stuexen uint8_t *new_array1, *new_array2; 1157170138Srrs uint32_t new_size; 1158163953Srrs 1159170138Srrs new_size = asoc->mapping_array_size + ((needed + 7) / 8 + SCTP_MAPPING_ARRAY_INCR); 1160206137Stuexen SCTP_MALLOC(new_array1, uint8_t *, new_size, SCTP_M_MAP); 1161206137Stuexen SCTP_MALLOC(new_array2, uint8_t *, new_size, SCTP_M_MAP); 1162206137Stuexen if ((new_array1 == NULL) || (new_array2 == NULL)) { 1163163953Srrs /* can't get more, forget it */ 1164206137Stuexen SCTP_PRINTF("No memory for expansion of SCTP mapping array %d\n", new_size); 1165206137Stuexen if (new_array1) { 1166206137Stuexen SCTP_FREE(new_array1, SCTP_M_MAP); 1167206137Stuexen } 1168206137Stuexen if (new_array2) { 1169206137Stuexen SCTP_FREE(new_array2, SCTP_M_MAP); 1170206137Stuexen } 1171163953Srrs return (-1); 1172163953Srrs } 1173206137Stuexen memset(new_array1, 0, new_size); 1174206137Stuexen memset(new_array2, 0, new_size); 1175206137Stuexen memcpy(new_array1, asoc->mapping_array, asoc->mapping_array_size); 1176206137Stuexen memcpy(new_array2, asoc->nr_mapping_array, asoc->mapping_array_size); 1177170091Srrs SCTP_FREE(asoc->mapping_array, SCTP_M_MAP); 1178206137Stuexen SCTP_FREE(asoc->nr_mapping_array, SCTP_M_MAP); 1179206137Stuexen asoc->mapping_array = new_array1; 1180206137Stuexen asoc->nr_mapping_array = new_array2; 1181163953Srrs asoc->mapping_array_size = new_size; 1182163953Srrs return (0); 1183163953Srrs} 1184163953Srrs 1185185694Srrs 1186167598Srrsstatic void 1187167598Srrssctp_iterator_work(struct sctp_iterator *it) 1188167598Srrs{ 1189167598Srrs int iteration_count = 0; 1190167598Srrs int inp_skip = 0; 1191209029Srrs int first_in = 1; 1192209029Srrs struct sctp_inpcb *tinp; 1193163953Srrs 1194209029Srrs SCTP_INP_INFO_RLOCK(); 1195167598Srrs SCTP_ITERATOR_LOCK(); 1196169420Srrs if (it->inp) { 1197209029Srrs SCTP_INP_RLOCK(it->inp); 1198167598Srrs SCTP_INP_DECR_REF(it->inp); 1199169420Srrs } 1200167598Srrs if (it->inp == NULL) { 1201167598Srrs /* iterator is complete */ 1202167598Srrsdone_with_iterator: 1203167598Srrs SCTP_ITERATOR_UNLOCK(); 1204209029Srrs SCTP_INP_INFO_RUNLOCK(); 1205167598Srrs if (it->function_atend != NULL) { 1206167598Srrs (*it->function_atend) (it->pointer, it->val); 1207167598Srrs } 1208170091Srrs SCTP_FREE(it, SCTP_M_ITER); 1209167598Srrs return; 1210167598Srrs } 1211167598Srrsselect_a_new_ep: 1212209029Srrs if (first_in) { 1213209029Srrs first_in = 0; 1214209029Srrs } else { 1215209029Srrs SCTP_INP_RLOCK(it->inp); 1216209029Srrs } 1217167598Srrs while (((it->pcb_flags) && 1218167598Srrs ((it->inp->sctp_flags & it->pcb_flags) != it->pcb_flags)) || 1219167598Srrs ((it->pcb_features) && 1220167598Srrs ((it->inp->sctp_features & it->pcb_features) != it->pcb_features))) { 1221167598Srrs /* endpoint flags or features don't match, so keep looking */ 1222167598Srrs if (it->iterator_flags & SCTP_ITERATOR_DO_SINGLE_INP) { 1223208160Srrs SCTP_INP_RUNLOCK(it->inp); 1224167598Srrs goto done_with_iterator; 1225167598Srrs } 1226209029Srrs tinp = it->inp; 1227167598Srrs it->inp = LIST_NEXT(it->inp, sctp_list); 1228209029Srrs SCTP_INP_RUNLOCK(tinp); 1229167598Srrs if (it->inp == NULL) { 1230167598Srrs goto done_with_iterator; 1231167598Srrs } 1232208160Srrs SCTP_INP_RLOCK(it->inp); 1233167598Srrs } 1234167598Srrs /* now go through each assoc which is in the desired state */ 1235167598Srrs if (it->done_current_ep == 0) { 1236167598Srrs if (it->function_inp != NULL) 1237167598Srrs inp_skip = (*it->function_inp) (it->inp, it->pointer, it->val); 1238167598Srrs it->done_current_ep = 1; 1239167598Srrs } 1240167598Srrs if (it->stcb == NULL) { 1241167598Srrs /* run the per instance function */ 1242167598Srrs it->stcb = LIST_FIRST(&it->inp->sctp_asoc_list); 1243167598Srrs } 1244167598Srrs if ((inp_skip) || it->stcb == NULL) { 1245167598Srrs if (it->function_inp_end != NULL) { 1246167598Srrs inp_skip = (*it->function_inp_end) (it->inp, 1247167598Srrs it->pointer, 1248167598Srrs it->val); 1249167598Srrs } 1250167598Srrs SCTP_INP_RUNLOCK(it->inp); 1251167598Srrs goto no_stcb; 1252167598Srrs } 1253167598Srrs while (it->stcb) { 1254167598Srrs SCTP_TCB_LOCK(it->stcb); 1255167598Srrs if (it->asoc_state && ((it->stcb->asoc.state & it->asoc_state) != it->asoc_state)) { 1256167598Srrs /* not in the right state... keep looking */ 1257167598Srrs SCTP_TCB_UNLOCK(it->stcb); 1258167598Srrs goto next_assoc; 1259167598Srrs } 1260167598Srrs /* see if we have limited out the iterator loop */ 1261167598Srrs iteration_count++; 1262167598Srrs if (iteration_count > SCTP_ITERATOR_MAX_AT_ONCE) { 1263167598Srrs /* Pause to let others grab the lock */ 1264167598Srrs atomic_add_int(&it->stcb->asoc.refcnt, 1); 1265167598Srrs SCTP_TCB_UNLOCK(it->stcb); 1266171943Srrs SCTP_INP_INCR_REF(it->inp); 1267167598Srrs SCTP_INP_RUNLOCK(it->inp); 1268167598Srrs SCTP_ITERATOR_UNLOCK(); 1269209029Srrs SCTP_INP_INFO_RUNLOCK(); 1270209029Srrs SCTP_INP_INFO_RLOCK(); 1271167598Srrs SCTP_ITERATOR_LOCK(); 1272208160Srrs if (sctp_it_ctl.iterator_flags) { 1273208160Srrs /* We won't be staying here */ 1274208160Srrs SCTP_INP_DECR_REF(it->inp); 1275208160Srrs atomic_add_int(&it->stcb->asoc.refcnt, -1); 1276208160Srrs if (sctp_it_ctl.iterator_flags & 1277208160Srrs SCTP_ITERATOR_STOP_CUR_IT) { 1278208160Srrs sctp_it_ctl.iterator_flags &= ~SCTP_ITERATOR_STOP_CUR_IT; 1279208160Srrs goto done_with_iterator; 1280208160Srrs } 1281208160Srrs if (sctp_it_ctl.iterator_flags & 1282208160Srrs SCTP_ITERATOR_STOP_CUR_INP) { 1283208160Srrs sctp_it_ctl.iterator_flags &= ~SCTP_ITERATOR_STOP_CUR_INP; 1284208160Srrs goto no_stcb; 1285208160Srrs } 1286208160Srrs /* If we reach here huh? */ 1287235164Stuexen SCTP_PRINTF("Unknown it ctl flag %x\n", 1288208160Srrs sctp_it_ctl.iterator_flags); 1289208160Srrs sctp_it_ctl.iterator_flags = 0; 1290208160Srrs } 1291167598Srrs SCTP_INP_RLOCK(it->inp); 1292171943Srrs SCTP_INP_DECR_REF(it->inp); 1293167598Srrs SCTP_TCB_LOCK(it->stcb); 1294167598Srrs atomic_add_int(&it->stcb->asoc.refcnt, -1); 1295167598Srrs iteration_count = 0; 1296167598Srrs } 1297167598Srrs /* run function on this one */ 1298167598Srrs (*it->function_assoc) (it->inp, it->stcb, it->pointer, it->val); 1299167598Srrs 1300167598Srrs /* 1301167598Srrs * we lie here, it really needs to have its own type but 1302167598Srrs * first I must verify that this won't effect things :-0 1303167598Srrs */ 1304167598Srrs if (it->no_chunk_output == 0) 1305172090Srrs sctp_chunk_output(it->inp, it->stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_NOT_LOCKED); 1306167598Srrs 1307167598Srrs SCTP_TCB_UNLOCK(it->stcb); 1308167598Srrsnext_assoc: 1309167598Srrs it->stcb = LIST_NEXT(it->stcb, sctp_tcblist); 1310167598Srrs if (it->stcb == NULL) { 1311167598Srrs /* Run last function */ 1312167598Srrs if (it->function_inp_end != NULL) { 1313167598Srrs inp_skip = (*it->function_inp_end) (it->inp, 1314167598Srrs it->pointer, 1315167598Srrs it->val); 1316167598Srrs } 1317167598Srrs } 1318167598Srrs } 1319167598Srrs SCTP_INP_RUNLOCK(it->inp); 1320167598Srrsno_stcb: 1321167598Srrs /* done with all assocs on this endpoint, move on to next endpoint */ 1322167598Srrs it->done_current_ep = 0; 1323167598Srrs if (it->iterator_flags & SCTP_ITERATOR_DO_SINGLE_INP) { 1324167598Srrs it->inp = NULL; 1325167598Srrs } else { 1326167598Srrs it->inp = LIST_NEXT(it->inp, sctp_list); 1327167598Srrs } 1328167598Srrs if (it->inp == NULL) { 1329167598Srrs goto done_with_iterator; 1330167598Srrs } 1331167598Srrs goto select_a_new_ep; 1332167598Srrs} 1333167598Srrs 1334167598Srrsvoid 1335167598Srrssctp_iterator_worker(void) 1336167598Srrs{ 1337216822Stuexen struct sctp_iterator *it, *nit; 1338167598Srrs 1339167598Srrs /* This function is called with the WQ lock in place */ 1340167598Srrs 1341208160Srrs sctp_it_ctl.iterator_running = 1; 1342216822Stuexen TAILQ_FOREACH_SAFE(it, &sctp_it_ctl.iteratorhead, sctp_nxt_itr, nit) { 1343216822Stuexen sctp_it_ctl.cur_it = it; 1344167598Srrs /* now lets work on this one */ 1345208160Srrs TAILQ_REMOVE(&sctp_it_ctl.iteratorhead, it, sctp_nxt_itr); 1346167598Srrs SCTP_IPI_ITERATOR_WQ_UNLOCK(); 1347208160Srrs CURVNET_SET(it->vn); 1348167598Srrs sctp_iterator_work(it); 1349219397Srrs sctp_it_ctl.cur_it = NULL; 1350208160Srrs CURVNET_RESTORE(); 1351167598Srrs SCTP_IPI_ITERATOR_WQ_LOCK(); 1352169655Srrs /* sa_ignore FREED_MEMORY */ 1353167598Srrs } 1354208160Srrs sctp_it_ctl.iterator_running = 0; 1355167598Srrs return; 1356167598Srrs} 1357167598Srrs 1358167598Srrs 1359163953Srrsstatic void 1360163953Srrssctp_handle_addr_wq(void) 1361163953Srrs{ 1362163953Srrs /* deal with the ADDR wq from the rtsock calls */ 1363216822Stuexen struct sctp_laddr *wi, *nwi; 1364167598Srrs struct sctp_asconf_iterator *asc; 1365163953Srrs 1366167598Srrs SCTP_MALLOC(asc, struct sctp_asconf_iterator *, 1367170091Srrs sizeof(struct sctp_asconf_iterator), SCTP_M_ASC_IT); 1368167598Srrs if (asc == NULL) { 1369167598Srrs /* Try later, no memory */ 1370163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_ADDR_WQ, 1371163953Srrs (struct sctp_inpcb *)NULL, 1372163953Srrs (struct sctp_tcb *)NULL, 1373163953Srrs (struct sctp_nets *)NULL); 1374167598Srrs return; 1375163953Srrs } 1376167598Srrs LIST_INIT(&asc->list_of_work); 1377167598Srrs asc->cnt = 0; 1378208160Srrs 1379208160Srrs SCTP_WQ_ADDR_LOCK(); 1380216822Stuexen LIST_FOREACH_SAFE(wi, &SCTP_BASE_INFO(addr_wq), sctp_nxt_addr, nwi) { 1381167598Srrs LIST_REMOVE(wi, sctp_nxt_addr); 1382167598Srrs LIST_INSERT_HEAD(&asc->list_of_work, wi, sctp_nxt_addr); 1383167598Srrs asc->cnt++; 1384163953Srrs } 1385208160Srrs SCTP_WQ_ADDR_UNLOCK(); 1386208160Srrs 1387167598Srrs if (asc->cnt == 0) { 1388170091Srrs SCTP_FREE(asc, SCTP_M_ASC_IT); 1389167598Srrs } else { 1390171572Srrs (void)sctp_initiate_iterator(sctp_asconf_iterator_ep, 1391171572Srrs sctp_asconf_iterator_stcb, 1392167598Srrs NULL, /* No ep end for boundall */ 1393167598Srrs SCTP_PCB_FLAGS_BOUNDALL, 1394167598Srrs SCTP_PCB_ANY_FEATURES, 1395171572Srrs SCTP_ASOC_ANY_STATE, 1396171572Srrs (void *)asc, 0, 1397171572Srrs sctp_asconf_iterator_end, NULL, 0); 1398167598Srrs } 1399163953Srrs} 1400163953Srrs 1401163953Srrsvoid 1402163953Srrssctp_timeout_handler(void *t) 1403163953Srrs{ 1404163953Srrs struct sctp_inpcb *inp; 1405163953Srrs struct sctp_tcb *stcb; 1406163953Srrs struct sctp_nets *net; 1407163953Srrs struct sctp_timer *tmr; 1408172090Srrs 1409252882Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1410172090Srrs struct socket *so; 1411172090Srrs 1412172090Srrs#endif 1413179180Srrs int did_output, type; 1414163953Srrs 1415163953Srrs tmr = (struct sctp_timer *)t; 1416163953Srrs inp = (struct sctp_inpcb *)tmr->ep; 1417163953Srrs stcb = (struct sctp_tcb *)tmr->tcb; 1418163953Srrs net = (struct sctp_nets *)tmr->net; 1419197326Stuexen CURVNET_SET((struct vnet *)tmr->vnet); 1420163953Srrs did_output = 1; 1421163953Srrs 1422163953Srrs#ifdef SCTP_AUDITING_ENABLED 1423163953Srrs sctp_audit_log(0xF0, (uint8_t) tmr->type); 1424163953Srrs sctp_auditing(3, inp, stcb, net); 1425163953Srrs#endif 1426163953Srrs 1427163953Srrs /* sanity checks... */ 1428163953Srrs if (tmr->self != (void *)tmr) { 1429163953Srrs /* 1430169420Srrs * SCTP_PRINTF("Stale SCTP timer fired (%p), ignoring...\n", 1431252927Stuexen * (void *)tmr); 1432163953Srrs */ 1433197326Stuexen CURVNET_RESTORE(); 1434163953Srrs return; 1435163953Srrs } 1436165220Srrs tmr->stopped_from = 0xa001; 1437163953Srrs if (!SCTP_IS_TIMER_TYPE_VALID(tmr->type)) { 1438163953Srrs /* 1439169420Srrs * SCTP_PRINTF("SCTP timer fired with invalid type: 0x%x\n", 1440163953Srrs * tmr->type); 1441163953Srrs */ 1442197326Stuexen CURVNET_RESTORE(); 1443163953Srrs return; 1444163953Srrs } 1445165220Srrs tmr->stopped_from = 0xa002; 1446163953Srrs if ((tmr->type != SCTP_TIMER_TYPE_ADDR_WQ) && (inp == NULL)) { 1447197326Stuexen CURVNET_RESTORE(); 1448163953Srrs return; 1449163953Srrs } 1450163953Srrs /* if this is an iterator timeout, get the struct and clear inp */ 1451165220Srrs tmr->stopped_from = 0xa003; 1452179180Srrs type = tmr->type; 1453163953Srrs if (inp) { 1454163953Srrs SCTP_INP_INCR_REF(inp); 1455231040Stuexen if ((inp->sctp_socket == NULL) && 1456163953Srrs ((tmr->type != SCTP_TIMER_TYPE_INPKILL) && 1457196260Stuexen (tmr->type != SCTP_TIMER_TYPE_INIT) && 1458184883Srrs (tmr->type != SCTP_TIMER_TYPE_SEND) && 1459184883Srrs (tmr->type != SCTP_TIMER_TYPE_RECV) && 1460184883Srrs (tmr->type != SCTP_TIMER_TYPE_HEARTBEAT) && 1461163953Srrs (tmr->type != SCTP_TIMER_TYPE_SHUTDOWN) && 1462163953Srrs (tmr->type != SCTP_TIMER_TYPE_SHUTDOWNACK) && 1463163953Srrs (tmr->type != SCTP_TIMER_TYPE_SHUTDOWNGUARD) && 1464163953Srrs (tmr->type != SCTP_TIMER_TYPE_ASOCKILL)) 1465163953Srrs ) { 1466163953Srrs SCTP_INP_DECR_REF(inp); 1467197326Stuexen CURVNET_RESTORE(); 1468163953Srrs return; 1469163953Srrs } 1470163953Srrs } 1471165220Srrs tmr->stopped_from = 0xa004; 1472163953Srrs if (stcb) { 1473168709Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 1474163953Srrs if (stcb->asoc.state == 0) { 1475168709Srrs atomic_add_int(&stcb->asoc.refcnt, -1); 1476163953Srrs if (inp) { 1477163953Srrs SCTP_INP_DECR_REF(inp); 1478163953Srrs } 1479197326Stuexen CURVNET_RESTORE(); 1480163953Srrs return; 1481163953Srrs } 1482163953Srrs } 1483165220Srrs tmr->stopped_from = 0xa005; 1484169420Srrs SCTPDBG(SCTP_DEBUG_TIMER1, "Timer type %d goes off\n", tmr->type); 1485165647Srrs if (!SCTP_OS_TIMER_ACTIVE(&tmr->timer)) { 1486163953Srrs if (inp) { 1487163953Srrs SCTP_INP_DECR_REF(inp); 1488163953Srrs } 1489170091Srrs if (stcb) { 1490170091Srrs atomic_add_int(&stcb->asoc.refcnt, -1); 1491170091Srrs } 1492197326Stuexen CURVNET_RESTORE(); 1493163953Srrs return; 1494163953Srrs } 1495165220Srrs tmr->stopped_from = 0xa006; 1496165220Srrs 1497163953Srrs if (stcb) { 1498163953Srrs SCTP_TCB_LOCK(stcb); 1499163996Srrs atomic_add_int(&stcb->asoc.refcnt, -1); 1500171440Srrs if ((tmr->type != SCTP_TIMER_TYPE_ASOCKILL) && 1501171440Srrs ((stcb->asoc.state == 0) || 1502171440Srrs (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED))) { 1503171440Srrs SCTP_TCB_UNLOCK(stcb); 1504171440Srrs if (inp) { 1505171440Srrs SCTP_INP_DECR_REF(inp); 1506171440Srrs } 1507197326Stuexen CURVNET_RESTORE(); 1508171440Srrs return; 1509171440Srrs } 1510163953Srrs } 1511166023Srrs /* record in stopped what t-o occured */ 1512166023Srrs tmr->stopped_from = tmr->type; 1513166023Srrs 1514163953Srrs /* mark as being serviced now */ 1515166023Srrs if (SCTP_OS_TIMER_PENDING(&tmr->timer)) { 1516166023Srrs /* 1517166023Srrs * Callout has been rescheduled. 1518166023Srrs */ 1519166023Srrs goto get_out; 1520166023Srrs } 1521166023Srrs if (!SCTP_OS_TIMER_ACTIVE(&tmr->timer)) { 1522166023Srrs /* 1523166023Srrs * Not active, so no action. 1524166023Srrs */ 1525166023Srrs goto get_out; 1526166023Srrs } 1527165647Srrs SCTP_OS_TIMER_DEACTIVATE(&tmr->timer); 1528163953Srrs 1529163953Srrs /* call the handler for the appropriate timer type */ 1530163953Srrs switch (tmr->type) { 1531170056Srrs case SCTP_TIMER_TYPE_ZERO_COPY: 1532170931Srrs if (inp == NULL) { 1533170931Srrs break; 1534170931Srrs } 1535170056Srrs if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_ZERO_COPY_ACTIVE)) { 1536170056Srrs SCTP_ZERO_COPY_EVENT(inp, inp->sctp_socket); 1537170056Srrs } 1538170056Srrs break; 1539170181Srrs case SCTP_TIMER_TYPE_ZCOPY_SENDQ: 1540170931Srrs if (inp == NULL) { 1541170931Srrs break; 1542170931Srrs } 1543170181Srrs if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_ZERO_COPY_ACTIVE)) { 1544170181Srrs SCTP_ZERO_COPY_SENDQ_EVENT(inp, inp->sctp_socket); 1545170181Srrs } 1546170181Srrs break; 1547163953Srrs case SCTP_TIMER_TYPE_ADDR_WQ: 1548163953Srrs sctp_handle_addr_wq(); 1549163953Srrs break; 1550163953Srrs case SCTP_TIMER_TYPE_SEND: 1551169420Srrs if ((stcb == NULL) || (inp == NULL)) { 1552169420Srrs break; 1553169420Srrs } 1554163953Srrs SCTP_STAT_INCR(sctps_timodata); 1555166675Srrs stcb->asoc.timodata++; 1556163953Srrs stcb->asoc.num_send_timers_up--; 1557163953Srrs if (stcb->asoc.num_send_timers_up < 0) { 1558163953Srrs stcb->asoc.num_send_timers_up = 0; 1559163953Srrs } 1560171440Srrs SCTP_TCB_LOCK_ASSERT(stcb); 1561231039Stuexen if (sctp_t3rxt_timer(inp, stcb, net)) { 1562163953Srrs /* no need to unlock on tcb its gone */ 1563163953Srrs 1564163953Srrs goto out_decr; 1565163953Srrs } 1566171440Srrs SCTP_TCB_LOCK_ASSERT(stcb); 1567163953Srrs#ifdef SCTP_AUDITING_ENABLED 1568163953Srrs sctp_auditing(4, inp, stcb, net); 1569163953Srrs#endif 1570172090Srrs sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_NOT_LOCKED); 1571163953Srrs if ((stcb->asoc.num_send_timers_up == 0) && 1572216822Stuexen (stcb->asoc.sent_queue_cnt > 0)) { 1573163953Srrs struct sctp_tmit_chunk *chk; 1574163953Srrs 1575163953Srrs /* 1576163953Srrs * safeguard. If there on some on the sent queue 1577163953Srrs * somewhere but no timers running something is 1578163953Srrs * wrong... so we start a timer on the first chunk 1579163953Srrs * on the send queue on whatever net it is sent to. 1580163953Srrs */ 1581163953Srrs chk = TAILQ_FIRST(&stcb->asoc.sent_queue); 1582163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_SEND, inp, stcb, 1583163953Srrs chk->whoTo); 1584163953Srrs } 1585163953Srrs break; 1586163953Srrs case SCTP_TIMER_TYPE_INIT: 1587169420Srrs if ((stcb == NULL) || (inp == NULL)) { 1588169420Srrs break; 1589169420Srrs } 1590163953Srrs SCTP_STAT_INCR(sctps_timoinit); 1591166675Srrs stcb->asoc.timoinit++; 1592163953Srrs if (sctp_t1init_timer(inp, stcb, net)) { 1593163953Srrs /* no need to unlock on tcb its gone */ 1594163953Srrs goto out_decr; 1595163953Srrs } 1596163953Srrs /* We do output but not here */ 1597163953Srrs did_output = 0; 1598163953Srrs break; 1599163953Srrs case SCTP_TIMER_TYPE_RECV: 1600169420Srrs if ((stcb == NULL) || (inp == NULL)) { 1601169420Srrs break; 1602169420Srrs } 1603224641Stuexen SCTP_STAT_INCR(sctps_timosack); 1604224641Stuexen stcb->asoc.timosack++; 1605224641Stuexen sctp_send_sack(stcb, SCTP_SO_NOT_LOCKED); 1606163953Srrs#ifdef SCTP_AUDITING_ENABLED 1607163953Srrs sctp_auditing(4, inp, stcb, net); 1608163953Srrs#endif 1609172090Srrs sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_SACK_TMR, SCTP_SO_NOT_LOCKED); 1610163953Srrs break; 1611163953Srrs case SCTP_TIMER_TYPE_SHUTDOWN: 1612169420Srrs if ((stcb == NULL) || (inp == NULL)) { 1613169420Srrs break; 1614169420Srrs } 1615163953Srrs if (sctp_shutdown_timer(inp, stcb, net)) { 1616163953Srrs /* no need to unlock on tcb its gone */ 1617163953Srrs goto out_decr; 1618163953Srrs } 1619163953Srrs SCTP_STAT_INCR(sctps_timoshutdown); 1620166675Srrs stcb->asoc.timoshutdown++; 1621163953Srrs#ifdef SCTP_AUDITING_ENABLED 1622163953Srrs sctp_auditing(4, inp, stcb, net); 1623163953Srrs#endif 1624172090Srrs sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_SHUT_TMR, SCTP_SO_NOT_LOCKED); 1625163953Srrs break; 1626163953Srrs case SCTP_TIMER_TYPE_HEARTBEAT: 1627224641Stuexen if ((stcb == NULL) || (inp == NULL) || (net == NULL)) { 1628224641Stuexen break; 1629224641Stuexen } 1630224641Stuexen SCTP_STAT_INCR(sctps_timoheartbeat); 1631224641Stuexen stcb->asoc.timoheartbeat++; 1632224641Stuexen if (sctp_heartbeat_timer(inp, stcb, net)) { 1633224641Stuexen /* no need to unlock on tcb its gone */ 1634224641Stuexen goto out_decr; 1635224641Stuexen } 1636163953Srrs#ifdef SCTP_AUDITING_ENABLED 1637224641Stuexen sctp_auditing(4, inp, stcb, net); 1638163953Srrs#endif 1639224641Stuexen if (!(net->dest_state & SCTP_ADDR_NOHB)) { 1640226267Stuexen sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net); 1641172090Srrs sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_HB_TMR, SCTP_SO_NOT_LOCKED); 1642163953Srrs } 1643163953Srrs break; 1644163953Srrs case SCTP_TIMER_TYPE_COOKIE: 1645169420Srrs if ((stcb == NULL) || (inp == NULL)) { 1646169420Srrs break; 1647169420Srrs } 1648163953Srrs if (sctp_cookie_timer(inp, stcb, net)) { 1649163953Srrs /* no need to unlock on tcb its gone */ 1650163953Srrs goto out_decr; 1651163953Srrs } 1652163953Srrs SCTP_STAT_INCR(sctps_timocookie); 1653166675Srrs stcb->asoc.timocookie++; 1654163953Srrs#ifdef SCTP_AUDITING_ENABLED 1655163953Srrs sctp_auditing(4, inp, stcb, net); 1656163953Srrs#endif 1657163953Srrs /* 1658163953Srrs * We consider T3 and Cookie timer pretty much the same with 1659163953Srrs * respect to where from in chunk_output. 1660163953Srrs */ 1661172090Srrs sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_NOT_LOCKED); 1662163953Srrs break; 1663163953Srrs case SCTP_TIMER_TYPE_NEWCOOKIE: 1664163953Srrs { 1665163953Srrs struct timeval tv; 1666163953Srrs int i, secret; 1667163953Srrs 1668169420Srrs if (inp == NULL) { 1669169420Srrs break; 1670169420Srrs } 1671163953Srrs SCTP_STAT_INCR(sctps_timosecret); 1672169378Srrs (void)SCTP_GETTIME_TIMEVAL(&tv); 1673163953Srrs SCTP_INP_WLOCK(inp); 1674163953Srrs inp->sctp_ep.time_of_secret_change = tv.tv_sec; 1675163953Srrs inp->sctp_ep.last_secret_number = 1676163953Srrs inp->sctp_ep.current_secret_number; 1677163953Srrs inp->sctp_ep.current_secret_number++; 1678163953Srrs if (inp->sctp_ep.current_secret_number >= 1679163953Srrs SCTP_HOW_MANY_SECRETS) { 1680163953Srrs inp->sctp_ep.current_secret_number = 0; 1681163953Srrs } 1682163953Srrs secret = (int)inp->sctp_ep.current_secret_number; 1683163953Srrs for (i = 0; i < SCTP_NUMBER_OF_SECRETS; i++) { 1684163953Srrs inp->sctp_ep.secret_key[secret][i] = 1685163953Srrs sctp_select_initial_TSN(&inp->sctp_ep); 1686163953Srrs } 1687163953Srrs SCTP_INP_WUNLOCK(inp); 1688163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_NEWCOOKIE, inp, stcb, net); 1689163953Srrs } 1690163953Srrs did_output = 0; 1691163953Srrs break; 1692163953Srrs case SCTP_TIMER_TYPE_PATHMTURAISE: 1693169420Srrs if ((stcb == NULL) || (inp == NULL)) { 1694169420Srrs break; 1695169420Srrs } 1696163953Srrs SCTP_STAT_INCR(sctps_timopathmtu); 1697163953Srrs sctp_pathmtu_timer(inp, stcb, net); 1698163953Srrs did_output = 0; 1699163953Srrs break; 1700163953Srrs case SCTP_TIMER_TYPE_SHUTDOWNACK: 1701169420Srrs if ((stcb == NULL) || (inp == NULL)) { 1702169420Srrs break; 1703169420Srrs } 1704163953Srrs if (sctp_shutdownack_timer(inp, stcb, net)) { 1705163953Srrs /* no need to unlock on tcb its gone */ 1706163953Srrs goto out_decr; 1707163953Srrs } 1708163953Srrs SCTP_STAT_INCR(sctps_timoshutdownack); 1709166675Srrs stcb->asoc.timoshutdownack++; 1710163953Srrs#ifdef SCTP_AUDITING_ENABLED 1711163953Srrs sctp_auditing(4, inp, stcb, net); 1712163953Srrs#endif 1713172090Srrs sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_SHUT_ACK_TMR, SCTP_SO_NOT_LOCKED); 1714163953Srrs break; 1715163953Srrs case SCTP_TIMER_TYPE_SHUTDOWNGUARD: 1716169420Srrs if ((stcb == NULL) || (inp == NULL)) { 1717169420Srrs break; 1718169420Srrs } 1719163953Srrs SCTP_STAT_INCR(sctps_timoshutdownguard); 1720237884Stuexen sctp_abort_an_association(inp, stcb, NULL, SCTP_SO_NOT_LOCKED); 1721163953Srrs /* no need to unlock on tcb its gone */ 1722163953Srrs goto out_decr; 1723163953Srrs 1724163953Srrs case SCTP_TIMER_TYPE_STRRESET: 1725169420Srrs if ((stcb == NULL) || (inp == NULL)) { 1726169420Srrs break; 1727169420Srrs } 1728163953Srrs if (sctp_strreset_timer(inp, stcb, net)) { 1729163953Srrs /* no need to unlock on tcb its gone */ 1730163953Srrs goto out_decr; 1731163953Srrs } 1732163953Srrs SCTP_STAT_INCR(sctps_timostrmrst); 1733172090Srrs sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_TMR, SCTP_SO_NOT_LOCKED); 1734163953Srrs break; 1735163953Srrs case SCTP_TIMER_TYPE_ASCONF: 1736169420Srrs if ((stcb == NULL) || (inp == NULL)) { 1737169420Srrs break; 1738169420Srrs } 1739163953Srrs if (sctp_asconf_timer(inp, stcb, net)) { 1740163953Srrs /* no need to unlock on tcb its gone */ 1741163953Srrs goto out_decr; 1742163953Srrs } 1743163953Srrs SCTP_STAT_INCR(sctps_timoasconf); 1744163953Srrs#ifdef SCTP_AUDITING_ENABLED 1745163953Srrs sctp_auditing(4, inp, stcb, net); 1746163953Srrs#endif 1747172090Srrs sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_ASCONF_TMR, SCTP_SO_NOT_LOCKED); 1748163953Srrs break; 1749172091Srrs case SCTP_TIMER_TYPE_PRIM_DELETED: 1750172091Srrs if ((stcb == NULL) || (inp == NULL)) { 1751172091Srrs break; 1752172091Srrs } 1753172156Srrs sctp_delete_prim_timer(inp, stcb, net); 1754172091Srrs SCTP_STAT_INCR(sctps_timodelprim); 1755172091Srrs break; 1756163953Srrs 1757163953Srrs case SCTP_TIMER_TYPE_AUTOCLOSE: 1758169420Srrs if ((stcb == NULL) || (inp == NULL)) { 1759169420Srrs break; 1760169420Srrs } 1761163953Srrs SCTP_STAT_INCR(sctps_timoautoclose); 1762163953Srrs sctp_autoclose_timer(inp, stcb, net); 1763172090Srrs sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_AUTOCLOSE_TMR, SCTP_SO_NOT_LOCKED); 1764163953Srrs did_output = 0; 1765163953Srrs break; 1766163953Srrs case SCTP_TIMER_TYPE_ASOCKILL: 1767169420Srrs if ((stcb == NULL) || (inp == NULL)) { 1768169420Srrs break; 1769169420Srrs } 1770163953Srrs SCTP_STAT_INCR(sctps_timoassockill); 1771163953Srrs /* Can we free it yet? */ 1772163953Srrs SCTP_INP_DECR_REF(inp); 1773165220Srrs sctp_timer_stop(SCTP_TIMER_TYPE_ASOCKILL, inp, stcb, NULL, SCTP_FROM_SCTPUTIL + SCTP_LOC_1); 1774252882Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1775172090Srrs so = SCTP_INP_SO(inp); 1776172090Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 1777172090Srrs SCTP_TCB_UNLOCK(stcb); 1778172090Srrs SCTP_SOCKET_LOCK(so, 1); 1779172090Srrs SCTP_TCB_LOCK(stcb); 1780172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 1781172090Srrs#endif 1782171943Srrs (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTPUTIL + SCTP_LOC_2); 1783252882Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1784172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 1785172090Srrs#endif 1786163953Srrs /* 1787163953Srrs * free asoc, always unlocks (or destroy's) so prevent 1788163953Srrs * duplicate unlock or unlock of a free mtx :-0 1789163953Srrs */ 1790163953Srrs stcb = NULL; 1791163953Srrs goto out_no_decr; 1792163953Srrs case SCTP_TIMER_TYPE_INPKILL: 1793163953Srrs SCTP_STAT_INCR(sctps_timoinpkill); 1794169420Srrs if (inp == NULL) { 1795169420Srrs break; 1796169420Srrs } 1797163953Srrs /* 1798163953Srrs * special case, take away our increment since WE are the 1799163953Srrs * killer 1800163953Srrs */ 1801163953Srrs SCTP_INP_DECR_REF(inp); 1802165220Srrs sctp_timer_stop(SCTP_TIMER_TYPE_INPKILL, inp, NULL, NULL, SCTP_FROM_SCTPUTIL + SCTP_LOC_3); 1803169380Srrs sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT, 1804208878Srrs SCTP_CALLED_FROM_INPKILL_TIMER); 1805179180Srrs inp = NULL; 1806163953Srrs goto out_no_decr; 1807163953Srrs default: 1808169420Srrs SCTPDBG(SCTP_DEBUG_TIMER1, "sctp_timeout_handler:unknown timer %d\n", 1809169420Srrs tmr->type); 1810163953Srrs break; 1811231039Stuexen } 1812163953Srrs#ifdef SCTP_AUDITING_ENABLED 1813163953Srrs sctp_audit_log(0xF1, (uint8_t) tmr->type); 1814163953Srrs if (inp) 1815163953Srrs sctp_auditing(5, inp, stcb, net); 1816163953Srrs#endif 1817163953Srrs if ((did_output) && stcb) { 1818163953Srrs /* 1819163953Srrs * Now we need to clean up the control chunk chain if an 1820163953Srrs * ECNE is on it. It must be marked as UNSENT again so next 1821163953Srrs * call will continue to send it until such time that we get 1822163953Srrs * a CWR, to remove it. It is, however, less likely that we 1823163953Srrs * will find a ecn echo on the chain though. 1824163953Srrs */ 1825163953Srrs sctp_fix_ecn_echo(&stcb->asoc); 1826163953Srrs } 1827166023Srrsget_out: 1828163953Srrs if (stcb) { 1829163953Srrs SCTP_TCB_UNLOCK(stcb); 1830163953Srrs } 1831163953Srrsout_decr: 1832163953Srrs if (inp) { 1833163953Srrs SCTP_INP_DECR_REF(inp); 1834163953Srrs } 1835163953Srrsout_no_decr: 1836169420Srrs SCTPDBG(SCTP_DEBUG_TIMER1, "Timer now complete (type %d)\n", 1837179180Srrs type); 1838197326Stuexen CURVNET_RESTORE(); 1839163953Srrs} 1840163953Srrs 1841169420Srrsvoid 1842163953Srrssctp_timer_start(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb, 1843163953Srrs struct sctp_nets *net) 1844163953Srrs{ 1845224641Stuexen uint32_t to_ticks; 1846163953Srrs struct sctp_timer *tmr; 1847163953Srrs 1848165647Srrs if ((t_type != SCTP_TIMER_TYPE_ADDR_WQ) && (inp == NULL)) 1849169420Srrs return; 1850163953Srrs 1851163953Srrs tmr = NULL; 1852163953Srrs if (stcb) { 1853163953Srrs SCTP_TCB_LOCK_ASSERT(stcb); 1854163953Srrs } 1855163953Srrs switch (t_type) { 1856170056Srrs case SCTP_TIMER_TYPE_ZERO_COPY: 1857170056Srrs tmr = &inp->sctp_ep.zero_copy_timer; 1858170056Srrs to_ticks = SCTP_ZERO_COPY_TICK_DELAY; 1859170056Srrs break; 1860170181Srrs case SCTP_TIMER_TYPE_ZCOPY_SENDQ: 1861170181Srrs tmr = &inp->sctp_ep.zero_copy_sendq_timer; 1862170181Srrs to_ticks = SCTP_ZERO_COPY_SENDQ_TICK_DELAY; 1863170181Srrs break; 1864163953Srrs case SCTP_TIMER_TYPE_ADDR_WQ: 1865163953Srrs /* Only 1 tick away :-) */ 1866179783Srrs tmr = &SCTP_BASE_INFO(addr_wq_timer); 1867167598Srrs to_ticks = SCTP_ADDRESS_TICK_DELAY; 1868163953Srrs break; 1869163953Srrs case SCTP_TIMER_TYPE_SEND: 1870163953Srrs /* Here we use the RTO timer */ 1871163953Srrs { 1872163953Srrs int rto_val; 1873163953Srrs 1874163953Srrs if ((stcb == NULL) || (net == NULL)) { 1875169420Srrs return; 1876163953Srrs } 1877163953Srrs tmr = &net->rxt_timer; 1878163953Srrs if (net->RTO == 0) { 1879163953Srrs rto_val = stcb->asoc.initial_rto; 1880163953Srrs } else { 1881163953Srrs rto_val = net->RTO; 1882163953Srrs } 1883163953Srrs to_ticks = MSEC_TO_TICKS(rto_val); 1884163953Srrs } 1885163953Srrs break; 1886163953Srrs case SCTP_TIMER_TYPE_INIT: 1887163953Srrs /* 1888163953Srrs * Here we use the INIT timer default usually about 1 1889163953Srrs * minute. 1890163953Srrs */ 1891163953Srrs if ((stcb == NULL) || (net == NULL)) { 1892169420Srrs return; 1893163953Srrs } 1894163953Srrs tmr = &net->rxt_timer; 1895163953Srrs if (net->RTO == 0) { 1896163953Srrs to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto); 1897163953Srrs } else { 1898163953Srrs to_ticks = MSEC_TO_TICKS(net->RTO); 1899163953Srrs } 1900163953Srrs break; 1901163953Srrs case SCTP_TIMER_TYPE_RECV: 1902163953Srrs /* 1903163953Srrs * Here we use the Delayed-Ack timer value from the inp 1904163953Srrs * ususually about 200ms. 1905163953Srrs */ 1906163953Srrs if (stcb == NULL) { 1907169420Srrs return; 1908163953Srrs } 1909163953Srrs tmr = &stcb->asoc.dack_timer; 1910163953Srrs to_ticks = MSEC_TO_TICKS(stcb->asoc.delayed_ack); 1911163953Srrs break; 1912163953Srrs case SCTP_TIMER_TYPE_SHUTDOWN: 1913163953Srrs /* Here we use the RTO of the destination. */ 1914163953Srrs if ((stcb == NULL) || (net == NULL)) { 1915169420Srrs return; 1916163953Srrs } 1917163953Srrs if (net->RTO == 0) { 1918163953Srrs to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto); 1919163953Srrs } else { 1920163953Srrs to_ticks = MSEC_TO_TICKS(net->RTO); 1921163953Srrs } 1922163953Srrs tmr = &net->rxt_timer; 1923163953Srrs break; 1924163953Srrs case SCTP_TIMER_TYPE_HEARTBEAT: 1925163953Srrs /* 1926163953Srrs * the net is used here so that we can add in the RTO. Even 1927163953Srrs * though we use a different timer. We also add the HB timer 1928163953Srrs * PLUS a random jitter. 1929163953Srrs */ 1930224641Stuexen if ((inp == NULL) || (stcb == NULL) || (net == NULL)) { 1931169420Srrs return; 1932169420Srrs } else { 1933163953Srrs uint32_t rndval; 1934224641Stuexen uint32_t jitter; 1935163953Srrs 1936224641Stuexen if ((net->dest_state & SCTP_ADDR_NOHB) && 1937224641Stuexen !(net->dest_state & SCTP_ADDR_UNCONFIRMED)) { 1938224641Stuexen return; 1939163953Srrs } 1940224641Stuexen if (net->RTO == 0) { 1941224641Stuexen to_ticks = stcb->asoc.initial_rto; 1942224641Stuexen } else { 1943224641Stuexen to_ticks = net->RTO; 1944163953Srrs } 1945224641Stuexen rndval = sctp_select_initial_TSN(&inp->sctp_ep); 1946224641Stuexen jitter = rndval % to_ticks; 1947224641Stuexen if (jitter >= (to_ticks >> 1)) { 1948224641Stuexen to_ticks = to_ticks + (jitter - (to_ticks >> 1)); 1949224641Stuexen } else { 1950224641Stuexen to_ticks = to_ticks - jitter; 1951163953Srrs } 1952224641Stuexen if (!(net->dest_state & SCTP_ADDR_UNCONFIRMED) && 1953224641Stuexen !(net->dest_state & SCTP_ADDR_PF)) { 1954224641Stuexen to_ticks += net->heart_beat_delay; 1955163953Srrs } 1956163953Srrs /* 1957163953Srrs * Now we must convert the to_ticks that are now in 1958163953Srrs * ms to ticks. 1959163953Srrs */ 1960163953Srrs to_ticks = MSEC_TO_TICKS(to_ticks); 1961224641Stuexen tmr = &net->hb_timer; 1962163953Srrs } 1963163953Srrs break; 1964163953Srrs case SCTP_TIMER_TYPE_COOKIE: 1965163953Srrs /* 1966163953Srrs * Here we can use the RTO timer from the network since one 1967163953Srrs * RTT was compelete. If a retran happened then we will be 1968163953Srrs * using the RTO initial value. 1969163953Srrs */ 1970163953Srrs if ((stcb == NULL) || (net == NULL)) { 1971169420Srrs return; 1972163953Srrs } 1973163953Srrs if (net->RTO == 0) { 1974163953Srrs to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto); 1975163953Srrs } else { 1976163953Srrs to_ticks = MSEC_TO_TICKS(net->RTO); 1977163953Srrs } 1978163953Srrs tmr = &net->rxt_timer; 1979163953Srrs break; 1980163953Srrs case SCTP_TIMER_TYPE_NEWCOOKIE: 1981163953Srrs /* 1982163953Srrs * nothing needed but the endpoint here ususually about 60 1983163953Srrs * minutes. 1984163953Srrs */ 1985169420Srrs if (inp == NULL) { 1986169420Srrs return; 1987169420Srrs } 1988163953Srrs tmr = &inp->sctp_ep.signature_change; 1989163953Srrs to_ticks = inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_SIGNATURE]; 1990163953Srrs break; 1991163953Srrs case SCTP_TIMER_TYPE_ASOCKILL: 1992163953Srrs if (stcb == NULL) { 1993169420Srrs return; 1994163953Srrs } 1995163953Srrs tmr = &stcb->asoc.strreset_timer; 1996163953Srrs to_ticks = MSEC_TO_TICKS(SCTP_ASOC_KILL_TIMEOUT); 1997163953Srrs break; 1998163953Srrs case SCTP_TIMER_TYPE_INPKILL: 1999163953Srrs /* 2000163953Srrs * The inp is setup to die. We re-use the signature_chage 2001163953Srrs * timer since that has stopped and we are in the GONE 2002163953Srrs * state. 2003163953Srrs */ 2004169420Srrs if (inp == NULL) { 2005169420Srrs return; 2006169420Srrs } 2007163953Srrs tmr = &inp->sctp_ep.signature_change; 2008163953Srrs to_ticks = MSEC_TO_TICKS(SCTP_INP_KILL_TIMEOUT); 2009163953Srrs break; 2010163953Srrs case SCTP_TIMER_TYPE_PATHMTURAISE: 2011163953Srrs /* 2012163953Srrs * Here we use the value found in the EP for PMTU ususually 2013163953Srrs * about 10 minutes. 2014163953Srrs */ 2015169420Srrs if ((stcb == NULL) || (inp == NULL)) { 2016169420Srrs return; 2017163953Srrs } 2018163953Srrs if (net == NULL) { 2019169420Srrs return; 2020163953Srrs } 2021225635Stuexen if (net->dest_state & SCTP_ADDR_NO_PMTUD) { 2022225635Stuexen return; 2023225635Stuexen } 2024163953Srrs to_ticks = inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_PMTU]; 2025163953Srrs tmr = &net->pmtu_timer; 2026163953Srrs break; 2027163953Srrs case SCTP_TIMER_TYPE_SHUTDOWNACK: 2028163953Srrs /* Here we use the RTO of the destination */ 2029163953Srrs if ((stcb == NULL) || (net == NULL)) { 2030169420Srrs return; 2031163953Srrs } 2032163953Srrs if (net->RTO == 0) { 2033163953Srrs to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto); 2034163953Srrs } else { 2035163953Srrs to_ticks = MSEC_TO_TICKS(net->RTO); 2036163953Srrs } 2037163953Srrs tmr = &net->rxt_timer; 2038163953Srrs break; 2039163953Srrs case SCTP_TIMER_TYPE_SHUTDOWNGUARD: 2040163953Srrs /* 2041163953Srrs * Here we use the endpoints shutdown guard timer usually 2042163953Srrs * about 3 minutes. 2043163953Srrs */ 2044169420Srrs if ((inp == NULL) || (stcb == NULL)) { 2045169420Srrs return; 2046163953Srrs } 2047163953Srrs to_ticks = inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_MAXSHUTDOWN]; 2048163953Srrs tmr = &stcb->asoc.shut_guard_timer; 2049163953Srrs break; 2050163953Srrs case SCTP_TIMER_TYPE_STRRESET: 2051163953Srrs /* 2052171572Srrs * Here the timer comes from the stcb but its value is from 2053171572Srrs * the net's RTO. 2054163953Srrs */ 2055163953Srrs if ((stcb == NULL) || (net == NULL)) { 2056169420Srrs return; 2057163953Srrs } 2058163953Srrs if (net->RTO == 0) { 2059163953Srrs to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto); 2060163953Srrs } else { 2061163953Srrs to_ticks = MSEC_TO_TICKS(net->RTO); 2062163953Srrs } 2063163953Srrs tmr = &stcb->asoc.strreset_timer; 2064163953Srrs break; 2065163953Srrs case SCTP_TIMER_TYPE_ASCONF: 2066163953Srrs /* 2067171572Srrs * Here the timer comes from the stcb but its value is from 2068171572Srrs * the net's RTO. 2069163953Srrs */ 2070163953Srrs if ((stcb == NULL) || (net == NULL)) { 2071169420Srrs return; 2072163953Srrs } 2073163953Srrs if (net->RTO == 0) { 2074163953Srrs to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto); 2075163953Srrs } else { 2076163953Srrs to_ticks = MSEC_TO_TICKS(net->RTO); 2077163953Srrs } 2078163953Srrs tmr = &stcb->asoc.asconf_timer; 2079163953Srrs break; 2080172091Srrs case SCTP_TIMER_TYPE_PRIM_DELETED: 2081172091Srrs if ((stcb == NULL) || (net != NULL)) { 2082172091Srrs return; 2083172091Srrs } 2084172091Srrs to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto); 2085172091Srrs tmr = &stcb->asoc.delete_prim_timer; 2086172091Srrs break; 2087163953Srrs case SCTP_TIMER_TYPE_AUTOCLOSE: 2088163953Srrs if (stcb == NULL) { 2089169420Srrs return; 2090163953Srrs } 2091163953Srrs if (stcb->asoc.sctp_autoclose_ticks == 0) { 2092163953Srrs /* 2093163953Srrs * Really an error since stcb is NOT set to 2094163953Srrs * autoclose 2095163953Srrs */ 2096169420Srrs return; 2097163953Srrs } 2098163953Srrs to_ticks = stcb->asoc.sctp_autoclose_ticks; 2099163953Srrs tmr = &stcb->asoc.autoclose_timer; 2100163953Srrs break; 2101163953Srrs default: 2102169420Srrs SCTPDBG(SCTP_DEBUG_TIMER1, "%s: Unknown timer type %d\n", 2103169420Srrs __FUNCTION__, t_type); 2104169420Srrs return; 2105163953Srrs break; 2106231039Stuexen } 2107163953Srrs if ((to_ticks <= 0) || (tmr == NULL)) { 2108169420Srrs SCTPDBG(SCTP_DEBUG_TIMER1, "%s: %d:software error to_ticks:%d tmr:%p not set ??\n", 2109252927Stuexen __FUNCTION__, t_type, to_ticks, (void *)tmr); 2110169420Srrs return; 2111163953Srrs } 2112165647Srrs if (SCTP_OS_TIMER_PENDING(&tmr->timer)) { 2113163953Srrs /* 2114163953Srrs * we do NOT allow you to have it already running. if it is 2115163953Srrs * we leave the current one up unchanged 2116163953Srrs */ 2117169420Srrs return; 2118163953Srrs } 2119163953Srrs /* At this point we can proceed */ 2120163953Srrs if (t_type == SCTP_TIMER_TYPE_SEND) { 2121163953Srrs stcb->asoc.num_send_timers_up++; 2122163953Srrs } 2123165220Srrs tmr->stopped_from = 0; 2124163953Srrs tmr->type = t_type; 2125163953Srrs tmr->ep = (void *)inp; 2126163953Srrs tmr->tcb = (void *)stcb; 2127163953Srrs tmr->net = (void *)net; 2128163953Srrs tmr->self = (void *)tmr; 2129197326Stuexen tmr->vnet = (void *)curvnet; 2130171943Srrs tmr->ticks = sctp_get_tick_count(); 2131169420Srrs (void)SCTP_OS_TIMER_START(&tmr->timer, to_ticks, sctp_timeout_handler, tmr); 2132169420Srrs return; 2133163953Srrs} 2134163953Srrs 2135169378Srrsvoid 2136163953Srrssctp_timer_stop(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb, 2137165220Srrs struct sctp_nets *net, uint32_t from) 2138163953Srrs{ 2139163953Srrs struct sctp_timer *tmr; 2140163953Srrs 2141163953Srrs if ((t_type != SCTP_TIMER_TYPE_ADDR_WQ) && 2142163953Srrs (inp == NULL)) 2143169378Srrs return; 2144163953Srrs 2145163953Srrs tmr = NULL; 2146163953Srrs if (stcb) { 2147163953Srrs SCTP_TCB_LOCK_ASSERT(stcb); 2148163953Srrs } 2149163953Srrs switch (t_type) { 2150170056Srrs case SCTP_TIMER_TYPE_ZERO_COPY: 2151170056Srrs tmr = &inp->sctp_ep.zero_copy_timer; 2152170056Srrs break; 2153170181Srrs case SCTP_TIMER_TYPE_ZCOPY_SENDQ: 2154170181Srrs tmr = &inp->sctp_ep.zero_copy_sendq_timer; 2155170181Srrs break; 2156163953Srrs case SCTP_TIMER_TYPE_ADDR_WQ: 2157179783Srrs tmr = &SCTP_BASE_INFO(addr_wq_timer); 2158163953Srrs break; 2159163953Srrs case SCTP_TIMER_TYPE_SEND: 2160163953Srrs if ((stcb == NULL) || (net == NULL)) { 2161169378Srrs return; 2162163953Srrs } 2163163953Srrs tmr = &net->rxt_timer; 2164163953Srrs break; 2165163953Srrs case SCTP_TIMER_TYPE_INIT: 2166163953Srrs if ((stcb == NULL) || (net == NULL)) { 2167169378Srrs return; 2168163953Srrs } 2169163953Srrs tmr = &net->rxt_timer; 2170163953Srrs break; 2171163953Srrs case SCTP_TIMER_TYPE_RECV: 2172163953Srrs if (stcb == NULL) { 2173169378Srrs return; 2174163953Srrs } 2175163953Srrs tmr = &stcb->asoc.dack_timer; 2176163953Srrs break; 2177163953Srrs case SCTP_TIMER_TYPE_SHUTDOWN: 2178163953Srrs if ((stcb == NULL) || (net == NULL)) { 2179169378Srrs return; 2180163953Srrs } 2181163953Srrs tmr = &net->rxt_timer; 2182163953Srrs break; 2183163953Srrs case SCTP_TIMER_TYPE_HEARTBEAT: 2184224641Stuexen if ((stcb == NULL) || (net == NULL)) { 2185169378Srrs return; 2186163953Srrs } 2187224641Stuexen tmr = &net->hb_timer; 2188163953Srrs break; 2189163953Srrs case SCTP_TIMER_TYPE_COOKIE: 2190163953Srrs if ((stcb == NULL) || (net == NULL)) { 2191169378Srrs return; 2192163953Srrs } 2193163953Srrs tmr = &net->rxt_timer; 2194163953Srrs break; 2195163953Srrs case SCTP_TIMER_TYPE_NEWCOOKIE: 2196163953Srrs /* nothing needed but the endpoint here */ 2197163953Srrs tmr = &inp->sctp_ep.signature_change; 2198163953Srrs /* 2199163953Srrs * We re-use the newcookie timer for the INP kill timer. We 2200163953Srrs * must assure that we do not kill it by accident. 2201163953Srrs */ 2202163953Srrs break; 2203163953Srrs case SCTP_TIMER_TYPE_ASOCKILL: 2204163953Srrs /* 2205163953Srrs * Stop the asoc kill timer. 2206163953Srrs */ 2207163953Srrs if (stcb == NULL) { 2208169378Srrs return; 2209163953Srrs } 2210163953Srrs tmr = &stcb->asoc.strreset_timer; 2211163953Srrs break; 2212163953Srrs 2213163953Srrs case SCTP_TIMER_TYPE_INPKILL: 2214163953Srrs /* 2215163953Srrs * The inp is setup to die. We re-use the signature_chage 2216163953Srrs * timer since that has stopped and we are in the GONE 2217163953Srrs * state. 2218163953Srrs */ 2219163953Srrs tmr = &inp->sctp_ep.signature_change; 2220163953Srrs break; 2221163953Srrs case SCTP_TIMER_TYPE_PATHMTURAISE: 2222163953Srrs if ((stcb == NULL) || (net == NULL)) { 2223169378Srrs return; 2224163953Srrs } 2225163953Srrs tmr = &net->pmtu_timer; 2226163953Srrs break; 2227163953Srrs case SCTP_TIMER_TYPE_SHUTDOWNACK: 2228163953Srrs if ((stcb == NULL) || (net == NULL)) { 2229169378Srrs return; 2230163953Srrs } 2231163953Srrs tmr = &net->rxt_timer; 2232163953Srrs break; 2233163953Srrs case SCTP_TIMER_TYPE_SHUTDOWNGUARD: 2234163953Srrs if (stcb == NULL) { 2235169378Srrs return; 2236163953Srrs } 2237163953Srrs tmr = &stcb->asoc.shut_guard_timer; 2238163953Srrs break; 2239163953Srrs case SCTP_TIMER_TYPE_STRRESET: 2240163953Srrs if (stcb == NULL) { 2241169378Srrs return; 2242163953Srrs } 2243163953Srrs tmr = &stcb->asoc.strreset_timer; 2244163953Srrs break; 2245163953Srrs case SCTP_TIMER_TYPE_ASCONF: 2246163953Srrs if (stcb == NULL) { 2247169378Srrs return; 2248163953Srrs } 2249163953Srrs tmr = &stcb->asoc.asconf_timer; 2250163953Srrs break; 2251172091Srrs case SCTP_TIMER_TYPE_PRIM_DELETED: 2252172091Srrs if (stcb == NULL) { 2253172091Srrs return; 2254172091Srrs } 2255172091Srrs tmr = &stcb->asoc.delete_prim_timer; 2256172091Srrs break; 2257163953Srrs case SCTP_TIMER_TYPE_AUTOCLOSE: 2258163953Srrs if (stcb == NULL) { 2259169378Srrs return; 2260163953Srrs } 2261163953Srrs tmr = &stcb->asoc.autoclose_timer; 2262163953Srrs break; 2263163953Srrs default: 2264169420Srrs SCTPDBG(SCTP_DEBUG_TIMER1, "%s: Unknown timer type %d\n", 2265169420Srrs __FUNCTION__, t_type); 2266163953Srrs break; 2267231039Stuexen } 2268163953Srrs if (tmr == NULL) { 2269169378Srrs return; 2270163953Srrs } 2271163953Srrs if ((tmr->type != t_type) && tmr->type) { 2272163953Srrs /* 2273163953Srrs * Ok we have a timer that is under joint use. Cookie timer 2274163953Srrs * per chance with the SEND timer. We therefore are NOT 2275163953Srrs * running the timer that the caller wants stopped. So just 2276163953Srrs * return. 2277163953Srrs */ 2278169378Srrs return; 2279163953Srrs } 2280169420Srrs if ((t_type == SCTP_TIMER_TYPE_SEND) && (stcb != NULL)) { 2281163953Srrs stcb->asoc.num_send_timers_up--; 2282163953Srrs if (stcb->asoc.num_send_timers_up < 0) { 2283163953Srrs stcb->asoc.num_send_timers_up = 0; 2284163953Srrs } 2285163953Srrs } 2286163953Srrs tmr->self = NULL; 2287165220Srrs tmr->stopped_from = from; 2288169378Srrs (void)SCTP_OS_TIMER_STOP(&tmr->timer); 2289169378Srrs return; 2290163953Srrs} 2291163953Srrs 2292163953Srrsuint32_t 2293163953Srrssctp_calculate_len(struct mbuf *m) 2294163953Srrs{ 2295163953Srrs uint32_t tlen = 0; 2296163953Srrs struct mbuf *at; 2297163953Srrs 2298163953Srrs at = m; 2299163953Srrs while (at) { 2300165647Srrs tlen += SCTP_BUF_LEN(at); 2301165647Srrs at = SCTP_BUF_NEXT(at); 2302163953Srrs } 2303163953Srrs return (tlen); 2304163953Srrs} 2305163953Srrs 2306163953Srrsvoid 2307163953Srrssctp_mtu_size_reset(struct sctp_inpcb *inp, 2308166023Srrs struct sctp_association *asoc, uint32_t mtu) 2309163953Srrs{ 2310163953Srrs /* 2311163953Srrs * Reset the P-MTU size on this association, this involves changing 2312163953Srrs * the asoc MTU, going through ANY chunk+overhead larger than mtu to 2313163953Srrs * allow the DF flag to be cleared. 2314163953Srrs */ 2315163953Srrs struct sctp_tmit_chunk *chk; 2316163953Srrs unsigned int eff_mtu, ovh; 2317163953Srrs 2318163953Srrs asoc->smallest_mtu = mtu; 2319163953Srrs if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) { 2320163953Srrs ovh = SCTP_MIN_OVERHEAD; 2321163953Srrs } else { 2322163953Srrs ovh = SCTP_MIN_V4_OVERHEAD; 2323163953Srrs } 2324163953Srrs eff_mtu = mtu - ovh; 2325163953Srrs TAILQ_FOREACH(chk, &asoc->send_queue, sctp_next) { 2326163953Srrs if (chk->send_size > eff_mtu) { 2327163953Srrs chk->flags |= CHUNK_FLAGS_FRAGMENT_OK; 2328163953Srrs } 2329163953Srrs } 2330163953Srrs TAILQ_FOREACH(chk, &asoc->sent_queue, sctp_next) { 2331163953Srrs if (chk->send_size > eff_mtu) { 2332163953Srrs chk->flags |= CHUNK_FLAGS_FRAGMENT_OK; 2333163953Srrs } 2334163953Srrs } 2335163953Srrs} 2336163953Srrs 2337163953Srrs 2338163953Srrs/* 2339163953Srrs * given an association and starting time of the current RTT period return 2340166675Srrs * RTO in number of msecs net should point to the current network 2341163953Srrs */ 2342218186Srrs 2343163953Srrsuint32_t 2344163953Srrssctp_calculate_rto(struct sctp_tcb *stcb, 2345163953Srrs struct sctp_association *asoc, 2346163953Srrs struct sctp_nets *net, 2347171477Srrs struct timeval *told, 2348219397Srrs int safe, int rtt_from_sack) 2349163953Srrs{ 2350171477Srrs /*- 2351163953Srrs * given an association and the starting time of the current RTT 2352166675Srrs * period (in value1/value2) return RTO in number of msecs. 2353163953Srrs */ 2354219013Stuexen int32_t rtt; /* RTT in ms */ 2355219013Stuexen uint32_t new_rto; 2356163953Srrs int first_measure = 0; 2357171477Srrs struct timeval now, then, *old; 2358163953Srrs 2359171477Srrs /* Copy it out for sparc64 */ 2360171477Srrs if (safe == sctp_align_unsafe_makecopy) { 2361171477Srrs old = &then; 2362171477Srrs memcpy(&then, told, sizeof(struct timeval)); 2363171477Srrs } else if (safe == sctp_align_safe_nocopy) { 2364171477Srrs old = told; 2365171477Srrs } else { 2366171477Srrs /* error */ 2367171477Srrs SCTP_PRINTF("Huh, bad rto calc call\n"); 2368171477Srrs return (0); 2369171477Srrs } 2370163953Srrs /************************/ 2371163953Srrs /* 1. calculate new RTT */ 2372163953Srrs /************************/ 2373163953Srrs /* get the current time */ 2374219057Srrs if (stcb->asoc.use_precise_time) { 2375219057Srrs (void)SCTP_GETPTIME_TIMEVAL(&now); 2376219057Srrs } else { 2377219057Srrs (void)SCTP_GETTIME_TIMEVAL(&now); 2378219057Srrs } 2379219013Stuexen timevalsub(&now, old); 2380219013Stuexen /* store the current RTT in us */ 2381240129Stuexen net->rtt = (uint64_t) 1000000 *(uint64_t) now.tv_sec + 2382252925Stuexen (uint64_t) now.tv_usec; 2383218039Srrs 2384219013Stuexen /* computer rtt in ms */ 2385219013Stuexen rtt = net->rtt / 1000; 2386219397Srrs if ((asoc->cc_functions.sctp_rtt_calculated) && (rtt_from_sack == SCTP_RTT_FROM_DATA)) { 2387219397Srrs /* 2388219397Srrs * Tell the CC module that a new update has just occurred 2389219397Srrs * from a sack 2390219397Srrs */ 2391219397Srrs (*asoc->cc_functions.sctp_rtt_calculated) (stcb, net, &now); 2392219397Srrs } 2393219397Srrs /* 2394219397Srrs * Do we need to determine the lan? We do this only on sacks i.e. 2395219397Srrs * RTT being determined from data not non-data (HB/INIT->INITACK). 2396219397Srrs */ 2397219397Srrs if ((rtt_from_sack == SCTP_RTT_FROM_DATA) && 2398219013Stuexen (net->lan_type == SCTP_LAN_UNKNOWN)) { 2399219013Stuexen if (net->rtt > SCTP_LOCAL_LAN_RTT) { 2400218186Srrs net->lan_type = SCTP_LAN_INTERNET; 2401218186Srrs } else { 2402218186Srrs net->lan_type = SCTP_LAN_LOCAL; 2403218186Srrs } 2404218186Srrs } 2405163953Srrs /***************************/ 2406163953Srrs /* 2. update RTTVAR & SRTT */ 2407163953Srrs /***************************/ 2408219013Stuexen /*- 2409219013Stuexen * Compute the scaled average lastsa and the 2410219013Stuexen * scaled variance lastsv as described in van Jacobson 2411219013Stuexen * Paper "Congestion Avoidance and Control", Annex A. 2412219013Stuexen * 2413219013Stuexen * (net->lastsa >> SCTP_RTT_SHIFT) is the srtt 2414219013Stuexen * (net->lastsa >> SCTP_RTT_VAR_SHIFT) is the rttvar 2415219013Stuexen */ 2416170642Srrs if (net->RTO_measured) { 2417219013Stuexen rtt -= (net->lastsa >> SCTP_RTT_SHIFT); 2418219013Stuexen net->lastsa += rtt; 2419219013Stuexen if (rtt < 0) { 2420219013Stuexen rtt = -rtt; 2421219013Stuexen } 2422219013Stuexen rtt -= (net->lastsv >> SCTP_RTT_VAR_SHIFT); 2423219013Stuexen net->lastsv += rtt; 2424179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_RTTVAR_LOGGING_ENABLE) { 2425170744Srrs rto_logging(net, SCTP_LOG_RTTVAR); 2426170744Srrs } 2427163953Srrs } else { 2428163953Srrs /* First RTO measurment */ 2429170642Srrs net->RTO_measured = 1; 2430163953Srrs first_measure = 1; 2431219013Stuexen net->lastsa = rtt << SCTP_RTT_SHIFT; 2432219013Stuexen net->lastsv = (rtt / 2) << SCTP_RTT_VAR_SHIFT; 2433179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_RTTVAR_LOGGING_ENABLE) { 2434170744Srrs rto_logging(net, SCTP_LOG_INITIAL_RTT); 2435170744Srrs } 2436163953Srrs } 2437219013Stuexen if (net->lastsv == 0) { 2438219013Stuexen net->lastsv = SCTP_CLOCK_GRANULARITY; 2439219013Stuexen } 2440170428Srrs new_rto = (net->lastsa >> SCTP_RTT_SHIFT) + net->lastsv; 2441163953Srrs if ((new_rto > SCTP_SAT_NETWORK_MIN) && 2442163953Srrs (stcb->asoc.sat_network_lockout == 0)) { 2443163953Srrs stcb->asoc.sat_network = 1; 2444163953Srrs } else if ((!first_measure) && stcb->asoc.sat_network) { 2445163953Srrs stcb->asoc.sat_network = 0; 2446163953Srrs stcb->asoc.sat_network_lockout = 1; 2447163953Srrs } 2448163953Srrs /* bound it, per C6/C7 in Section 5.3.1 */ 2449163953Srrs if (new_rto < stcb->asoc.minrto) { 2450163953Srrs new_rto = stcb->asoc.minrto; 2451163953Srrs } 2452163953Srrs if (new_rto > stcb->asoc.maxrto) { 2453163953Srrs new_rto = stcb->asoc.maxrto; 2454163953Srrs } 2455168124Srrs /* we are now returning the RTO */ 2456168124Srrs return (new_rto); 2457163953Srrs} 2458163953Srrs 2459163953Srrs/* 2460163953Srrs * return a pointer to a contiguous piece of data from the given mbuf chain 2461163953Srrs * starting at 'off' for 'len' bytes. If the desired piece spans more than 2462163953Srrs * one mbuf, a copy is made at 'ptr'. caller must ensure that the buffer size 2463163953Srrs * is >= 'len' returns NULL if there there isn't 'len' bytes in the chain. 2464163953Srrs */ 2465170806Srrscaddr_t 2466163953Srrssctp_m_getptr(struct mbuf *m, int off, int len, uint8_t * in_ptr) 2467163953Srrs{ 2468163953Srrs uint32_t count; 2469163953Srrs uint8_t *ptr; 2470163953Srrs 2471163953Srrs ptr = in_ptr; 2472163953Srrs if ((off < 0) || (len <= 0)) 2473163953Srrs return (NULL); 2474163953Srrs 2475163953Srrs /* find the desired start location */ 2476163953Srrs while ((m != NULL) && (off > 0)) { 2477165647Srrs if (off < SCTP_BUF_LEN(m)) 2478163953Srrs break; 2479165647Srrs off -= SCTP_BUF_LEN(m); 2480165647Srrs m = SCTP_BUF_NEXT(m); 2481163953Srrs } 2482163953Srrs if (m == NULL) 2483163953Srrs return (NULL); 2484163953Srrs 2485163953Srrs /* is the current mbuf large enough (eg. contiguous)? */ 2486165647Srrs if ((SCTP_BUF_LEN(m) - off) >= len) { 2487163953Srrs return (mtod(m, caddr_t)+off); 2488163953Srrs } else { 2489163953Srrs /* else, it spans more than one mbuf, so save a temp copy... */ 2490163953Srrs while ((m != NULL) && (len > 0)) { 2491165647Srrs count = min(SCTP_BUF_LEN(m) - off, len); 2492163953Srrs bcopy(mtod(m, caddr_t)+off, ptr, count); 2493163953Srrs len -= count; 2494163953Srrs ptr += count; 2495163953Srrs off = 0; 2496165647Srrs m = SCTP_BUF_NEXT(m); 2497163953Srrs } 2498163953Srrs if ((m == NULL) && (len > 0)) 2499163953Srrs return (NULL); 2500163953Srrs else 2501163953Srrs return ((caddr_t)in_ptr); 2502163953Srrs } 2503163953Srrs} 2504163953Srrs 2505163953Srrs 2506166023Srrs 2507163953Srrsstruct sctp_paramhdr * 2508163953Srrssctp_get_next_param(struct mbuf *m, 2509163953Srrs int offset, 2510163953Srrs struct sctp_paramhdr *pull, 2511163953Srrs int pull_limit) 2512163953Srrs{ 2513163953Srrs /* This just provides a typed signature to Peter's Pull routine */ 2514163953Srrs return ((struct sctp_paramhdr *)sctp_m_getptr(m, offset, pull_limit, 2515163953Srrs (uint8_t *) pull)); 2516163953Srrs} 2517163953Srrs 2518163953Srrs 2519163953Srrsint 2520163953Srrssctp_add_pad_tombuf(struct mbuf *m, int padlen) 2521163953Srrs{ 2522163953Srrs /* 2523163953Srrs * add padlen bytes of 0 filled padding to the end of the mbuf. If 2524163953Srrs * padlen is > 3 this routine will fail. 2525163953Srrs */ 2526163953Srrs uint8_t *dp; 2527163953Srrs int i; 2528163953Srrs 2529163953Srrs if (padlen > 3) { 2530171943Srrs SCTP_LTRACE_ERR_RET_PKT(m, NULL, NULL, NULL, SCTP_FROM_SCTPUTIL, ENOBUFS); 2531163953Srrs return (ENOBUFS); 2532163953Srrs } 2533174387Srrs if (padlen <= M_TRAILINGSPACE(m)) { 2534163953Srrs /* 2535163953Srrs * The easy way. We hope the majority of the time we hit 2536163953Srrs * here :) 2537163953Srrs */ 2538165647Srrs dp = (uint8_t *) (mtod(m, caddr_t)+SCTP_BUF_LEN(m)); 2539165647Srrs SCTP_BUF_LEN(m) += padlen; 2540163953Srrs } else { 2541163953Srrs /* Hard way we must grow the mbuf */ 2542163953Srrs struct mbuf *tmp; 2543163953Srrs 2544163953Srrs tmp = sctp_get_mbuf_for_msg(padlen, 0, M_DONTWAIT, 1, MT_DATA); 2545163953Srrs if (tmp == NULL) { 2546163953Srrs /* Out of space GAK! we are in big trouble. */ 2547234796Stuexen SCTP_LTRACE_ERR_RET_PKT(m, NULL, NULL, NULL, SCTP_FROM_SCTPUTIL, ENOBUFS); 2548234796Stuexen return (ENOBUFS); 2549163953Srrs } 2550163953Srrs /* setup and insert in middle */ 2551165647Srrs SCTP_BUF_LEN(tmp) = padlen; 2552174387Srrs SCTP_BUF_NEXT(tmp) = NULL; 2553165647Srrs SCTP_BUF_NEXT(m) = tmp; 2554163953Srrs dp = mtod(tmp, uint8_t *); 2555163953Srrs } 2556163953Srrs /* zero out the pad */ 2557163953Srrs for (i = 0; i < padlen; i++) { 2558163953Srrs *dp = 0; 2559163953Srrs dp++; 2560163953Srrs } 2561163953Srrs return (0); 2562163953Srrs} 2563163953Srrs 2564163953Srrsint 2565163953Srrssctp_pad_lastmbuf(struct mbuf *m, int padval, struct mbuf *last_mbuf) 2566163953Srrs{ 2567163953Srrs /* find the last mbuf in chain and pad it */ 2568163953Srrs struct mbuf *m_at; 2569163953Srrs 2570163953Srrs if (last_mbuf) { 2571163953Srrs return (sctp_add_pad_tombuf(last_mbuf, padval)); 2572163953Srrs } else { 2573237908Stuexen for (m_at = m; m_at; m_at = SCTP_BUF_NEXT(m_at)) { 2574165647Srrs if (SCTP_BUF_NEXT(m_at) == NULL) { 2575163953Srrs return (sctp_add_pad_tombuf(m_at, padval)); 2576163953Srrs } 2577163953Srrs } 2578163953Srrs } 2579171943Srrs SCTP_LTRACE_ERR_RET_PKT(m, NULL, NULL, NULL, SCTP_FROM_SCTPUTIL, EFAULT); 2580163953Srrs return (EFAULT); 2581163953Srrs} 2582163953Srrs 2583163953Srrsstatic void 2584235431Stuexensctp_notify_assoc_change(uint16_t state, struct sctp_tcb *stcb, 2585237886Stuexen uint16_t error, struct sctp_abort_chunk *abort, uint8_t from_peer, int so_locked 2586172090Srrs#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING) 2587172090Srrs SCTP_UNUSED 2588172090Srrs#endif 2589172090Srrs) 2590163953Srrs{ 2591163953Srrs struct mbuf *m_notify; 2592163953Srrs struct sctp_assoc_change *sac; 2593163953Srrs struct sctp_queued_to_read *control; 2594237884Stuexen size_t notif_len, abort_len; 2595235175Stuexen unsigned int i; 2596163953Srrs 2597252882Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2598172090Srrs struct socket *so; 2599172090Srrs 2600172090Srrs#endif 2601172090Srrs 2602237885Stuexen if (sctp_stcb_is_feature_on(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVASSOCEVNT)) { 2603237885Stuexen notif_len = sizeof(struct sctp_assoc_change); 2604237885Stuexen if (abort != NULL) { 2605266056Stuexen abort_len = ntohs(abort->ch.chunk_length); 2606237885Stuexen } else { 2607237885Stuexen abort_len = 0; 2608237885Stuexen } 2609237885Stuexen if ((state == SCTP_COMM_UP) || (state == SCTP_RESTART)) { 2610237885Stuexen notif_len += SCTP_ASSOC_SUPPORTS_MAX; 2611237885Stuexen } else if ((state == SCTP_COMM_LOST) || (state == SCTP_CANT_STR_ASSOC)) { 2612237885Stuexen notif_len += abort_len; 2613237885Stuexen } 2614237885Stuexen m_notify = sctp_get_mbuf_for_msg(notif_len, 0, M_DONTWAIT, 1, MT_DATA); 2615237885Stuexen if (m_notify == NULL) { 2616237885Stuexen /* Retry with smaller value. */ 2617237885Stuexen notif_len = sizeof(struct sctp_assoc_change); 2618237885Stuexen m_notify = sctp_get_mbuf_for_msg(notif_len, 0, M_DONTWAIT, 1, MT_DATA); 2619237885Stuexen if (m_notify == NULL) { 2620237885Stuexen goto set_error; 2621237885Stuexen } 2622237885Stuexen } 2623237885Stuexen SCTP_BUF_NEXT(m_notify) = NULL; 2624237885Stuexen sac = mtod(m_notify, struct sctp_assoc_change *); 2625268433Sdelphij memset(sac, 0, notif_len); 2626237885Stuexen sac->sac_type = SCTP_ASSOC_CHANGE; 2627237885Stuexen sac->sac_flags = 0; 2628237885Stuexen sac->sac_length = sizeof(struct sctp_assoc_change); 2629237885Stuexen sac->sac_state = state; 2630237885Stuexen sac->sac_error = error; 2631237885Stuexen /* XXX verify these stream counts */ 2632237885Stuexen sac->sac_outbound_streams = stcb->asoc.streamoutcnt; 2633237885Stuexen sac->sac_inbound_streams = stcb->asoc.streamincnt; 2634237885Stuexen sac->sac_assoc_id = sctp_get_associd(stcb); 2635237885Stuexen if (notif_len > sizeof(struct sctp_assoc_change)) { 2636237885Stuexen if ((state == SCTP_COMM_UP) || (state == SCTP_RESTART)) { 2637237885Stuexen i = 0; 2638237885Stuexen if (stcb->asoc.peer_supports_prsctp) { 2639237885Stuexen sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_PR; 2640237885Stuexen } 2641237885Stuexen if (stcb->asoc.peer_supports_auth) { 2642237885Stuexen sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_AUTH; 2643237885Stuexen } 2644237885Stuexen if (stcb->asoc.peer_supports_asconf) { 2645237885Stuexen sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_ASCONF; 2646237885Stuexen } 2647237885Stuexen sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_MULTIBUF; 2648237885Stuexen if (stcb->asoc.peer_supports_strreset) { 2649237885Stuexen sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_RE_CONFIG; 2650237885Stuexen } 2651237885Stuexen sac->sac_length += i; 2652237885Stuexen } else if ((state == SCTP_COMM_LOST) || (state == SCTP_CANT_STR_ASSOC)) { 2653237885Stuexen memcpy(sac->sac_info, abort, abort_len); 2654237885Stuexen sac->sac_length += abort_len; 2655237885Stuexen } 2656237885Stuexen } 2657237885Stuexen SCTP_BUF_LEN(m_notify) = sac->sac_length; 2658237885Stuexen control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination, 2659237885Stuexen 0, 0, stcb->asoc.context, 0, 0, 0, 2660237885Stuexen m_notify); 2661237885Stuexen if (control != NULL) { 2662237885Stuexen control->length = SCTP_BUF_LEN(m_notify); 2663237885Stuexen /* not that we need this */ 2664237885Stuexen control->tail_mbuf = m_notify; 2665237885Stuexen control->spec_flags = M_NOTIFICATION; 2666237885Stuexen sctp_add_to_readq(stcb->sctp_ep, stcb, 2667237885Stuexen control, 2668237885Stuexen &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, 2669237885Stuexen so_locked); 2670237885Stuexen } else { 2671237885Stuexen sctp_m_freem(m_notify); 2672237885Stuexen } 2673237885Stuexen } 2674163953Srrs /* 2675237885Stuexen * For 1-to-1 style sockets, we send up and error when an ABORT 2676237885Stuexen * comes in. 2677163953Srrs */ 2678237885Stuexenset_error: 2679163953Srrs if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 2680163953Srrs (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) && 2681235431Stuexen ((state == SCTP_COMM_LOST) || (state == SCTP_CANT_STR_ASSOC))) { 2682252967Stuexen SOCK_LOCK(stcb->sctp_socket); 2683237886Stuexen if (from_peer) { 2684237886Stuexen if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_WAIT) { 2685237886Stuexen SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ECONNREFUSED); 2686237886Stuexen stcb->sctp_socket->so_error = ECONNREFUSED; 2687237886Stuexen } else { 2688237886Stuexen SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ECONNRESET); 2689237886Stuexen stcb->sctp_socket->so_error = ECONNRESET; 2690237886Stuexen } 2691171943Srrs } else { 2692252973Stuexen if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_WAIT) || 2693252973Stuexen (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_ECHOED)) { 2694252973Stuexen SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ETIMEDOUT); 2695252973Stuexen stcb->sctp_socket->so_error = ETIMEDOUT; 2696252973Stuexen } else { 2697252973Stuexen SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ECONNABORTED); 2698252973Stuexen stcb->sctp_socket->so_error = ECONNABORTED; 2699252973Stuexen } 2700171943Srrs } 2701237885Stuexen } 2702237885Stuexen /* Wake ANY sleepers */ 2703252882Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2704237885Stuexen so = SCTP_INP_SO(stcb->sctp_ep); 2705237885Stuexen if (!so_locked) { 2706237885Stuexen atomic_add_int(&stcb->asoc.refcnt, 1); 2707237885Stuexen SCTP_TCB_UNLOCK(stcb); 2708237885Stuexen SCTP_SOCKET_LOCK(so, 1); 2709237885Stuexen SCTP_TCB_LOCK(stcb); 2710237885Stuexen atomic_subtract_int(&stcb->asoc.refcnt, 1); 2711237885Stuexen if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) { 2712172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 2713237884Stuexen return; 2714237884Stuexen } 2715237884Stuexen } 2716237885Stuexen#endif 2717237885Stuexen if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 2718237885Stuexen (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) && 2719237885Stuexen ((state == SCTP_COMM_LOST) || (state == SCTP_CANT_STR_ASSOC))) { 2720252967Stuexen socantrcvmore_locked(stcb->sctp_socket); 2721235175Stuexen } 2722237885Stuexen sorwakeup(stcb->sctp_socket); 2723237885Stuexen sowwakeup(stcb->sctp_socket); 2724252882Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2725237885Stuexen if (!so_locked) { 2726237885Stuexen SCTP_SOCKET_UNLOCK(so, 1); 2727163953Srrs } 2728172090Srrs#endif 2729163953Srrs} 2730163953Srrs 2731163953Srrsstatic void 2732163953Srrssctp_notify_peer_addr_change(struct sctp_tcb *stcb, uint32_t state, 2733163953Srrs struct sockaddr *sa, uint32_t error) 2734163953Srrs{ 2735163953Srrs struct mbuf *m_notify; 2736163953Srrs struct sctp_paddr_change *spc; 2737163953Srrs struct sctp_queued_to_read *control; 2738163953Srrs 2739231039Stuexen if ((stcb == NULL) || 2740231039Stuexen sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVPADDREVNT)) { 2741163953Srrs /* event not enabled */ 2742163953Srrs return; 2743185694Srrs } 2744165647Srrs m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_paddr_change), 0, M_DONTWAIT, 1, MT_DATA); 2745163953Srrs if (m_notify == NULL) 2746163953Srrs return; 2747165647Srrs SCTP_BUF_LEN(m_notify) = 0; 2748163953Srrs spc = mtod(m_notify, struct sctp_paddr_change *); 2749163953Srrs spc->spc_type = SCTP_PEER_ADDR_CHANGE; 2750163953Srrs spc->spc_flags = 0; 2751163953Srrs spc->spc_length = sizeof(struct sctp_paddr_change); 2752178251Srrs switch (sa->sa_family) { 2753221328Stuexen#ifdef INET 2754178251Srrs case AF_INET: 2755163953Srrs memcpy(&spc->spc_aaddr, sa, sizeof(struct sockaddr_in)); 2756178251Srrs break; 2757221328Stuexen#endif 2758178251Srrs#ifdef INET6 2759178251Srrs case AF_INET6: 2760178251Srrs { 2761178251Srrs struct sockaddr_in6 *sin6; 2762166675Srrs 2763178251Srrs memcpy(&spc->spc_aaddr, sa, sizeof(struct sockaddr_in6)); 2764166675Srrs 2765178251Srrs sin6 = (struct sockaddr_in6 *)&spc->spc_aaddr; 2766178251Srrs if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr)) { 2767178251Srrs if (sin6->sin6_scope_id == 0) { 2768178251Srrs /* recover scope_id for user */ 2769178251Srrs (void)sa6_recoverscope(sin6); 2770178251Srrs } else { 2771178251Srrs /* clear embedded scope_id for user */ 2772178251Srrs in6_clearscope(&sin6->sin6_addr); 2773178251Srrs } 2774167598Srrs } 2775178251Srrs break; 2776166675Srrs } 2777178251Srrs#endif 2778178251Srrs default: 2779178251Srrs /* TSNH */ 2780178251Srrs break; 2781163953Srrs } 2782163953Srrs spc->spc_state = state; 2783163953Srrs spc->spc_error = error; 2784163953Srrs spc->spc_assoc_id = sctp_get_associd(stcb); 2785163953Srrs 2786165647Srrs SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_paddr_change); 2787165647Srrs SCTP_BUF_NEXT(m_notify) = NULL; 2788163953Srrs 2789163953Srrs /* append to socket */ 2790163953Srrs control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination, 2791231038Stuexen 0, 0, stcb->asoc.context, 0, 0, 0, 2792163953Srrs m_notify); 2793163953Srrs if (control == NULL) { 2794163953Srrs /* no memory */ 2795163953Srrs sctp_m_freem(m_notify); 2796163953Srrs return; 2797163953Srrs } 2798165647Srrs control->length = SCTP_BUF_LEN(m_notify); 2799165647Srrs control->spec_flags = M_NOTIFICATION; 2800163953Srrs /* not that we need this */ 2801163953Srrs control->tail_mbuf = m_notify; 2802163953Srrs sctp_add_to_readq(stcb->sctp_ep, stcb, 2803163953Srrs control, 2804195918Srrs &stcb->sctp_socket->so_rcv, 1, 2805195918Srrs SCTP_READ_LOCK_NOT_HELD, 2806195918Srrs SCTP_SO_NOT_LOCKED); 2807163953Srrs} 2808163953Srrs 2809163953Srrs 2810163953Srrsstatic void 2811237889Stuexensctp_notify_send_failed(struct sctp_tcb *stcb, uint8_t sent, uint32_t error, 2812172090Srrs struct sctp_tmit_chunk *chk, int so_locked 2813172090Srrs#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING) 2814172090Srrs SCTP_UNUSED 2815172090Srrs#endif 2816172090Srrs) 2817163953Srrs{ 2818185694Srrs struct mbuf *m_notify; 2819163953Srrs struct sctp_send_failed *ssf; 2820235172Stuexen struct sctp_send_failed_event *ssfe; 2821163953Srrs struct sctp_queued_to_read *control; 2822163953Srrs int length; 2823163953Srrs 2824231039Stuexen if ((stcb == NULL) || 2825235172Stuexen (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVSENDFAILEVNT) && 2826235172Stuexen sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVNSENDFAILEVNT))) { 2827163953Srrs /* event not enabled */ 2828163953Srrs return; 2829185694Srrs } 2830235172Stuexen if (sctp_stcb_is_feature_on(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVNSENDFAILEVNT)) { 2831235172Stuexen length = sizeof(struct sctp_send_failed_event); 2832235172Stuexen } else { 2833235172Stuexen length = sizeof(struct sctp_send_failed); 2834235172Stuexen } 2835235172Stuexen m_notify = sctp_get_mbuf_for_msg(length, 0, M_DONTWAIT, 1, MT_DATA); 2836163953Srrs if (m_notify == NULL) 2837163953Srrs /* no space left */ 2838163953Srrs return; 2839165647Srrs SCTP_BUF_LEN(m_notify) = 0; 2840235172Stuexen if (sctp_stcb_is_feature_on(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVNSENDFAILEVNT)) { 2841235172Stuexen ssfe = mtod(m_notify, struct sctp_send_failed_event *); 2842268433Sdelphij memset(ssfe, 0, length); 2843235172Stuexen ssfe->ssfe_type = SCTP_SEND_FAILED_EVENT; 2844237889Stuexen if (sent) { 2845237889Stuexen ssfe->ssfe_flags = SCTP_DATA_SENT; 2846237889Stuexen } else { 2847235172Stuexen ssfe->ssfe_flags = SCTP_DATA_UNSENT; 2848237889Stuexen } 2849268433Sdelphij length += chk->send_size; 2850268433Sdelphij length -= sizeof(struct sctp_data_chunk); 2851235172Stuexen ssfe->ssfe_length = length; 2852235172Stuexen ssfe->ssfe_error = error; 2853235172Stuexen /* not exactly what the user sent in, but should be close :) */ 2854235172Stuexen ssfe->ssfe_info.snd_sid = chk->rec.data.stream_number; 2855235172Stuexen ssfe->ssfe_info.snd_flags = chk->rec.data.rcv_flags; 2856235172Stuexen ssfe->ssfe_info.snd_ppid = chk->rec.data.payloadtype; 2857235172Stuexen ssfe->ssfe_info.snd_context = chk->rec.data.context; 2858235172Stuexen ssfe->ssfe_info.snd_assoc_id = sctp_get_associd(stcb); 2859235172Stuexen ssfe->ssfe_assoc_id = sctp_get_associd(stcb); 2860235172Stuexen SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_send_failed_event); 2861235172Stuexen } else { 2862235172Stuexen ssf = mtod(m_notify, struct sctp_send_failed *); 2863268433Sdelphij memset(ssf, 0, length); 2864235172Stuexen ssf->ssf_type = SCTP_SEND_FAILED; 2865237889Stuexen if (sent) { 2866237889Stuexen ssf->ssf_flags = SCTP_DATA_SENT; 2867237889Stuexen } else { 2868235172Stuexen ssf->ssf_flags = SCTP_DATA_UNSENT; 2869237889Stuexen } 2870268433Sdelphij length += chk->send_size; 2871268433Sdelphij length -= sizeof(struct sctp_data_chunk); 2872235172Stuexen ssf->ssf_length = length; 2873235172Stuexen ssf->ssf_error = error; 2874235172Stuexen /* not exactly what the user sent in, but should be close :) */ 2875235172Stuexen bzero(&ssf->ssf_info, sizeof(ssf->ssf_info)); 2876235172Stuexen ssf->ssf_info.sinfo_stream = chk->rec.data.stream_number; 2877235172Stuexen ssf->ssf_info.sinfo_ssn = chk->rec.data.stream_seq; 2878235172Stuexen ssf->ssf_info.sinfo_flags = chk->rec.data.rcv_flags; 2879235172Stuexen ssf->ssf_info.sinfo_ppid = chk->rec.data.payloadtype; 2880235172Stuexen ssf->ssf_info.sinfo_context = chk->rec.data.context; 2881235172Stuexen ssf->ssf_info.sinfo_assoc_id = sctp_get_associd(stcb); 2882235172Stuexen ssf->ssf_assoc_id = sctp_get_associd(stcb); 2883235172Stuexen SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_send_failed); 2884235172Stuexen } 2885185694Srrs if (chk->data) { 2886185694Srrs /* 2887185694Srrs * trim off the sctp chunk header(it should be there) 2888185694Srrs */ 2889185694Srrs if (chk->send_size >= sizeof(struct sctp_data_chunk)) { 2890185694Srrs m_adj(chk->data, sizeof(struct sctp_data_chunk)); 2891185694Srrs sctp_mbuf_crush(chk->data); 2892185694Srrs chk->send_size -= sizeof(struct sctp_data_chunk); 2893185694Srrs } 2894185694Srrs } 2895196260Stuexen SCTP_BUF_NEXT(m_notify) = chk->data; 2896163953Srrs /* Steal off the mbuf */ 2897163953Srrs chk->data = NULL; 2898163953Srrs /* 2899163953Srrs * For this case, we check the actual socket buffer, since the assoc 2900163953Srrs * is going away we don't want to overfill the socket buffer for a 2901163953Srrs * non-reader 2902163953Srrs */ 2903165647Srrs if (sctp_sbspace_failedmsgs(&stcb->sctp_socket->so_rcv) < SCTP_BUF_LEN(m_notify)) { 2904163953Srrs sctp_m_freem(m_notify); 2905163953Srrs return; 2906163953Srrs } 2907163953Srrs /* append to socket */ 2908163953Srrs control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination, 2909231038Stuexen 0, 0, stcb->asoc.context, 0, 0, 0, 2910163953Srrs m_notify); 2911163953Srrs if (control == NULL) { 2912163953Srrs /* no memory */ 2913163953Srrs sctp_m_freem(m_notify); 2914163953Srrs return; 2915163953Srrs } 2916165647Srrs control->spec_flags = M_NOTIFICATION; 2917163953Srrs sctp_add_to_readq(stcb->sctp_ep, stcb, 2918163953Srrs control, 2919195918Srrs &stcb->sctp_socket->so_rcv, 1, 2920195918Srrs SCTP_READ_LOCK_NOT_HELD, 2921195918Srrs so_locked); 2922163953Srrs} 2923163953Srrs 2924163953Srrs 2925163953Srrsstatic void 2926163953Srrssctp_notify_send_failed2(struct sctp_tcb *stcb, uint32_t error, 2927172090Srrs struct sctp_stream_queue_pending *sp, int so_locked 2928172090Srrs#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING) 2929172090Srrs SCTP_UNUSED 2930172090Srrs#endif 2931172090Srrs) 2932163953Srrs{ 2933163953Srrs struct mbuf *m_notify; 2934163953Srrs struct sctp_send_failed *ssf; 2935235172Stuexen struct sctp_send_failed_event *ssfe; 2936163953Srrs struct sctp_queued_to_read *control; 2937163953Srrs int length; 2938163953Srrs 2939231039Stuexen if ((stcb == NULL) || 2940235172Stuexen (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVSENDFAILEVNT) && 2941235172Stuexen sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVNSENDFAILEVNT))) { 2942163953Srrs /* event not enabled */ 2943163953Srrs return; 2944185694Srrs } 2945235172Stuexen if (sctp_stcb_is_feature_on(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVNSENDFAILEVNT)) { 2946235172Stuexen length = sizeof(struct sctp_send_failed_event); 2947235172Stuexen } else { 2948235172Stuexen length = sizeof(struct sctp_send_failed); 2949235172Stuexen } 2950235172Stuexen m_notify = sctp_get_mbuf_for_msg(length, 0, M_DONTWAIT, 1, MT_DATA); 2951235172Stuexen if (m_notify == NULL) { 2952163953Srrs /* no space left */ 2953163953Srrs return; 2954235172Stuexen } 2955165647Srrs SCTP_BUF_LEN(m_notify) = 0; 2956235172Stuexen if (sctp_stcb_is_feature_on(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVNSENDFAILEVNT)) { 2957235172Stuexen ssfe = mtod(m_notify, struct sctp_send_failed_event *); 2958268433Sdelphij memset(ssfe, 0, length); 2959238549Stuexen ssfe->ssfe_type = SCTP_SEND_FAILED_EVENT; 2960237889Stuexen ssfe->ssfe_flags = SCTP_DATA_UNSENT; 2961268433Sdelphij length += sp->length; 2962235172Stuexen ssfe->ssfe_length = length; 2963235172Stuexen ssfe->ssfe_error = error; 2964235172Stuexen /* not exactly what the user sent in, but should be close :) */ 2965235172Stuexen ssfe->ssfe_info.snd_sid = sp->stream; 2966235172Stuexen if (sp->some_taken) { 2967235172Stuexen ssfe->ssfe_info.snd_flags = SCTP_DATA_LAST_FRAG; 2968235172Stuexen } else { 2969235172Stuexen ssfe->ssfe_info.snd_flags = SCTP_DATA_NOT_FRAG; 2970235172Stuexen } 2971235172Stuexen ssfe->ssfe_info.snd_ppid = sp->ppid; 2972235172Stuexen ssfe->ssfe_info.snd_context = sp->context; 2973235172Stuexen ssfe->ssfe_info.snd_assoc_id = sctp_get_associd(stcb); 2974235172Stuexen ssfe->ssfe_assoc_id = sctp_get_associd(stcb); 2975235172Stuexen SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_send_failed_event); 2976180387Srrs } else { 2977235172Stuexen ssf = mtod(m_notify, struct sctp_send_failed *); 2978268433Sdelphij memset(ssf, 0, length); 2979235172Stuexen ssf->ssf_type = SCTP_SEND_FAILED; 2980237889Stuexen ssf->ssf_flags = SCTP_DATA_UNSENT; 2981268433Sdelphij length += sp->length; 2982235172Stuexen ssf->ssf_length = length; 2983235172Stuexen ssf->ssf_error = error; 2984235172Stuexen /* not exactly what the user sent in, but should be close :) */ 2985235172Stuexen ssf->ssf_info.sinfo_stream = sp->stream; 2986252940Stuexen ssf->ssf_info.sinfo_ssn = 0; 2987235172Stuexen if (sp->some_taken) { 2988235172Stuexen ssf->ssf_info.sinfo_flags = SCTP_DATA_LAST_FRAG; 2989235172Stuexen } else { 2990235172Stuexen ssf->ssf_info.sinfo_flags = SCTP_DATA_NOT_FRAG; 2991235172Stuexen } 2992235172Stuexen ssf->ssf_info.sinfo_ppid = sp->ppid; 2993235172Stuexen ssf->ssf_info.sinfo_context = sp->context; 2994235172Stuexen ssf->ssf_info.sinfo_assoc_id = sctp_get_associd(stcb); 2995235172Stuexen ssf->ssf_assoc_id = sctp_get_associd(stcb); 2996235172Stuexen SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_send_failed); 2997180387Srrs } 2998165647Srrs SCTP_BUF_NEXT(m_notify) = sp->data; 2999163953Srrs 3000163953Srrs /* Steal off the mbuf */ 3001163953Srrs sp->data = NULL; 3002163953Srrs /* 3003163953Srrs * For this case, we check the actual socket buffer, since the assoc 3004163953Srrs * is going away we don't want to overfill the socket buffer for a 3005163953Srrs * non-reader 3006163953Srrs */ 3007165647Srrs if (sctp_sbspace_failedmsgs(&stcb->sctp_socket->so_rcv) < SCTP_BUF_LEN(m_notify)) { 3008163953Srrs sctp_m_freem(m_notify); 3009163953Srrs return; 3010163953Srrs } 3011163953Srrs /* append to socket */ 3012163953Srrs control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination, 3013231038Stuexen 0, 0, stcb->asoc.context, 0, 0, 0, 3014163953Srrs m_notify); 3015163953Srrs if (control == NULL) { 3016163953Srrs /* no memory */ 3017163953Srrs sctp_m_freem(m_notify); 3018163953Srrs return; 3019163953Srrs } 3020165647Srrs control->spec_flags = M_NOTIFICATION; 3021163953Srrs sctp_add_to_readq(stcb->sctp_ep, stcb, 3022163953Srrs control, 3023195918Srrs &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, so_locked); 3024163953Srrs} 3025163953Srrs 3026163953Srrs 3027163953Srrs 3028163953Srrsstatic void 3029231038Stuexensctp_notify_adaptation_layer(struct sctp_tcb *stcb) 3030163953Srrs{ 3031163953Srrs struct mbuf *m_notify; 3032163953Srrs struct sctp_adaptation_event *sai; 3033163953Srrs struct sctp_queued_to_read *control; 3034163953Srrs 3035231039Stuexen if ((stcb == NULL) || 3036231039Stuexen sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_ADAPTATIONEVNT)) { 3037163953Srrs /* event not enabled */ 3038163953Srrs return; 3039185694Srrs } 3040165647Srrs m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_adaption_event), 0, M_DONTWAIT, 1, MT_DATA); 3041163953Srrs if (m_notify == NULL) 3042163953Srrs /* no space left */ 3043163953Srrs return; 3044165647Srrs SCTP_BUF_LEN(m_notify) = 0; 3045163953Srrs sai = mtod(m_notify, struct sctp_adaptation_event *); 3046268433Sdelphij memset(sai, 0, sizeof(struct sctp_adaptation_event)); 3047163953Srrs sai->sai_type = SCTP_ADAPTATION_INDICATION; 3048163953Srrs sai->sai_flags = 0; 3049163953Srrs sai->sai_length = sizeof(struct sctp_adaptation_event); 3050171990Srrs sai->sai_adaptation_ind = stcb->asoc.peers_adaptation; 3051163953Srrs sai->sai_assoc_id = sctp_get_associd(stcb); 3052163953Srrs 3053165647Srrs SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_adaptation_event); 3054165647Srrs SCTP_BUF_NEXT(m_notify) = NULL; 3055163953Srrs 3056163953Srrs /* append to socket */ 3057163953Srrs control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination, 3058231038Stuexen 0, 0, stcb->asoc.context, 0, 0, 0, 3059163953Srrs m_notify); 3060163953Srrs if (control == NULL) { 3061163953Srrs /* no memory */ 3062163953Srrs sctp_m_freem(m_notify); 3063163953Srrs return; 3064163953Srrs } 3065165647Srrs control->length = SCTP_BUF_LEN(m_notify); 3066165647Srrs control->spec_flags = M_NOTIFICATION; 3067163953Srrs /* not that we need this */ 3068163953Srrs control->tail_mbuf = m_notify; 3069163953Srrs sctp_add_to_readq(stcb->sctp_ep, stcb, 3070163953Srrs control, 3071195918Srrs &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED); 3072163953Srrs} 3073163953Srrs 3074164085Srrs/* This always must be called with the read-queue LOCKED in the INP */ 3075196260Stuexenstatic void 3076171858Srrssctp_notify_partial_delivery_indication(struct sctp_tcb *stcb, uint32_t error, 3077196260Stuexen uint32_t val, int so_locked 3078196260Stuexen#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING) 3079196260Stuexen SCTP_UNUSED 3080196260Stuexen#endif 3081196260Stuexen) 3082163953Srrs{ 3083163953Srrs struct mbuf *m_notify; 3084163953Srrs struct sctp_pdapi_event *pdapi; 3085163953Srrs struct sctp_queued_to_read *control; 3086164085Srrs struct sockbuf *sb; 3087163953Srrs 3088231039Stuexen if ((stcb == NULL) || 3089231039Stuexen sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_PDAPIEVNT)) { 3090163953Srrs /* event not enabled */ 3091163953Srrs return; 3092185694Srrs } 3093209289Stuexen if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_CANT_READ) { 3094209289Stuexen return; 3095209289Stuexen } 3096165647Srrs m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_pdapi_event), 0, M_DONTWAIT, 1, MT_DATA); 3097163953Srrs if (m_notify == NULL) 3098163953Srrs /* no space left */ 3099163953Srrs return; 3100165647Srrs SCTP_BUF_LEN(m_notify) = 0; 3101163953Srrs pdapi = mtod(m_notify, struct sctp_pdapi_event *); 3102268433Sdelphij memset(pdapi, 0, sizeof(struct sctp_pdapi_event)); 3103163953Srrs pdapi->pdapi_type = SCTP_PARTIAL_DELIVERY_EVENT; 3104163953Srrs pdapi->pdapi_flags = 0; 3105163953Srrs pdapi->pdapi_length = sizeof(struct sctp_pdapi_event); 3106163953Srrs pdapi->pdapi_indication = error; 3107168943Srrs pdapi->pdapi_stream = (val >> 16); 3108168943Srrs pdapi->pdapi_seq = (val & 0x0000ffff); 3109163953Srrs pdapi->pdapi_assoc_id = sctp_get_associd(stcb); 3110163953Srrs 3111165647Srrs SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_pdapi_event); 3112165647Srrs SCTP_BUF_NEXT(m_notify) = NULL; 3113164085Srrs control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination, 3114231038Stuexen 0, 0, stcb->asoc.context, 0, 0, 0, 3115164085Srrs m_notify); 3116164085Srrs if (control == NULL) { 3117164085Srrs /* no memory */ 3118164085Srrs sctp_m_freem(m_notify); 3119164085Srrs return; 3120164085Srrs } 3121165647Srrs control->spec_flags = M_NOTIFICATION; 3122165647Srrs control->length = SCTP_BUF_LEN(m_notify); 3123164085Srrs /* not that we need this */ 3124164085Srrs control->tail_mbuf = m_notify; 3125164085Srrs control->held_length = 0; 3126164085Srrs control->length = 0; 3127164085Srrs sb = &stcb->sctp_socket->so_rcv; 3128179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) { 3129170744Srrs sctp_sblog(sb, control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBALLOC, SCTP_BUF_LEN(m_notify)); 3130170744Srrs } 3131164085Srrs sctp_sballoc(stcb, sb, m_notify); 3132179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) { 3133170744Srrs sctp_sblog(sb, control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBRESULT, 0); 3134170744Srrs } 3135165647Srrs atomic_add_int(&control->length, SCTP_BUF_LEN(m_notify)); 3136164085Srrs control->end_added = 1; 3137164085Srrs if (stcb->asoc.control_pdapi) 3138164085Srrs TAILQ_INSERT_AFTER(&stcb->sctp_ep->read_queue, stcb->asoc.control_pdapi, control, next); 3139164085Srrs else { 3140164085Srrs /* we really should not see this case */ 3141164085Srrs TAILQ_INSERT_TAIL(&stcb->sctp_ep->read_queue, control, next); 3142164085Srrs } 3143164085Srrs if (stcb->sctp_ep && stcb->sctp_socket) { 3144164085Srrs /* This should always be the case */ 3145252882Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 3146196260Stuexen struct socket *so; 3147196260Stuexen 3148196260Stuexen so = SCTP_INP_SO(stcb->sctp_ep); 3149196260Stuexen if (!so_locked) { 3150196260Stuexen atomic_add_int(&stcb->asoc.refcnt, 1); 3151196260Stuexen SCTP_TCB_UNLOCK(stcb); 3152196260Stuexen SCTP_SOCKET_LOCK(so, 1); 3153196260Stuexen SCTP_TCB_LOCK(stcb); 3154196260Stuexen atomic_subtract_int(&stcb->asoc.refcnt, 1); 3155196260Stuexen if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) { 3156196260Stuexen SCTP_SOCKET_UNLOCK(so, 1); 3157196260Stuexen return; 3158196260Stuexen } 3159196260Stuexen } 3160196260Stuexen#endif 3161163996Srrs sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket); 3162252882Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 3163196260Stuexen if (!so_locked) { 3164196260Stuexen SCTP_SOCKET_UNLOCK(so, 1); 3165196260Stuexen } 3166196260Stuexen#endif 3167163953Srrs } 3168163953Srrs} 3169163953Srrs 3170163953Srrsstatic void 3171163953Srrssctp_notify_shutdown_event(struct sctp_tcb *stcb) 3172163953Srrs{ 3173163953Srrs struct mbuf *m_notify; 3174163953Srrs struct sctp_shutdown_event *sse; 3175163953Srrs struct sctp_queued_to_read *control; 3176163953Srrs 3177163953Srrs /* 3178163953Srrs * For TCP model AND UDP connected sockets we will send an error up 3179163953Srrs * when an SHUTDOWN completes 3180163953Srrs */ 3181163953Srrs if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 3182163953Srrs (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) { 3183163953Srrs /* mark socket closed for read/write and wakeup! */ 3184252882Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 3185172090Srrs struct socket *so; 3186172090Srrs 3187172090Srrs so = SCTP_INP_SO(stcb->sctp_ep); 3188172090Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 3189172090Srrs SCTP_TCB_UNLOCK(stcb); 3190172090Srrs SCTP_SOCKET_LOCK(so, 1); 3191172090Srrs SCTP_TCB_LOCK(stcb); 3192172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 3193172090Srrs if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) { 3194172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 3195172090Srrs return; 3196172090Srrs } 3197172090Srrs#endif 3198163953Srrs socantsendmore(stcb->sctp_socket); 3199252882Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 3200172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 3201172090Srrs#endif 3202163953Srrs } 3203223132Stuexen if (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT)) { 3204163953Srrs /* event not enabled */ 3205163953Srrs return; 3206185694Srrs } 3207165647Srrs m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_shutdown_event), 0, M_DONTWAIT, 1, MT_DATA); 3208163953Srrs if (m_notify == NULL) 3209163953Srrs /* no space left */ 3210163953Srrs return; 3211163953Srrs sse = mtod(m_notify, struct sctp_shutdown_event *); 3212268433Sdelphij memset(sse, 0, sizeof(struct sctp_shutdown_event)); 3213163953Srrs sse->sse_type = SCTP_SHUTDOWN_EVENT; 3214163953Srrs sse->sse_flags = 0; 3215163953Srrs sse->sse_length = sizeof(struct sctp_shutdown_event); 3216163953Srrs sse->sse_assoc_id = sctp_get_associd(stcb); 3217163953Srrs 3218165647Srrs SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_shutdown_event); 3219165647Srrs SCTP_BUF_NEXT(m_notify) = NULL; 3220163953Srrs 3221163953Srrs /* append to socket */ 3222163953Srrs control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination, 3223231038Stuexen 0, 0, stcb->asoc.context, 0, 0, 0, 3224163953Srrs m_notify); 3225163953Srrs if (control == NULL) { 3226163953Srrs /* no memory */ 3227163953Srrs sctp_m_freem(m_notify); 3228163953Srrs return; 3229163953Srrs } 3230165647Srrs control->spec_flags = M_NOTIFICATION; 3231165647Srrs control->length = SCTP_BUF_LEN(m_notify); 3232163953Srrs /* not that we need this */ 3233163953Srrs control->tail_mbuf = m_notify; 3234163953Srrs sctp_add_to_readq(stcb->sctp_ep, stcb, 3235163953Srrs control, 3236195918Srrs &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED); 3237163953Srrs} 3238163953Srrs 3239163953Srrsstatic void 3240185694Srrssctp_notify_sender_dry_event(struct sctp_tcb *stcb, 3241185694Srrs int so_locked 3242185694Srrs#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING) 3243185694Srrs SCTP_UNUSED 3244185694Srrs#endif 3245185694Srrs) 3246185694Srrs{ 3247185694Srrs struct mbuf *m_notify; 3248185694Srrs struct sctp_sender_dry_event *event; 3249185694Srrs struct sctp_queued_to_read *control; 3250185694Srrs 3251231039Stuexen if ((stcb == NULL) || 3252231039Stuexen sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_DRYEVNT)) { 3253185694Srrs /* event not enabled */ 3254185694Srrs return; 3255185694Srrs } 3256185694Srrs m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_sender_dry_event), 0, M_DONTWAIT, 1, MT_DATA); 3257185694Srrs if (m_notify == NULL) { 3258185694Srrs /* no space left */ 3259185694Srrs return; 3260185694Srrs } 3261185694Srrs SCTP_BUF_LEN(m_notify) = 0; 3262185694Srrs event = mtod(m_notify, struct sctp_sender_dry_event *); 3263268433Sdelphij memset(event, 0, sizeof(struct sctp_sender_dry_event)); 3264185694Srrs event->sender_dry_type = SCTP_SENDER_DRY_EVENT; 3265185694Srrs event->sender_dry_flags = 0; 3266185694Srrs event->sender_dry_length = sizeof(struct sctp_sender_dry_event); 3267185694Srrs event->sender_dry_assoc_id = sctp_get_associd(stcb); 3268185694Srrs 3269185694Srrs SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_sender_dry_event); 3270185694Srrs SCTP_BUF_NEXT(m_notify) = NULL; 3271185694Srrs 3272185694Srrs /* append to socket */ 3273185694Srrs control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination, 3274231038Stuexen 0, 0, stcb->asoc.context, 0, 0, 0, 3275231038Stuexen m_notify); 3276185694Srrs if (control == NULL) { 3277185694Srrs /* no memory */ 3278185694Srrs sctp_m_freem(m_notify); 3279185694Srrs return; 3280185694Srrs } 3281185694Srrs control->length = SCTP_BUF_LEN(m_notify); 3282185694Srrs control->spec_flags = M_NOTIFICATION; 3283185694Srrs /* not that we need this */ 3284185694Srrs control->tail_mbuf = m_notify; 3285185694Srrs sctp_add_to_readq(stcb->sctp_ep, stcb, control, 3286195918Srrs &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, so_locked); 3287185694Srrs} 3288185694Srrs 3289188854Srrs 3290234790Stuexenvoid 3291234790Stuexensctp_notify_stream_reset_add(struct sctp_tcb *stcb, uint16_t numberin, uint16_t numberout, int flag) 3292188854Srrs{ 3293188854Srrs struct mbuf *m_notify; 3294188854Srrs struct sctp_queued_to_read *control; 3295234790Stuexen struct sctp_stream_change_event *stradd; 3296188854Srrs 3297235176Stuexen if ((stcb == NULL) || 3298235176Stuexen (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_STREAM_CHANGEEVNT))) { 3299188854Srrs /* event not enabled */ 3300188854Srrs return; 3301188854Srrs } 3302234790Stuexen if ((stcb->asoc.peer_req_out) && flag) { 3303234790Stuexen /* Peer made the request, don't tell the local user */ 3304234790Stuexen stcb->asoc.peer_req_out = 0; 3305234790Stuexen return; 3306234790Stuexen } 3307234790Stuexen stcb->asoc.peer_req_out = 0; 3308268433Sdelphij m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_stream_change_event), 0, M_DONTWAIT, 1, MT_DATA); 3309188854Srrs if (m_notify == NULL) 3310188854Srrs /* no space left */ 3311188854Srrs return; 3312188854Srrs SCTP_BUF_LEN(m_notify) = 0; 3313234790Stuexen stradd = mtod(m_notify, struct sctp_stream_change_event *); 3314268433Sdelphij memset(stradd, 0, sizeof(struct sctp_stream_change_event)); 3315234790Stuexen stradd->strchange_type = SCTP_STREAM_CHANGE_EVENT; 3316234790Stuexen stradd->strchange_flags = flag; 3317268433Sdelphij stradd->strchange_length = sizeof(struct sctp_stream_change_event); 3318234790Stuexen stradd->strchange_assoc_id = sctp_get_associd(stcb); 3319234790Stuexen stradd->strchange_instrms = numberin; 3320234790Stuexen stradd->strchange_outstrms = numberout; 3321268433Sdelphij SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_stream_change_event); 3322234790Stuexen SCTP_BUF_NEXT(m_notify) = NULL; 3323234790Stuexen if (sctp_sbspace(&stcb->asoc, &stcb->sctp_socket->so_rcv) < SCTP_BUF_LEN(m_notify)) { 3324234790Stuexen /* no space */ 3325234790Stuexen sctp_m_freem(m_notify); 3326234790Stuexen return; 3327234790Stuexen } 3328234790Stuexen /* append to socket */ 3329234790Stuexen control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination, 3330234790Stuexen 0, 0, stcb->asoc.context, 0, 0, 0, 3331234790Stuexen m_notify); 3332234790Stuexen if (control == NULL) { 3333234790Stuexen /* no memory */ 3334234790Stuexen sctp_m_freem(m_notify); 3335234790Stuexen return; 3336234790Stuexen } 3337234790Stuexen control->spec_flags = M_NOTIFICATION; 3338234790Stuexen control->length = SCTP_BUF_LEN(m_notify); 3339234790Stuexen /* not that we need this */ 3340234790Stuexen control->tail_mbuf = m_notify; 3341234790Stuexen sctp_add_to_readq(stcb->sctp_ep, stcb, 3342234790Stuexen control, 3343234790Stuexen &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED); 3344234790Stuexen} 3345188854Srrs 3346234790Stuexenvoid 3347234790Stuexensctp_notify_stream_reset_tsn(struct sctp_tcb *stcb, uint32_t sending_tsn, uint32_t recv_tsn, int flag) 3348234790Stuexen{ 3349234790Stuexen struct mbuf *m_notify; 3350234790Stuexen struct sctp_queued_to_read *control; 3351234790Stuexen struct sctp_assoc_reset_event *strasoc; 3352234790Stuexen 3353235176Stuexen if ((stcb == NULL) || 3354235176Stuexen (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_ASSOC_RESETEVNT))) { 3355234790Stuexen /* event not enabled */ 3356234790Stuexen return; 3357234790Stuexen } 3358268433Sdelphij m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_assoc_reset_event), 0, M_DONTWAIT, 1, MT_DATA); 3359234790Stuexen if (m_notify == NULL) 3360234790Stuexen /* no space left */ 3361234790Stuexen return; 3362234790Stuexen SCTP_BUF_LEN(m_notify) = 0; 3363234790Stuexen strasoc = mtod(m_notify, struct sctp_assoc_reset_event *); 3364268433Sdelphij memset(strasoc, 0, sizeof(struct sctp_assoc_reset_event)); 3365234790Stuexen strasoc->assocreset_type = SCTP_ASSOC_RESET_EVENT; 3366234790Stuexen strasoc->assocreset_flags = flag; 3367268433Sdelphij strasoc->assocreset_length = sizeof(struct sctp_assoc_reset_event); 3368234790Stuexen strasoc->assocreset_assoc_id = sctp_get_associd(stcb); 3369234790Stuexen strasoc->assocreset_local_tsn = sending_tsn; 3370234790Stuexen strasoc->assocreset_remote_tsn = recv_tsn; 3371268433Sdelphij SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_assoc_reset_event); 3372188854Srrs SCTP_BUF_NEXT(m_notify) = NULL; 3373188854Srrs if (sctp_sbspace(&stcb->asoc, &stcb->sctp_socket->so_rcv) < SCTP_BUF_LEN(m_notify)) { 3374188854Srrs /* no space */ 3375188854Srrs sctp_m_freem(m_notify); 3376188854Srrs return; 3377188854Srrs } 3378188854Srrs /* append to socket */ 3379188854Srrs control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination, 3380231038Stuexen 0, 0, stcb->asoc.context, 0, 0, 0, 3381188854Srrs m_notify); 3382188854Srrs if (control == NULL) { 3383188854Srrs /* no memory */ 3384188854Srrs sctp_m_freem(m_notify); 3385188854Srrs return; 3386188854Srrs } 3387188854Srrs control->spec_flags = M_NOTIFICATION; 3388188854Srrs control->length = SCTP_BUF_LEN(m_notify); 3389188854Srrs /* not that we need this */ 3390188854Srrs control->tail_mbuf = m_notify; 3391188854Srrs sctp_add_to_readq(stcb->sctp_ep, stcb, 3392188854Srrs control, 3393195918Srrs &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED); 3394188854Srrs} 3395188854Srrs 3396188854Srrs 3397234790Stuexen 3398188854Srrsstatic void 3399163953Srrssctp_notify_stream_reset(struct sctp_tcb *stcb, 3400163953Srrs int number_entries, uint16_t * list, int flag) 3401163953Srrs{ 3402163953Srrs struct mbuf *m_notify; 3403163953Srrs struct sctp_queued_to_read *control; 3404163953Srrs struct sctp_stream_reset_event *strreset; 3405163953Srrs int len; 3406163953Srrs 3407235176Stuexen if ((stcb == NULL) || 3408235176Stuexen (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_STREAM_RESETEVNT))) { 3409185694Srrs /* event not enabled */ 3410169420Srrs return; 3411169420Srrs } 3412165647Srrs m_notify = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_DONTWAIT, 1, MT_DATA); 3413163953Srrs if (m_notify == NULL) 3414163953Srrs /* no space left */ 3415163953Srrs return; 3416165647Srrs SCTP_BUF_LEN(m_notify) = 0; 3417163953Srrs len = sizeof(struct sctp_stream_reset_event) + (number_entries * sizeof(uint16_t)); 3418163953Srrs if (len > M_TRAILINGSPACE(m_notify)) { 3419163953Srrs /* never enough room */ 3420163953Srrs sctp_m_freem(m_notify); 3421163953Srrs return; 3422163953Srrs } 3423163953Srrs strreset = mtod(m_notify, struct sctp_stream_reset_event *); 3424268433Sdelphij memset(strreset, 0, len); 3425163953Srrs strreset->strreset_type = SCTP_STREAM_RESET_EVENT; 3426234790Stuexen strreset->strreset_flags = flag; 3427163953Srrs strreset->strreset_length = len; 3428163953Srrs strreset->strreset_assoc_id = sctp_get_associd(stcb); 3429163953Srrs if (number_entries) { 3430163953Srrs int i; 3431163953Srrs 3432163953Srrs for (i = 0; i < number_entries; i++) { 3433234790Stuexen strreset->strreset_stream_list[i] = ntohs(list[i]); 3434163953Srrs } 3435163953Srrs } 3436165647Srrs SCTP_BUF_LEN(m_notify) = len; 3437165647Srrs SCTP_BUF_NEXT(m_notify) = NULL; 3438165647Srrs if (sctp_sbspace(&stcb->asoc, &stcb->sctp_socket->so_rcv) < SCTP_BUF_LEN(m_notify)) { 3439163953Srrs /* no space */ 3440163953Srrs sctp_m_freem(m_notify); 3441163953Srrs return; 3442163953Srrs } 3443163953Srrs /* append to socket */ 3444163953Srrs control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination, 3445231038Stuexen 0, 0, stcb->asoc.context, 0, 0, 0, 3446163953Srrs m_notify); 3447163953Srrs if (control == NULL) { 3448163953Srrs /* no memory */ 3449163953Srrs sctp_m_freem(m_notify); 3450163953Srrs return; 3451163953Srrs } 3452165647Srrs control->spec_flags = M_NOTIFICATION; 3453165647Srrs control->length = SCTP_BUF_LEN(m_notify); 3454163953Srrs /* not that we need this */ 3455163953Srrs control->tail_mbuf = m_notify; 3456163953Srrs sctp_add_to_readq(stcb->sctp_ep, stcb, 3457163953Srrs control, 3458195918Srrs &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED); 3459163953Srrs} 3460163953Srrs 3461163953Srrs 3462237890Stuexenstatic void 3463237890Stuexensctp_notify_remote_error(struct sctp_tcb *stcb, uint16_t error, struct sctp_error_chunk *chunk) 3464237890Stuexen{ 3465237890Stuexen struct mbuf *m_notify; 3466237890Stuexen struct sctp_remote_error *sre; 3467237890Stuexen struct sctp_queued_to_read *control; 3468237890Stuexen size_t notif_len, chunk_len; 3469237890Stuexen 3470237890Stuexen if ((stcb == NULL) || 3471237890Stuexen sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVPEERERR)) { 3472237890Stuexen return; 3473237890Stuexen } 3474237890Stuexen if (chunk != NULL) { 3475266056Stuexen chunk_len = ntohs(chunk->ch.chunk_length); 3476237890Stuexen } else { 3477237890Stuexen chunk_len = 0; 3478237890Stuexen } 3479237890Stuexen notif_len = sizeof(struct sctp_remote_error) + chunk_len; 3480237890Stuexen m_notify = sctp_get_mbuf_for_msg(notif_len, 0, M_DONTWAIT, 1, MT_DATA); 3481237890Stuexen if (m_notify == NULL) { 3482237890Stuexen /* Retry with smaller value. */ 3483237890Stuexen notif_len = sizeof(struct sctp_remote_error); 3484237890Stuexen m_notify = sctp_get_mbuf_for_msg(notif_len, 0, M_DONTWAIT, 1, MT_DATA); 3485237890Stuexen if (m_notify == NULL) { 3486237890Stuexen return; 3487237890Stuexen } 3488237890Stuexen } 3489237890Stuexen SCTP_BUF_NEXT(m_notify) = NULL; 3490237890Stuexen sre = mtod(m_notify, struct sctp_remote_error *); 3491237890Stuexen sre->sre_type = SCTP_REMOTE_ERROR; 3492237890Stuexen sre->sre_flags = 0; 3493237890Stuexen sre->sre_length = sizeof(struct sctp_remote_error); 3494237890Stuexen sre->sre_error = error; 3495237890Stuexen sre->sre_assoc_id = sctp_get_associd(stcb); 3496237890Stuexen if (notif_len > sizeof(struct sctp_remote_error)) { 3497237890Stuexen memcpy(sre->sre_data, chunk, chunk_len); 3498237890Stuexen sre->sre_length += chunk_len; 3499237890Stuexen } 3500237890Stuexen SCTP_BUF_LEN(m_notify) = sre->sre_length; 3501237890Stuexen control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination, 3502237890Stuexen 0, 0, stcb->asoc.context, 0, 0, 0, 3503237890Stuexen m_notify); 3504237890Stuexen if (control != NULL) { 3505237890Stuexen control->length = SCTP_BUF_LEN(m_notify); 3506237890Stuexen /* not that we need this */ 3507237890Stuexen control->tail_mbuf = m_notify; 3508237890Stuexen control->spec_flags = M_NOTIFICATION; 3509237890Stuexen sctp_add_to_readq(stcb->sctp_ep, stcb, 3510237890Stuexen control, 3511237890Stuexen &stcb->sctp_socket->so_rcv, 1, 3512237890Stuexen SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED); 3513237890Stuexen } else { 3514237890Stuexen sctp_m_freem(m_notify); 3515237890Stuexen } 3516237890Stuexen} 3517237890Stuexen 3518237890Stuexen 3519163953Srrsvoid 3520163953Srrssctp_ulp_notify(uint32_t notification, struct sctp_tcb *stcb, 3521172090Srrs uint32_t error, void *data, int so_locked 3522172090Srrs#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING) 3523172090Srrs SCTP_UNUSED 3524172090Srrs#endif 3525172090Srrs) 3526163953Srrs{ 3527185694Srrs if ((stcb == NULL) || 3528185694Srrs (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) || 3529163953Srrs (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) || 3530185694Srrs (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET)) { 3531185694Srrs /* If the socket is gone we are out of here */ 3532163953Srrs return; 3533163953Srrs } 3534188067Srrs if (stcb->sctp_socket->so_rcv.sb_state & SBS_CANTRCVMORE) { 3535188067Srrs return; 3536188067Srrs } 3537252974Stuexen if ((stcb->asoc.state & SCTP_STATE_COOKIE_WAIT) || 3538252974Stuexen (stcb->asoc.state & SCTP_STATE_COOKIE_ECHOED)) { 3539169352Srrs if ((notification == SCTP_NOTIFY_INTERFACE_DOWN) || 3540169352Srrs (notification == SCTP_NOTIFY_INTERFACE_UP) || 3541169352Srrs (notification == SCTP_NOTIFY_INTERFACE_CONFIRMED)) { 3542169352Srrs /* Don't report these in front states */ 3543169352Srrs return; 3544169352Srrs } 3545169352Srrs } 3546163953Srrs switch (notification) { 3547163953Srrs case SCTP_NOTIFY_ASSOC_UP: 3548163953Srrs if (stcb->asoc.assoc_up_sent == 0) { 3549237886Stuexen sctp_notify_assoc_change(SCTP_COMM_UP, stcb, error, NULL, 0, so_locked); 3550163953Srrs stcb->asoc.assoc_up_sent = 1; 3551163953Srrs } 3552171990Srrs if (stcb->asoc.adaptation_needed && (stcb->asoc.adaptation_sent == 0)) { 3553231038Stuexen sctp_notify_adaptation_layer(stcb); 3554171990Srrs } 3555185694Srrs if (stcb->asoc.peer_supports_auth == 0) { 3556185694Srrs sctp_ulp_notify(SCTP_NOTIFY_NO_PEER_AUTH, stcb, 0, 3557185694Srrs NULL, so_locked); 3558185694Srrs } 3559163953Srrs break; 3560163953Srrs case SCTP_NOTIFY_ASSOC_DOWN: 3561237886Stuexen sctp_notify_assoc_change(SCTP_SHUTDOWN_COMP, stcb, error, NULL, 0, so_locked); 3562163953Srrs break; 3563163953Srrs case SCTP_NOTIFY_INTERFACE_DOWN: 3564163953Srrs { 3565163953Srrs struct sctp_nets *net; 3566163953Srrs 3567163953Srrs net = (struct sctp_nets *)data; 3568163953Srrs sctp_notify_peer_addr_change(stcb, SCTP_ADDR_UNREACHABLE, 3569163953Srrs (struct sockaddr *)&net->ro._l_addr, error); 3570163953Srrs break; 3571163953Srrs } 3572163953Srrs case SCTP_NOTIFY_INTERFACE_UP: 3573163953Srrs { 3574163953Srrs struct sctp_nets *net; 3575163953Srrs 3576163953Srrs net = (struct sctp_nets *)data; 3577163953Srrs sctp_notify_peer_addr_change(stcb, SCTP_ADDR_AVAILABLE, 3578163953Srrs (struct sockaddr *)&net->ro._l_addr, error); 3579163953Srrs break; 3580163953Srrs } 3581163953Srrs case SCTP_NOTIFY_INTERFACE_CONFIRMED: 3582163953Srrs { 3583163953Srrs struct sctp_nets *net; 3584163953Srrs 3585163953Srrs net = (struct sctp_nets *)data; 3586163953Srrs sctp_notify_peer_addr_change(stcb, SCTP_ADDR_CONFIRMED, 3587163953Srrs (struct sockaddr *)&net->ro._l_addr, error); 3588163953Srrs break; 3589163953Srrs } 3590163953Srrs case SCTP_NOTIFY_SPECIAL_SP_FAIL: 3591163953Srrs sctp_notify_send_failed2(stcb, error, 3592172090Srrs (struct sctp_stream_queue_pending *)data, so_locked); 3593163953Srrs break; 3594237889Stuexen case SCTP_NOTIFY_SENT_DG_FAIL: 3595237889Stuexen sctp_notify_send_failed(stcb, 1, error, 3596172090Srrs (struct sctp_tmit_chunk *)data, so_locked); 3597163953Srrs break; 3598237889Stuexen case SCTP_NOTIFY_UNSENT_DG_FAIL: 3599237889Stuexen sctp_notify_send_failed(stcb, 0, error, 3600237889Stuexen (struct sctp_tmit_chunk *)data, so_locked); 3601237889Stuexen break; 3602163953Srrs case SCTP_NOTIFY_PARTIAL_DELVIERY_INDICATION: 3603168943Srrs { 3604168943Srrs uint32_t val; 3605168943Srrs 3606168943Srrs val = *((uint32_t *) data); 3607168943Srrs 3608196260Stuexen sctp_notify_partial_delivery_indication(stcb, error, val, so_locked); 3609196260Stuexen break; 3610168943Srrs } 3611237886Stuexen case SCTP_NOTIFY_ASSOC_LOC_ABORTED: 3612252974Stuexen if (((stcb->asoc.state & SCTP_STATE_MASK) == SCTP_STATE_COOKIE_WAIT) || 3613252974Stuexen ((stcb->asoc.state & SCTP_STATE_MASK) == SCTP_STATE_COOKIE_ECHOED)) { 3614237886Stuexen sctp_notify_assoc_change(SCTP_CANT_STR_ASSOC, stcb, error, data, 0, so_locked); 3615168709Srrs } else { 3616237886Stuexen sctp_notify_assoc_change(SCTP_COMM_LOST, stcb, error, data, 0, so_locked); 3617168709Srrs } 3618163953Srrs break; 3619237886Stuexen case SCTP_NOTIFY_ASSOC_REM_ABORTED: 3620252974Stuexen if (((stcb->asoc.state & SCTP_STATE_MASK) == SCTP_STATE_COOKIE_WAIT) || 3621252974Stuexen ((stcb->asoc.state & SCTP_STATE_MASK) == SCTP_STATE_COOKIE_ECHOED)) { 3622237886Stuexen sctp_notify_assoc_change(SCTP_CANT_STR_ASSOC, stcb, error, data, 1, so_locked); 3623237886Stuexen } else { 3624237886Stuexen sctp_notify_assoc_change(SCTP_COMM_LOST, stcb, error, data, 1, so_locked); 3625237886Stuexen } 3626237886Stuexen break; 3627163953Srrs case SCTP_NOTIFY_ASSOC_RESTART: 3628237886Stuexen sctp_notify_assoc_change(SCTP_RESTART, stcb, error, NULL, 0, so_locked); 3629185694Srrs if (stcb->asoc.peer_supports_auth == 0) { 3630185694Srrs sctp_ulp_notify(SCTP_NOTIFY_NO_PEER_AUTH, stcb, 0, 3631185694Srrs NULL, so_locked); 3632185694Srrs } 3633163953Srrs break; 3634163953Srrs case SCTP_NOTIFY_STR_RESET_SEND: 3635234801Stuexen sctp_notify_stream_reset(stcb, error, ((uint16_t *) data), SCTP_STREAM_RESET_OUTGOING_SSN); 3636163953Srrs break; 3637163953Srrs case SCTP_NOTIFY_STR_RESET_RECV: 3638234801Stuexen sctp_notify_stream_reset(stcb, error, ((uint16_t *) data), SCTP_STREAM_RESET_INCOMING); 3639163953Srrs break; 3640163953Srrs case SCTP_NOTIFY_STR_RESET_FAILED_OUT: 3641234790Stuexen sctp_notify_stream_reset(stcb, error, ((uint16_t *) data), 3642234801Stuexen (SCTP_STREAM_RESET_OUTGOING_SSN | SCTP_STREAM_RESET_FAILED)); 3643163953Srrs break; 3644235171Stuexen case SCTP_NOTIFY_STR_RESET_DENIED_OUT: 3645235171Stuexen sctp_notify_stream_reset(stcb, error, ((uint16_t *) data), 3646235171Stuexen (SCTP_STREAM_RESET_OUTGOING_SSN | SCTP_STREAM_RESET_DENIED)); 3647235171Stuexen break; 3648163953Srrs case SCTP_NOTIFY_STR_RESET_FAILED_IN: 3649234790Stuexen sctp_notify_stream_reset(stcb, error, ((uint16_t *) data), 3650234801Stuexen (SCTP_STREAM_RESET_INCOMING | SCTP_STREAM_RESET_FAILED)); 3651163953Srrs break; 3652235171Stuexen case SCTP_NOTIFY_STR_RESET_DENIED_IN: 3653235171Stuexen sctp_notify_stream_reset(stcb, error, ((uint16_t *) data), 3654235171Stuexen (SCTP_STREAM_RESET_INCOMING | SCTP_STREAM_RESET_DENIED)); 3655235171Stuexen break; 3656163953Srrs case SCTP_NOTIFY_ASCONF_ADD_IP: 3657163953Srrs sctp_notify_peer_addr_change(stcb, SCTP_ADDR_ADDED, data, 3658163953Srrs error); 3659163953Srrs break; 3660163953Srrs case SCTP_NOTIFY_ASCONF_DELETE_IP: 3661163953Srrs sctp_notify_peer_addr_change(stcb, SCTP_ADDR_REMOVED, data, 3662163953Srrs error); 3663163953Srrs break; 3664163953Srrs case SCTP_NOTIFY_ASCONF_SET_PRIMARY: 3665163953Srrs sctp_notify_peer_addr_change(stcb, SCTP_ADDR_MADE_PRIM, data, 3666163953Srrs error); 3667163953Srrs break; 3668163953Srrs case SCTP_NOTIFY_PEER_SHUTDOWN: 3669163953Srrs sctp_notify_shutdown_event(stcb); 3670163953Srrs break; 3671163953Srrs case SCTP_NOTIFY_AUTH_NEW_KEY: 3672234802Stuexen sctp_notify_authentication(stcb, SCTP_AUTH_NEW_KEY, error, 3673185694Srrs (uint16_t) (uintptr_t) data, 3674185694Srrs so_locked); 3675163953Srrs break; 3676185694Srrs case SCTP_NOTIFY_AUTH_FREE_KEY: 3677185694Srrs sctp_notify_authentication(stcb, SCTP_AUTH_FREE_KEY, error, 3678185694Srrs (uint16_t) (uintptr_t) data, 3679185694Srrs so_locked); 3680163953Srrs break; 3681185694Srrs case SCTP_NOTIFY_NO_PEER_AUTH: 3682185694Srrs sctp_notify_authentication(stcb, SCTP_AUTH_NO_AUTH, error, 3683185694Srrs (uint16_t) (uintptr_t) data, 3684185694Srrs so_locked); 3685185694Srrs break; 3686185694Srrs case SCTP_NOTIFY_SENDER_DRY: 3687185694Srrs sctp_notify_sender_dry_event(stcb, so_locked); 3688185694Srrs break; 3689237890Stuexen case SCTP_NOTIFY_REMOTE_ERROR: 3690237890Stuexen sctp_notify_remote_error(stcb, error, data); 3691237890Stuexen break; 3692163953Srrs default: 3693169420Srrs SCTPDBG(SCTP_DEBUG_UTIL1, "%s: unknown notification %xh (%u)\n", 3694169420Srrs __FUNCTION__, notification, notification); 3695163953Srrs break; 3696163953Srrs } /* end switch */ 3697163953Srrs} 3698163953Srrs 3699163953Srrsvoid 3700237889Stuexensctp_report_all_outbound(struct sctp_tcb *stcb, uint16_t error, int holds_lock, int so_locked 3701172090Srrs#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING) 3702172090Srrs SCTP_UNUSED 3703172090Srrs#endif 3704172090Srrs) 3705163953Srrs{ 3706163953Srrs struct sctp_association *asoc; 3707163953Srrs struct sctp_stream_out *outs; 3708216822Stuexen struct sctp_tmit_chunk *chk, *nchk; 3709216822Stuexen struct sctp_stream_queue_pending *sp, *nsp; 3710164205Srrs int i; 3711163953Srrs 3712169420Srrs if (stcb == NULL) { 3713169420Srrs return; 3714169420Srrs } 3715216822Stuexen asoc = &stcb->asoc; 3716216822Stuexen if (asoc->state & SCTP_STATE_ABOUT_TO_BE_FREED) { 3717209663Srrs /* already being freed */ 3718209663Srrs return; 3719209663Srrs } 3720163953Srrs if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) || 3721163953Srrs (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) || 3722216822Stuexen (asoc->state & SCTP_STATE_CLOSED_SOCKET)) { 3723163953Srrs return; 3724163953Srrs } 3725163953Srrs /* now through all the gunk freeing chunks */ 3726169420Srrs if (holds_lock == 0) { 3727164205Srrs SCTP_TCB_SEND_LOCK(stcb); 3728169420Srrs } 3729170462Srrs /* sent queue SHOULD be empty */ 3730216822Stuexen TAILQ_FOREACH_SAFE(chk, &asoc->sent_queue, sctp_next, nchk) { 3731216822Stuexen TAILQ_REMOVE(&asoc->sent_queue, chk, sctp_next); 3732216822Stuexen asoc->sent_queue_cnt--; 3733252943Stuexen if (chk->sent != SCTP_DATAGRAM_NR_ACKED) { 3734252942Stuexen if (asoc->strmout[chk->rec.data.stream_number].chunks_on_queues > 0) { 3735252942Stuexen asoc->strmout[chk->rec.data.stream_number].chunks_on_queues--; 3736252942Stuexen#ifdef INVARIANTS 3737252942Stuexen } else { 3738252942Stuexen panic("No chunks on the queues for sid %u.", chk->rec.data.stream_number); 3739252942Stuexen#endif 3740252942Stuexen } 3741252942Stuexen } 3742216822Stuexen if (chk->data != NULL) { 3743216822Stuexen sctp_free_bufspace(stcb, asoc, chk, 1); 3744237889Stuexen sctp_ulp_notify(SCTP_NOTIFY_SENT_DG_FAIL, stcb, 3745237889Stuexen error, chk, so_locked); 3746216822Stuexen if (chk->data) { 3747216822Stuexen sctp_m_freem(chk->data); 3748216822Stuexen chk->data = NULL; 3749163953Srrs } 3750163953Srrs } 3751221627Stuexen sctp_free_a_chunk(stcb, chk, so_locked); 3752216822Stuexen /* sa_ignore FREED_MEMORY */ 3753163953Srrs } 3754170462Srrs /* pending send queue SHOULD be empty */ 3755216822Stuexen TAILQ_FOREACH_SAFE(chk, &asoc->send_queue, sctp_next, nchk) { 3756216822Stuexen TAILQ_REMOVE(&asoc->send_queue, chk, sctp_next); 3757216822Stuexen asoc->send_queue_cnt--; 3758252942Stuexen if (asoc->strmout[chk->rec.data.stream_number].chunks_on_queues > 0) { 3759252942Stuexen asoc->strmout[chk->rec.data.stream_number].chunks_on_queues--; 3760252942Stuexen#ifdef INVARIANTS 3761252942Stuexen } else { 3762252942Stuexen panic("No chunks on the queues for sid %u.", chk->rec.data.stream_number); 3763252942Stuexen#endif 3764252942Stuexen } 3765216822Stuexen if (chk->data != NULL) { 3766216822Stuexen sctp_free_bufspace(stcb, asoc, chk, 1); 3767237889Stuexen sctp_ulp_notify(SCTP_NOTIFY_UNSENT_DG_FAIL, stcb, 3768237889Stuexen error, chk, so_locked); 3769216822Stuexen if (chk->data) { 3770216822Stuexen sctp_m_freem(chk->data); 3771216822Stuexen chk->data = NULL; 3772163953Srrs } 3773163953Srrs } 3774221627Stuexen sctp_free_a_chunk(stcb, chk, so_locked); 3775216822Stuexen /* sa_ignore FREED_MEMORY */ 3776163953Srrs } 3777216822Stuexen for (i = 0; i < asoc->streamoutcnt; i++) { 3778170462Srrs /* For each stream */ 3779216822Stuexen outs = &asoc->strmout[i]; 3780170462Srrs /* clean up any sends there */ 3781216822Stuexen asoc->locked_on_sending = NULL; 3782216822Stuexen TAILQ_FOREACH_SAFE(sp, &outs->outqueue, next, nsp) { 3783216822Stuexen asoc->stream_queue_cnt--; 3784170462Srrs TAILQ_REMOVE(&outs->outqueue, sp, next); 3785170462Srrs sctp_free_spbufspace(stcb, asoc, sp); 3786170462Srrs if (sp->data) { 3787209663Srrs sctp_ulp_notify(SCTP_NOTIFY_SPECIAL_SP_FAIL, stcb, 3788237889Stuexen error, (void *)sp, so_locked); 3789209663Srrs if (sp->data) { 3790209663Srrs sctp_m_freem(sp->data); 3791209663Srrs sp->data = NULL; 3792238655Stuexen sp->tail_mbuf = NULL; 3793238655Stuexen sp->length = 0; 3794209663Srrs } 3795170462Srrs } 3796212712Stuexen if (sp->net) { 3797170462Srrs sctp_free_remote_addr(sp->net); 3798212712Stuexen sp->net = NULL; 3799212712Stuexen } 3800170462Srrs /* Free the chunk */ 3801221627Stuexen sctp_free_a_strmoq(stcb, sp, so_locked); 3802170462Srrs /* sa_ignore FREED_MEMORY */ 3803170462Srrs } 3804170462Srrs } 3805170462Srrs 3806169420Srrs if (holds_lock == 0) { 3807164205Srrs SCTP_TCB_SEND_UNLOCK(stcb); 3808169420Srrs } 3809163953Srrs} 3810163953Srrs 3811163953Srrsvoid 3812237886Stuexensctp_abort_notification(struct sctp_tcb *stcb, uint8_t from_peer, uint16_t error, 3813237884Stuexen struct sctp_abort_chunk *abort, int so_locked 3814172090Srrs#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING) 3815172090Srrs SCTP_UNUSED 3816172090Srrs#endif 3817172090Srrs) 3818163953Srrs{ 3819169420Srrs if (stcb == NULL) { 3820169420Srrs return; 3821169420Srrs } 3822225559Stuexen if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) || 3823225559Stuexen ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) && 3824225559Stuexen (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_CONNECTED))) { 3825225559Stuexen stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_WAS_ABORTED; 3826225559Stuexen } 3827163953Srrs if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) || 3828163953Srrs (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) || 3829163953Srrs (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET)) { 3830163953Srrs return; 3831163953Srrs } 3832163953Srrs /* Tell them we lost the asoc */ 3833237889Stuexen sctp_report_all_outbound(stcb, error, 1, so_locked); 3834237886Stuexen if (from_peer) { 3835237886Stuexen sctp_ulp_notify(SCTP_NOTIFY_ASSOC_REM_ABORTED, stcb, error, abort, so_locked); 3836237886Stuexen } else { 3837237886Stuexen sctp_ulp_notify(SCTP_NOTIFY_ASSOC_LOC_ABORTED, stcb, error, abort, so_locked); 3838237886Stuexen } 3839163953Srrs} 3840163953Srrs 3841163953Srrsvoid 3842163953Srrssctp_abort_association(struct sctp_inpcb *inp, struct sctp_tcb *stcb, 3843252889Stuexen struct mbuf *m, int iphlen, 3844252889Stuexen struct sockaddr *src, struct sockaddr *dst, 3845252889Stuexen struct sctphdr *sh, struct mbuf *op_err, 3846238253Stuexen uint8_t use_mflowid, uint32_t mflowid, 3847179157Srrs uint32_t vrf_id, uint16_t port) 3848163953Srrs{ 3849163953Srrs uint32_t vtag; 3850163953Srrs 3851252882Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 3852172090Srrs struct socket *so; 3853172090Srrs 3854172090Srrs#endif 3855172090Srrs 3856163953Srrs vtag = 0; 3857163953Srrs if (stcb != NULL) { 3858163953Srrs /* We have a TCB to abort, send notification too */ 3859163953Srrs vtag = stcb->asoc.peer_vtag; 3860237886Stuexen sctp_abort_notification(stcb, 0, 0, NULL, SCTP_SO_NOT_LOCKED); 3861169352Srrs /* get the assoc vrf id and table id */ 3862169352Srrs vrf_id = stcb->asoc.vrf_id; 3863171745Srrs stcb->asoc.state |= SCTP_STATE_WAS_ABORTED; 3864163953Srrs } 3865252889Stuexen sctp_send_abort(m, iphlen, src, dst, sh, vtag, op_err, 3866238253Stuexen use_mflowid, mflowid, 3867238253Stuexen vrf_id, port); 3868163953Srrs if (stcb != NULL) { 3869163953Srrs /* Ok, now lets free it */ 3870252882Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 3871172090Srrs so = SCTP_INP_SO(inp); 3872172090Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 3873172090Srrs SCTP_TCB_UNLOCK(stcb); 3874172090Srrs SCTP_SOCKET_LOCK(so, 1); 3875172090Srrs SCTP_TCB_LOCK(stcb); 3876172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 3877172090Srrs#endif 3878216397Stuexen SCTP_STAT_INCR_COUNTER32(sctps_aborted); 3879216397Stuexen if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) || 3880216397Stuexen (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) { 3881216397Stuexen SCTP_STAT_DECR_GAUGE32(sctps_currestab); 3882216397Stuexen } 3883171943Srrs (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTPUTIL + SCTP_LOC_4); 3884252882Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 3885172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 3886172090Srrs#endif 3887163953Srrs } 3888163953Srrs} 3889163953Srrs 3890168859Srrs#ifdef SCTP_ASOCLOG_OF_TSNS 3891163953Srrsvoid 3892168859Srrssctp_print_out_track_log(struct sctp_tcb *stcb) 3893168859Srrs{ 3894171477Srrs#ifdef NOSIY_PRINTS 3895168859Srrs int i; 3896168859Srrs 3897169420Srrs SCTP_PRINTF("Last ep reason:%x\n", stcb->sctp_ep->last_abort_code); 3898169420Srrs SCTP_PRINTF("IN bound TSN log-aaa\n"); 3899168859Srrs if ((stcb->asoc.tsn_in_at == 0) && (stcb->asoc.tsn_in_wrapped == 0)) { 3900169420Srrs SCTP_PRINTF("None rcvd\n"); 3901168859Srrs goto none_in; 3902168859Srrs } 3903168859Srrs if (stcb->asoc.tsn_in_wrapped) { 3904168859Srrs for (i = stcb->asoc.tsn_in_at; i < SCTP_TSN_LOG_SIZE; i++) { 3905169420Srrs SCTP_PRINTF("TSN:%x strm:%d seq:%d flags:%x sz:%d\n", 3906168859Srrs stcb->asoc.in_tsnlog[i].tsn, 3907168859Srrs stcb->asoc.in_tsnlog[i].strm, 3908168859Srrs stcb->asoc.in_tsnlog[i].seq, 3909168859Srrs stcb->asoc.in_tsnlog[i].flgs, 3910168859Srrs stcb->asoc.in_tsnlog[i].sz); 3911168859Srrs } 3912168859Srrs } 3913168859Srrs if (stcb->asoc.tsn_in_at) { 3914168859Srrs for (i = 0; i < stcb->asoc.tsn_in_at; i++) { 3915169420Srrs SCTP_PRINTF("TSN:%x strm:%d seq:%d flags:%x sz:%d\n", 3916168859Srrs stcb->asoc.in_tsnlog[i].tsn, 3917168859Srrs stcb->asoc.in_tsnlog[i].strm, 3918168859Srrs stcb->asoc.in_tsnlog[i].seq, 3919168859Srrs stcb->asoc.in_tsnlog[i].flgs, 3920168859Srrs stcb->asoc.in_tsnlog[i].sz); 3921168859Srrs } 3922168859Srrs } 3923168859Srrsnone_in: 3924169420Srrs SCTP_PRINTF("OUT bound TSN log-aaa\n"); 3925169420Srrs if ((stcb->asoc.tsn_out_at == 0) && 3926169420Srrs (stcb->asoc.tsn_out_wrapped == 0)) { 3927169420Srrs SCTP_PRINTF("None sent\n"); 3928168859Srrs } 3929168859Srrs if (stcb->asoc.tsn_out_wrapped) { 3930168859Srrs for (i = stcb->asoc.tsn_out_at; i < SCTP_TSN_LOG_SIZE; i++) { 3931169420Srrs SCTP_PRINTF("TSN:%x strm:%d seq:%d flags:%x sz:%d\n", 3932168859Srrs stcb->asoc.out_tsnlog[i].tsn, 3933168859Srrs stcb->asoc.out_tsnlog[i].strm, 3934168859Srrs stcb->asoc.out_tsnlog[i].seq, 3935168859Srrs stcb->asoc.out_tsnlog[i].flgs, 3936168859Srrs stcb->asoc.out_tsnlog[i].sz); 3937168859Srrs } 3938168859Srrs } 3939168859Srrs if (stcb->asoc.tsn_out_at) { 3940168859Srrs for (i = 0; i < stcb->asoc.tsn_out_at; i++) { 3941169420Srrs SCTP_PRINTF("TSN:%x strm:%d seq:%d flags:%x sz:%d\n", 3942168859Srrs stcb->asoc.out_tsnlog[i].tsn, 3943168859Srrs stcb->asoc.out_tsnlog[i].strm, 3944168859Srrs stcb->asoc.out_tsnlog[i].seq, 3945168859Srrs stcb->asoc.out_tsnlog[i].flgs, 3946168859Srrs stcb->asoc.out_tsnlog[i].sz); 3947168859Srrs } 3948168859Srrs } 3949171477Srrs#endif 3950168859Srrs} 3951168859Srrs 3952168859Srrs#endif 3953168859Srrs 3954168859Srrsvoid 3955163953Srrssctp_abort_an_association(struct sctp_inpcb *inp, struct sctp_tcb *stcb, 3956237884Stuexen struct mbuf *op_err, 3957172090Srrs int so_locked 3958172090Srrs#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING) 3959172090Srrs SCTP_UNUSED 3960172090Srrs#endif 3961172090Srrs) 3962163953Srrs{ 3963252882Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 3964172090Srrs struct socket *so; 3965172090Srrs 3966172090Srrs#endif 3967172090Srrs 3968252882Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 3969172090Srrs so = SCTP_INP_SO(inp); 3970172090Srrs#endif 3971163953Srrs if (stcb == NULL) { 3972163953Srrs /* Got to have a TCB */ 3973163953Srrs if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) { 3974252975Stuexen if (LIST_EMPTY(&inp->sctp_asoc_list)) { 3975169380Srrs sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT, 3976169380Srrs SCTP_CALLED_DIRECTLY_NOCMPSET); 3977163953Srrs } 3978163953Srrs } 3979163953Srrs return; 3980171745Srrs } else { 3981171745Srrs stcb->asoc.state |= SCTP_STATE_WAS_ABORTED; 3982163953Srrs } 3983163953Srrs /* notify the ulp */ 3984237884Stuexen if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) { 3985237886Stuexen sctp_abort_notification(stcb, 0, 0, NULL, so_locked); 3986237884Stuexen } 3987163953Srrs /* notify the peer */ 3988172090Srrs sctp_send_abort_tcb(stcb, op_err, so_locked); 3989163953Srrs SCTP_STAT_INCR_COUNTER32(sctps_aborted); 3990163953Srrs if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) || 3991163953Srrs (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) { 3992163953Srrs SCTP_STAT_DECR_GAUGE32(sctps_currestab); 3993163953Srrs } 3994163953Srrs /* now free the asoc */ 3995168859Srrs#ifdef SCTP_ASOCLOG_OF_TSNS 3996168859Srrs sctp_print_out_track_log(stcb); 3997168859Srrs#endif 3998252882Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 3999172090Srrs if (!so_locked) { 4000172090Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 4001172090Srrs SCTP_TCB_UNLOCK(stcb); 4002172090Srrs SCTP_SOCKET_LOCK(so, 1); 4003172090Srrs SCTP_TCB_LOCK(stcb); 4004172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 4005172090Srrs } 4006172090Srrs#endif 4007171943Srrs (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTPUTIL + SCTP_LOC_5); 4008252882Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 4009172090Srrs if (!so_locked) { 4010172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 4011172090Srrs } 4012172090Srrs#endif 4013163953Srrs} 4014163953Srrs 4015163953Srrsvoid 4016252889Stuexensctp_handle_ootb(struct mbuf *m, int iphlen, int offset, 4017252889Stuexen struct sockaddr *src, struct sockaddr *dst, 4018252889Stuexen struct sctphdr *sh, struct sctp_inpcb *inp, 4019266181Stuexen struct mbuf *cause, 4020238253Stuexen uint8_t use_mflowid, uint32_t mflowid, 4021238253Stuexen uint32_t vrf_id, uint16_t port) 4022163953Srrs{ 4023163953Srrs struct sctp_chunkhdr *ch, chunk_buf; 4024163953Srrs unsigned int chk_length; 4025231045Stuexen int contains_init_chunk; 4026163953Srrs 4027163953Srrs SCTP_STAT_INCR_COUNTER32(sctps_outoftheblue); 4028163953Srrs /* Generate a TO address for future reference */ 4029163953Srrs if (inp && (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) { 4030252975Stuexen if (LIST_EMPTY(&inp->sctp_asoc_list)) { 4031169380Srrs sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT, 4032169380Srrs SCTP_CALLED_DIRECTLY_NOCMPSET); 4033163953Srrs } 4034163953Srrs } 4035231045Stuexen contains_init_chunk = 0; 4036163953Srrs ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, offset, 4037163953Srrs sizeof(*ch), (uint8_t *) & chunk_buf); 4038163953Srrs while (ch != NULL) { 4039163953Srrs chk_length = ntohs(ch->chunk_length); 4040163953Srrs if (chk_length < sizeof(*ch)) { 4041163953Srrs /* break to abort land */ 4042163953Srrs break; 4043163953Srrs } 4044163953Srrs switch (ch->chunk_type) { 4045231045Stuexen case SCTP_INIT: 4046231045Stuexen contains_init_chunk = 1; 4047231045Stuexen break; 4048163953Srrs case SCTP_PACKET_DROPPED: 4049163953Srrs /* we don't respond to pkt-dropped */ 4050163953Srrs return; 4051163953Srrs case SCTP_ABORT_ASSOCIATION: 4052163953Srrs /* we don't respond with an ABORT to an ABORT */ 4053163953Srrs return; 4054163953Srrs case SCTP_SHUTDOWN_COMPLETE: 4055163953Srrs /* 4056163953Srrs * we ignore it since we are not waiting for it and 4057163953Srrs * peer is gone 4058163953Srrs */ 4059163953Srrs return; 4060163953Srrs case SCTP_SHUTDOWN_ACK: 4061252889Stuexen sctp_send_shutdown_complete2(src, dst, sh, 4062238253Stuexen use_mflowid, mflowid, 4063238253Stuexen vrf_id, port); 4064163953Srrs return; 4065163953Srrs default: 4066163953Srrs break; 4067163953Srrs } 4068163953Srrs offset += SCTP_SIZE32(chk_length); 4069163953Srrs ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, offset, 4070163953Srrs sizeof(*ch), (uint8_t *) & chunk_buf); 4071163953Srrs } 4072231045Stuexen if ((SCTP_BASE_SYSCTL(sctp_blackhole) == 0) || 4073231045Stuexen ((SCTP_BASE_SYSCTL(sctp_blackhole) == 1) && 4074231045Stuexen (contains_init_chunk == 0))) { 4075266181Stuexen sctp_send_abort(m, iphlen, src, dst, sh, 0, cause, 4076238253Stuexen use_mflowid, mflowid, 4077238253Stuexen vrf_id, port); 4078231045Stuexen } 4079163953Srrs} 4080163953Srrs 4081163953Srrs/* 4082163953Srrs * check the inbound datagram to make sure there is not an abort inside it, 4083163953Srrs * if there is return 1, else return 0. 4084163953Srrs */ 4085163953Srrsint 4086163953Srrssctp_is_there_an_abort_here(struct mbuf *m, int iphlen, uint32_t * vtagfill) 4087163953Srrs{ 4088163953Srrs struct sctp_chunkhdr *ch; 4089163953Srrs struct sctp_init_chunk *init_chk, chunk_buf; 4090163953Srrs int offset; 4091163953Srrs unsigned int chk_length; 4092163953Srrs 4093163953Srrs offset = iphlen + sizeof(struct sctphdr); 4094163953Srrs ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, offset, sizeof(*ch), 4095163953Srrs (uint8_t *) & chunk_buf); 4096163953Srrs while (ch != NULL) { 4097163953Srrs chk_length = ntohs(ch->chunk_length); 4098163953Srrs if (chk_length < sizeof(*ch)) { 4099163953Srrs /* packet is probably corrupt */ 4100163953Srrs break; 4101163953Srrs } 4102163953Srrs /* we seem to be ok, is it an abort? */ 4103163953Srrs if (ch->chunk_type == SCTP_ABORT_ASSOCIATION) { 4104163953Srrs /* yep, tell them */ 4105163953Srrs return (1); 4106163953Srrs } 4107163953Srrs if (ch->chunk_type == SCTP_INITIATION) { 4108163953Srrs /* need to update the Vtag */ 4109163953Srrs init_chk = (struct sctp_init_chunk *)sctp_m_getptr(m, 4110163953Srrs offset, sizeof(*init_chk), (uint8_t *) & chunk_buf); 4111163953Srrs if (init_chk != NULL) { 4112163953Srrs *vtagfill = ntohl(init_chk->init.initiate_tag); 4113163953Srrs } 4114163953Srrs } 4115163953Srrs /* Nope, move to the next chunk */ 4116163953Srrs offset += SCTP_SIZE32(chk_length); 4117163953Srrs ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, offset, 4118163953Srrs sizeof(*ch), (uint8_t *) & chunk_buf); 4119163953Srrs } 4120163953Srrs return (0); 4121163953Srrs} 4122163953Srrs 4123163953Srrs/* 4124163953Srrs * currently (2/02), ifa_addr embeds scope_id's and don't have sin6_scope_id 4125163953Srrs * set (i.e. it's 0) so, create this function to compare link local scopes 4126163953Srrs */ 4127178251Srrs#ifdef INET6 4128163953Srrsuint32_t 4129163953Srrssctp_is_same_scope(struct sockaddr_in6 *addr1, struct sockaddr_in6 *addr2) 4130163953Srrs{ 4131163953Srrs struct sockaddr_in6 a, b; 4132163953Srrs 4133163953Srrs /* save copies */ 4134163953Srrs a = *addr1; 4135163953Srrs b = *addr2; 4136163953Srrs 4137163953Srrs if (a.sin6_scope_id == 0) 4138163953Srrs if (sa6_recoverscope(&a)) { 4139163953Srrs /* can't get scope, so can't match */ 4140163953Srrs return (0); 4141163953Srrs } 4142163953Srrs if (b.sin6_scope_id == 0) 4143163953Srrs if (sa6_recoverscope(&b)) { 4144163953Srrs /* can't get scope, so can't match */ 4145163953Srrs return (0); 4146163953Srrs } 4147163953Srrs if (a.sin6_scope_id != b.sin6_scope_id) 4148163953Srrs return (0); 4149163953Srrs 4150163953Srrs return (1); 4151163953Srrs} 4152163953Srrs 4153163953Srrs/* 4154163953Srrs * returns a sockaddr_in6 with embedded scope recovered and removed 4155163953Srrs */ 4156163953Srrsstruct sockaddr_in6 * 4157163953Srrssctp_recover_scope(struct sockaddr_in6 *addr, struct sockaddr_in6 *store) 4158163953Srrs{ 4159163953Srrs /* check and strip embedded scope junk */ 4160163953Srrs if (addr->sin6_family == AF_INET6) { 4161163953Srrs if (IN6_IS_SCOPE_LINKLOCAL(&addr->sin6_addr)) { 4162163953Srrs if (addr->sin6_scope_id == 0) { 4163163953Srrs *store = *addr; 4164163953Srrs if (!sa6_recoverscope(store)) { 4165163953Srrs /* use the recovered scope */ 4166163953Srrs addr = store; 4167163953Srrs } 4168166675Srrs } else { 4169163953Srrs /* else, return the original "to" addr */ 4170166675Srrs in6_clearscope(&addr->sin6_addr); 4171163953Srrs } 4172163953Srrs } 4173163953Srrs } 4174163953Srrs return (addr); 4175163953Srrs} 4176163953Srrs 4177178251Srrs#endif 4178178251Srrs 4179163953Srrs/* 4180163953Srrs * are the two addresses the same? currently a "scopeless" check returns: 1 4181163953Srrs * if same, 0 if not 4182163953Srrs */ 4183170806Srrsint 4184163953Srrssctp_cmpaddr(struct sockaddr *sa1, struct sockaddr *sa2) 4185163953Srrs{ 4186163953Srrs 4187163953Srrs /* must be valid */ 4188163953Srrs if (sa1 == NULL || sa2 == NULL) 4189163953Srrs return (0); 4190163953Srrs 4191163953Srrs /* must be the same family */ 4192163953Srrs if (sa1->sa_family != sa2->sa_family) 4193163953Srrs return (0); 4194163953Srrs 4195178251Srrs switch (sa1->sa_family) { 4196178251Srrs#ifdef INET6 4197178251Srrs case AF_INET6: 4198178251Srrs { 4199178251Srrs /* IPv6 addresses */ 4200178251Srrs struct sockaddr_in6 *sin6_1, *sin6_2; 4201163953Srrs 4202178251Srrs sin6_1 = (struct sockaddr_in6 *)sa1; 4203178251Srrs sin6_2 = (struct sockaddr_in6 *)sa2; 4204179157Srrs return (SCTP6_ARE_ADDR_EQUAL(sin6_1, 4205179157Srrs sin6_2)); 4206178251Srrs } 4207178251Srrs#endif 4208221328Stuexen#ifdef INET 4209178251Srrs case AF_INET: 4210178251Srrs { 4211178251Srrs /* IPv4 addresses */ 4212178251Srrs struct sockaddr_in *sin_1, *sin_2; 4213163953Srrs 4214178251Srrs sin_1 = (struct sockaddr_in *)sa1; 4215178251Srrs sin_2 = (struct sockaddr_in *)sa2; 4216178251Srrs return (sin_1->sin_addr.s_addr == sin_2->sin_addr.s_addr); 4217178251Srrs } 4218221328Stuexen#endif 4219178251Srrs default: 4220163953Srrs /* we don't do these... */ 4221163953Srrs return (0); 4222163953Srrs } 4223163953Srrs} 4224163953Srrs 4225163953Srrsvoid 4226163953Srrssctp_print_address(struct sockaddr *sa) 4227163953Srrs{ 4228178251Srrs#ifdef INET6 4229169420Srrs char ip6buf[INET6_ADDRSTRLEN]; 4230163953Srrs 4231178251Srrs#endif 4232163953Srrs 4233178251Srrs switch (sa->sa_family) { 4234178251Srrs#ifdef INET6 4235178251Srrs case AF_INET6: 4236178251Srrs { 4237178251Srrs struct sockaddr_in6 *sin6; 4238163953Srrs 4239178251Srrs sin6 = (struct sockaddr_in6 *)sa; 4240178251Srrs SCTP_PRINTF("IPv6 address: %s:port:%d scope:%u\n", 4241178251Srrs ip6_sprintf(ip6buf, &sin6->sin6_addr), 4242178251Srrs ntohs(sin6->sin6_port), 4243178251Srrs sin6->sin6_scope_id); 4244178251Srrs break; 4245178251Srrs } 4246178251Srrs#endif 4247221328Stuexen#ifdef INET 4248178251Srrs case AF_INET: 4249178251Srrs { 4250178251Srrs struct sockaddr_in *sin; 4251178251Srrs unsigned char *p; 4252178251Srrs 4253178251Srrs sin = (struct sockaddr_in *)sa; 4254178251Srrs p = (unsigned char *)&sin->sin_addr; 4255178251Srrs SCTP_PRINTF("IPv4 address: %u.%u.%u.%u:%d\n", 4256178251Srrs p[0], p[1], p[2], p[3], ntohs(sin->sin_port)); 4257178251Srrs break; 4258178251Srrs } 4259221328Stuexen#endif 4260178251Srrs default: 4261169420Srrs SCTP_PRINTF("?\n"); 4262178251Srrs break; 4263163953Srrs } 4264163953Srrs} 4265163953Srrs 4266163953Srrsvoid 4267163953Srrssctp_pull_off_control_to_new_inp(struct sctp_inpcb *old_inp, 4268163953Srrs struct sctp_inpcb *new_inp, 4269169208Srrs struct sctp_tcb *stcb, 4270169208Srrs int waitflags) 4271163953Srrs{ 4272163953Srrs /* 4273163953Srrs * go through our old INP and pull off any control structures that 4274163953Srrs * belong to stcb and move then to the new inp. 4275163953Srrs */ 4276163953Srrs struct socket *old_so, *new_so; 4277163953Srrs struct sctp_queued_to_read *control, *nctl; 4278163953Srrs struct sctp_readhead tmp_queue; 4279163953Srrs struct mbuf *m; 4280168299Srrs int error = 0; 4281163953Srrs 4282163953Srrs old_so = old_inp->sctp_socket; 4283163953Srrs new_so = new_inp->sctp_socket; 4284163953Srrs TAILQ_INIT(&tmp_queue); 4285169208Srrs error = sblock(&old_so->so_rcv, waitflags); 4286163953Srrs if (error) { 4287163953Srrs /* 4288163953Srrs * Gak, can't get sblock, we have a problem. data will be 4289163953Srrs * left stranded.. and we don't dare look at it since the 4290163953Srrs * other thread may be reading something. Oh well, its a 4291163953Srrs * screwed up app that does a peeloff OR a accept while 4292163953Srrs * reading from the main socket... actually its only the 4293163953Srrs * peeloff() case, since I think read will fail on a 4294163953Srrs * listening socket.. 4295163953Srrs */ 4296163953Srrs return; 4297163953Srrs } 4298163953Srrs /* lock the socket buffers */ 4299163953Srrs SCTP_INP_READ_LOCK(old_inp); 4300216822Stuexen TAILQ_FOREACH_SAFE(control, &old_inp->read_queue, next, nctl) { 4301216822Stuexen /* Pull off all for out target stcb */ 4302163953Srrs if (control->stcb == stcb) { 4303163953Srrs /* remove it we want it */ 4304163953Srrs TAILQ_REMOVE(&old_inp->read_queue, control, next); 4305163953Srrs TAILQ_INSERT_TAIL(&tmp_queue, control, next); 4306163953Srrs m = control->data; 4307163953Srrs while (m) { 4308179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) { 4309170744Srrs sctp_sblog(&old_so->so_rcv, control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBFREE, SCTP_BUF_LEN(m)); 4310170744Srrs } 4311163953Srrs sctp_sbfree(control, stcb, &old_so->so_rcv, m); 4312179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) { 4313170744Srrs sctp_sblog(&old_so->so_rcv, control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBRESULT, 0); 4314170744Srrs } 4315165647Srrs m = SCTP_BUF_NEXT(m); 4316163953Srrs } 4317163953Srrs } 4318163953Srrs } 4319163953Srrs SCTP_INP_READ_UNLOCK(old_inp); 4320163953Srrs /* Remove the sb-lock on the old socket */ 4321163953Srrs 4322163953Srrs sbunlock(&old_so->so_rcv); 4323163953Srrs /* Now we move them over to the new socket buffer */ 4324163953Srrs SCTP_INP_READ_LOCK(new_inp); 4325216822Stuexen TAILQ_FOREACH_SAFE(control, &tmp_queue, next, nctl) { 4326163953Srrs TAILQ_INSERT_TAIL(&new_inp->read_queue, control, next); 4327163953Srrs m = control->data; 4328163953Srrs while (m) { 4329179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) { 4330170744Srrs sctp_sblog(&new_so->so_rcv, control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBALLOC, SCTP_BUF_LEN(m)); 4331170744Srrs } 4332163953Srrs sctp_sballoc(stcb, &new_so->so_rcv, m); 4333179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) { 4334170744Srrs sctp_sblog(&new_so->so_rcv, control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBRESULT, 0); 4335170744Srrs } 4336165647Srrs m = SCTP_BUF_NEXT(m); 4337163953Srrs } 4338163953Srrs } 4339163953Srrs SCTP_INP_READ_UNLOCK(new_inp); 4340163953Srrs} 4341163953Srrs 4342163953Srrsvoid 4343163953Srrssctp_add_to_readq(struct sctp_inpcb *inp, 4344163953Srrs struct sctp_tcb *stcb, 4345163953Srrs struct sctp_queued_to_read *control, 4346163953Srrs struct sockbuf *sb, 4347172090Srrs int end, 4348195918Srrs int inp_read_lock_held, 4349172090Srrs int so_locked 4350172090Srrs#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING) 4351172090Srrs SCTP_UNUSED 4352172090Srrs#endif 4353172090Srrs) 4354163953Srrs{ 4355163953Srrs /* 4356163953Srrs * Here we must place the control on the end of the socket read 4357163953Srrs * queue AND increment sb_cc so that select will work properly on 4358163953Srrs * read. 4359163953Srrs */ 4360163953Srrs struct mbuf *m, *prev = NULL; 4361163953Srrs 4362164085Srrs if (inp == NULL) { 4363164085Srrs /* Gak, TSNH!! */ 4364165220Srrs#ifdef INVARIANTS 4365164085Srrs panic("Gak, inp NULL on add_to_readq"); 4366164085Srrs#endif 4367164085Srrs return; 4368164085Srrs } 4369195918Srrs if (inp_read_lock_held == 0) 4370195918Srrs SCTP_INP_READ_LOCK(inp); 4371209289Stuexen if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_CANT_READ) { 4372209289Stuexen sctp_free_remote_addr(control->whoFrom); 4373209289Stuexen if (control->data) { 4374209289Stuexen sctp_m_freem(control->data); 4375209289Stuexen control->data = NULL; 4376209289Stuexen } 4377209289Stuexen SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_readq), control); 4378209289Stuexen if (inp_read_lock_held == 0) 4379209289Stuexen SCTP_INP_READ_UNLOCK(inp); 4380209289Stuexen return; 4381209289Stuexen } 4382167598Srrs if (!(control->spec_flags & M_NOTIFICATION)) { 4383167598Srrs atomic_add_int(&inp->total_recvs, 1); 4384167598Srrs if (!control->do_not_ref_stcb) { 4385167598Srrs atomic_add_int(&stcb->total_recvs, 1); 4386167598Srrs } 4387167598Srrs } 4388163953Srrs m = control->data; 4389163953Srrs control->held_length = 0; 4390163953Srrs control->length = 0; 4391163953Srrs while (m) { 4392165647Srrs if (SCTP_BUF_LEN(m) == 0) { 4393163953Srrs /* Skip mbufs with NO length */ 4394163953Srrs if (prev == NULL) { 4395163953Srrs /* First one */ 4396163953Srrs control->data = sctp_m_free(m); 4397163953Srrs m = control->data; 4398163953Srrs } else { 4399165647Srrs SCTP_BUF_NEXT(prev) = sctp_m_free(m); 4400165647Srrs m = SCTP_BUF_NEXT(prev); 4401163953Srrs } 4402163953Srrs if (m == NULL) { 4403201758Smbr control->tail_mbuf = prev; 4404163953Srrs } 4405163953Srrs continue; 4406163953Srrs } 4407163953Srrs prev = m; 4408179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) { 4409170744Srrs sctp_sblog(sb, control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBALLOC, SCTP_BUF_LEN(m)); 4410170744Srrs } 4411163953Srrs sctp_sballoc(stcb, sb, m); 4412179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) { 4413170744Srrs sctp_sblog(sb, control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBRESULT, 0); 4414170744Srrs } 4415165647Srrs atomic_add_int(&control->length, SCTP_BUF_LEN(m)); 4416165647Srrs m = SCTP_BUF_NEXT(m); 4417163953Srrs } 4418163953Srrs if (prev != NULL) { 4419163953Srrs control->tail_mbuf = prev; 4420163953Srrs } else { 4421165647Srrs /* Everything got collapsed out?? */ 4422209289Stuexen sctp_free_remote_addr(control->whoFrom); 4423209289Stuexen SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_readq), control); 4424195918Srrs if (inp_read_lock_held == 0) 4425195918Srrs SCTP_INP_READ_UNLOCK(inp); 4426163953Srrs return; 4427163953Srrs } 4428163953Srrs if (end) { 4429163953Srrs control->end_added = 1; 4430163953Srrs } 4431163953Srrs TAILQ_INSERT_TAIL(&inp->read_queue, control, next); 4432195918Srrs if (inp_read_lock_held == 0) 4433195918Srrs SCTP_INP_READ_UNLOCK(inp); 4434163953Srrs if (inp && inp->sctp_socket) { 4435169352Srrs if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_ZERO_COPY_ACTIVE)) { 4436169352Srrs SCTP_ZERO_COPY_EVENT(inp, inp->sctp_socket); 4437172090Srrs } else { 4438252882Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 4439172090Srrs struct socket *so; 4440172090Srrs 4441172090Srrs so = SCTP_INP_SO(inp); 4442172090Srrs if (!so_locked) { 4443231039Stuexen if (stcb) { 4444231039Stuexen atomic_add_int(&stcb->asoc.refcnt, 1); 4445231039Stuexen SCTP_TCB_UNLOCK(stcb); 4446231039Stuexen } 4447172090Srrs SCTP_SOCKET_LOCK(so, 1); 4448231039Stuexen if (stcb) { 4449231039Stuexen SCTP_TCB_LOCK(stcb); 4450231039Stuexen atomic_subtract_int(&stcb->asoc.refcnt, 1); 4451231039Stuexen } 4452172090Srrs if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) { 4453172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 4454172090Srrs return; 4455172090Srrs } 4456172090Srrs } 4457172090Srrs#endif 4458169352Srrs sctp_sorwakeup(inp, inp->sctp_socket); 4459252882Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 4460172090Srrs if (!so_locked) { 4461172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 4462172090Srrs } 4463172090Srrs#endif 4464172090Srrs } 4465163953Srrs } 4466163953Srrs} 4467163953Srrs 4468163953Srrs 4469163953Srrsint 4470163953Srrssctp_append_to_readq(struct sctp_inpcb *inp, 4471163953Srrs struct sctp_tcb *stcb, 4472163953Srrs struct sctp_queued_to_read *control, 4473163953Srrs struct mbuf *m, 4474163953Srrs int end, 4475163953Srrs int ctls_cumack, 4476163953Srrs struct sockbuf *sb) 4477163953Srrs{ 4478163953Srrs /* 4479163953Srrs * A partial delivery API event is underway. OR we are appending on 4480163953Srrs * the reassembly queue. 4481163953Srrs * 4482163953Srrs * If PDAPI this means we need to add m to the end of the data. 4483163953Srrs * Increase the length in the control AND increment the sb_cc. 4484163953Srrs * Otherwise sb is NULL and all we need to do is put it at the end 4485163953Srrs * of the mbuf chain. 4486163953Srrs */ 4487163953Srrs int len = 0; 4488163953Srrs struct mbuf *mm, *tail = NULL, *prev = NULL; 4489163953Srrs 4490163953Srrs if (inp) { 4491163953Srrs SCTP_INP_READ_LOCK(inp); 4492163953Srrs } 4493163953Srrs if (control == NULL) { 4494163953Srrsget_out: 4495163953Srrs if (inp) { 4496163953Srrs SCTP_INP_READ_UNLOCK(inp); 4497163953Srrs } 4498163953Srrs return (-1); 4499163953Srrs } 4500209289Stuexen if (inp && (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_CANT_READ)) { 4501209289Stuexen SCTP_INP_READ_UNLOCK(inp); 4502231039Stuexen return (0); 4503209289Stuexen } 4504165647Srrs if (control->end_added) { 4505163953Srrs /* huh this one is complete? */ 4506163953Srrs goto get_out; 4507163953Srrs } 4508163953Srrs mm = m; 4509163953Srrs if (mm == NULL) { 4510163953Srrs goto get_out; 4511163953Srrs } 4512163953Srrs while (mm) { 4513165647Srrs if (SCTP_BUF_LEN(mm) == 0) { 4514163953Srrs /* Skip mbufs with NO lenght */ 4515163953Srrs if (prev == NULL) { 4516163953Srrs /* First one */ 4517163953Srrs m = sctp_m_free(mm); 4518163953Srrs mm = m; 4519163953Srrs } else { 4520165647Srrs SCTP_BUF_NEXT(prev) = sctp_m_free(mm); 4521165647Srrs mm = SCTP_BUF_NEXT(prev); 4522163953Srrs } 4523163953Srrs continue; 4524163953Srrs } 4525163953Srrs prev = mm; 4526165647Srrs len += SCTP_BUF_LEN(mm); 4527163953Srrs if (sb) { 4528179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) { 4529170744Srrs sctp_sblog(sb, control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBALLOC, SCTP_BUF_LEN(mm)); 4530170744Srrs } 4531163953Srrs sctp_sballoc(stcb, sb, mm); 4532179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) { 4533170744Srrs sctp_sblog(sb, control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBRESULT, 0); 4534170744Srrs } 4535163953Srrs } 4536165647Srrs mm = SCTP_BUF_NEXT(mm); 4537163953Srrs } 4538163953Srrs if (prev) { 4539163953Srrs tail = prev; 4540163953Srrs } else { 4541163953Srrs /* Really there should always be a prev */ 4542163953Srrs if (m == NULL) { 4543163953Srrs /* Huh nothing left? */ 4544165220Srrs#ifdef INVARIANTS 4545163953Srrs panic("Nothing left to add?"); 4546163953Srrs#else 4547163953Srrs goto get_out; 4548163953Srrs#endif 4549163953Srrs } 4550163953Srrs tail = m; 4551163953Srrs } 4552163953Srrs if (control->tail_mbuf) { 4553163953Srrs /* append */ 4554165647Srrs SCTP_BUF_NEXT(control->tail_mbuf) = m; 4555163953Srrs control->tail_mbuf = tail; 4556163953Srrs } else { 4557163953Srrs /* nothing there */ 4558165220Srrs#ifdef INVARIANTS 4559163953Srrs if (control->data != NULL) { 4560163953Srrs panic("This should NOT happen"); 4561163953Srrs } 4562163953Srrs#endif 4563163953Srrs control->data = m; 4564163953Srrs control->tail_mbuf = tail; 4565163953Srrs } 4566171477Srrs atomic_add_int(&control->length, len); 4567171477Srrs if (end) { 4568171477Srrs /* message is complete */ 4569171477Srrs if (stcb && (control == stcb->asoc.control_pdapi)) { 4570171477Srrs stcb->asoc.control_pdapi = NULL; 4571171477Srrs } 4572171477Srrs control->held_length = 0; 4573171477Srrs control->end_added = 1; 4574171477Srrs } 4575169420Srrs if (stcb == NULL) { 4576169420Srrs control->do_not_ref_stcb = 1; 4577169420Srrs } 4578163953Srrs /* 4579163953Srrs * When we are appending in partial delivery, the cum-ack is used 4580163953Srrs * for the actual pd-api highest tsn on this mbuf. The true cum-ack 4581163953Srrs * is populated in the outbound sinfo structure from the true cumack 4582163953Srrs * if the association exists... 4583163953Srrs */ 4584163953Srrs control->sinfo_tsn = control->sinfo_cumtsn = ctls_cumack; 4585163953Srrs if (inp) { 4586163953Srrs SCTP_INP_READ_UNLOCK(inp); 4587163953Srrs } 4588163953Srrs if (inp && inp->sctp_socket) { 4589169352Srrs if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_ZERO_COPY_ACTIVE)) { 4590169352Srrs SCTP_ZERO_COPY_EVENT(inp, inp->sctp_socket); 4591172090Srrs } else { 4592252882Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 4593172090Srrs struct socket *so; 4594172090Srrs 4595172090Srrs so = SCTP_INP_SO(inp); 4596231039Stuexen if (stcb) { 4597231039Stuexen atomic_add_int(&stcb->asoc.refcnt, 1); 4598231039Stuexen SCTP_TCB_UNLOCK(stcb); 4599231039Stuexen } 4600172090Srrs SCTP_SOCKET_LOCK(so, 1); 4601231039Stuexen if (stcb) { 4602231039Stuexen SCTP_TCB_LOCK(stcb); 4603231039Stuexen atomic_subtract_int(&stcb->asoc.refcnt, 1); 4604231039Stuexen } 4605172090Srrs if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) { 4606172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 4607172090Srrs return (0); 4608172090Srrs } 4609172090Srrs#endif 4610169352Srrs sctp_sorwakeup(inp, inp->sctp_socket); 4611252882Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 4612172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 4613172090Srrs#endif 4614172090Srrs } 4615163953Srrs } 4616163953Srrs return (0); 4617163953Srrs} 4618163953Srrs 4619163953Srrs 4620163953Srrs 4621163953Srrs/*************HOLD THIS COMMENT FOR PATCH FILE OF 4622163953Srrs *************ALTERNATE ROUTING CODE 4623163953Srrs */ 4624163953Srrs 4625163953Srrs/*************HOLD THIS COMMENT FOR END OF PATCH FILE OF 4626163953Srrs *************ALTERNATE ROUTING CODE 4627163953Srrs */ 4628163953Srrs 4629163953Srrsstruct mbuf * 4630266181Stuexensctp_generate_cause(uint16_t code, char *info) 4631163953Srrs{ 4632163953Srrs struct mbuf *m; 4633266181Stuexen struct sctp_gen_error_cause *cause; 4634266181Stuexen size_t info_len, len; 4635163953Srrs 4636266181Stuexen if ((code == 0) || (info == NULL)) { 4637266181Stuexen return (NULL); 4638163953Srrs } 4639266181Stuexen info_len = strlen(info); 4640266181Stuexen len = sizeof(struct sctp_paramhdr) + info_len; 4641266181Stuexen m = sctp_get_mbuf_for_msg(len, 0, M_NOWAIT, 1, MT_DATA); 4642266181Stuexen if (m != NULL) { 4643266181Stuexen SCTP_BUF_LEN(m) = len; 4644266181Stuexen cause = mtod(m, struct sctp_gen_error_cause *); 4645266181Stuexen cause->code = htons(code); 4646266181Stuexen cause->length = htons((uint16_t) len); 4647266181Stuexen memcpy(cause->info, info, info_len); 4648266181Stuexen } 4649163953Srrs return (m); 4650163953Srrs} 4651163953Srrs 4652266186Stuexenstruct mbuf * 4653266186Stuexensctp_generate_no_user_data_cause(uint32_t tsn) 4654266186Stuexen{ 4655266186Stuexen struct mbuf *m; 4656266186Stuexen struct sctp_error_no_user_data *no_user_data_cause; 4657266186Stuexen size_t len; 4658266186Stuexen 4659266186Stuexen len = sizeof(struct sctp_error_no_user_data); 4660266186Stuexen m = sctp_get_mbuf_for_msg(len, 0, M_NOWAIT, 1, MT_DATA); 4661266186Stuexen if (m != NULL) { 4662266186Stuexen SCTP_BUF_LEN(m) = len; 4663266186Stuexen no_user_data_cause = mtod(m, struct sctp_error_no_user_data *); 4664266186Stuexen no_user_data_cause->cause.code = htons(SCTP_CAUSE_NO_USER_DATA); 4665266186Stuexen no_user_data_cause->cause.length = htons((uint16_t) len); 4666266186Stuexen no_user_data_cause->tsn = tsn; /* tsn is passed in as NBO */ 4667266186Stuexen } 4668266186Stuexen return (m); 4669266186Stuexen} 4670266186Stuexen 4671163953Srrs#ifdef SCTP_MBCNT_LOGGING 4672163953Srrsvoid 4673163953Srrssctp_free_bufspace(struct sctp_tcb *stcb, struct sctp_association *asoc, 4674163953Srrs struct sctp_tmit_chunk *tp1, int chk_cnt) 4675163953Srrs{ 4676163953Srrs if (tp1->data == NULL) { 4677163953Srrs return; 4678163953Srrs } 4679163953Srrs asoc->chunks_on_out_queue -= chk_cnt; 4680179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBCNT_LOGGING_ENABLE) { 4681170744Srrs sctp_log_mbcnt(SCTP_LOG_MBCNT_DECREASE, 4682170744Srrs asoc->total_output_queue_size, 4683170744Srrs tp1->book_size, 4684170744Srrs 0, 4685170744Srrs tp1->mbcnt); 4686170744Srrs } 4687163953Srrs if (asoc->total_output_queue_size >= tp1->book_size) { 4688166023Srrs atomic_add_int(&asoc->total_output_queue_size, -tp1->book_size); 4689163953Srrs } else { 4690163953Srrs asoc->total_output_queue_size = 0; 4691163953Srrs } 4692163953Srrs 4693163953Srrs if (stcb->sctp_socket && (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) || 4694163953Srrs ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE)))) { 4695163953Srrs if (stcb->sctp_socket->so_snd.sb_cc >= tp1->book_size) { 4696163953Srrs stcb->sctp_socket->so_snd.sb_cc -= tp1->book_size; 4697163953Srrs } else { 4698163953Srrs stcb->sctp_socket->so_snd.sb_cc = 0; 4699163953Srrs 4700163953Srrs } 4701163953Srrs } 4702163953Srrs} 4703163953Srrs 4704163953Srrs#endif 4705163953Srrs 4706163953Srrsint 4707163953Srrssctp_release_pr_sctp_chunk(struct sctp_tcb *stcb, struct sctp_tmit_chunk *tp1, 4708237889Stuexen uint8_t sent, int so_locked 4709172090Srrs#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING) 4710172090Srrs SCTP_UNUSED 4711172090Srrs#endif 4712172090Srrs) 4713163953Srrs{ 4714189790Srrs struct sctp_stream_out *strq; 4715216822Stuexen struct sctp_tmit_chunk *chk = NULL, *tp2; 4716189790Srrs struct sctp_stream_queue_pending *sp; 4717189790Srrs uint16_t stream = 0, seq = 0; 4718189790Srrs uint8_t foundeom = 0; 4719163953Srrs int ret_sz = 0; 4720163953Srrs int notdone; 4721189790Srrs int do_wakeup_routine = 0; 4722163953Srrs 4723189790Srrs stream = tp1->rec.data.stream_number; 4724189790Srrs seq = tp1->rec.data.stream_seq; 4725163953Srrs do { 4726163953Srrs ret_sz += tp1->book_size; 4727189790Srrs if (tp1->data != NULL) { 4728190689Srrs if (tp1->sent < SCTP_DATAGRAM_RESEND) { 4729190689Srrs sctp_flight_size_decrease(tp1); 4730190689Srrs sctp_total_flight_decrease(stcb, tp1); 4731190689Srrs } 4732163953Srrs sctp_free_bufspace(stcb, &stcb->asoc, tp1, 1); 4733189790Srrs stcb->asoc.peers_rwnd += tp1->send_size; 4734189790Srrs stcb->asoc.peers_rwnd += SCTP_BASE_SYSCTL(sctp_peer_chunk_oh); 4735237889Stuexen if (sent) { 4736237889Stuexen sctp_ulp_notify(SCTP_NOTIFY_SENT_DG_FAIL, stcb, 0, tp1, so_locked); 4737237889Stuexen } else { 4738237889Stuexen sctp_ulp_notify(SCTP_NOTIFY_UNSENT_DG_FAIL, stcb, 0, tp1, so_locked); 4739237889Stuexen } 4740196376Stuexen if (tp1->data) { 4741196376Stuexen sctp_m_freem(tp1->data); 4742196376Stuexen tp1->data = NULL; 4743196376Stuexen } 4744189790Srrs do_wakeup_routine = 1; 4745189790Srrs if (PR_SCTP_BUF_ENABLED(tp1->flags)) { 4746189790Srrs stcb->asoc.sent_queue_cnt_removeable--; 4747172090Srrs } 4748163953Srrs } 4749190689Srrs tp1->sent = SCTP_FORWARD_TSN_SKIP; 4750163953Srrs if ((tp1->rec.data.rcv_flags & SCTP_DATA_NOT_FRAG) == 4751163953Srrs SCTP_DATA_NOT_FRAG) { 4752163953Srrs /* not frag'ed we ae done */ 4753163953Srrs notdone = 0; 4754163953Srrs foundeom = 1; 4755163953Srrs } else if (tp1->rec.data.rcv_flags & SCTP_DATA_LAST_FRAG) { 4756163953Srrs /* end of frag, we are done */ 4757163953Srrs notdone = 0; 4758163953Srrs foundeom = 1; 4759163953Srrs } else { 4760163953Srrs /* 4761163953Srrs * Its a begin or middle piece, we must mark all of 4762163953Srrs * it 4763163953Srrs */ 4764163953Srrs notdone = 1; 4765163953Srrs tp1 = TAILQ_NEXT(tp1, sctp_next); 4766163953Srrs } 4767163953Srrs } while (tp1 && notdone); 4768189790Srrs if (foundeom == 0) { 4769163953Srrs /* 4770163953Srrs * The multi-part message was scattered across the send and 4771163953Srrs * sent queue. 4772163953Srrs */ 4773216822Stuexen TAILQ_FOREACH_SAFE(tp1, &stcb->asoc.send_queue, sctp_next, tp2) { 4774216822Stuexen if ((tp1->rec.data.stream_number != stream) || 4775216822Stuexen (tp1->rec.data.stream_seq != seq)) { 4776216822Stuexen break; 4777216822Stuexen } 4778189790Srrs /* 4779189790Srrs * save to chk in case we have some on stream out 4780189790Srrs * queue. If so and we have an un-transmitted one we 4781189790Srrs * don't have to fudge the TSN. 4782189790Srrs */ 4783189790Srrs chk = tp1; 4784189790Srrs ret_sz += tp1->book_size; 4785196376Stuexen sctp_free_bufspace(stcb, &stcb->asoc, tp1, 1); 4786237889Stuexen if (sent) { 4787237889Stuexen sctp_ulp_notify(SCTP_NOTIFY_SENT_DG_FAIL, stcb, 0, tp1, so_locked); 4788237889Stuexen } else { 4789237889Stuexen sctp_ulp_notify(SCTP_NOTIFY_UNSENT_DG_FAIL, stcb, 0, tp1, so_locked); 4790237889Stuexen } 4791196376Stuexen if (tp1->data) { 4792196376Stuexen sctp_m_freem(tp1->data); 4793196376Stuexen tp1->data = NULL; 4794196376Stuexen } 4795190689Srrs /* No flight involved here book the size to 0 */ 4796190689Srrs tp1->book_size = 0; 4797189790Srrs if (tp1->rec.data.rcv_flags & SCTP_DATA_LAST_FRAG) { 4798189790Srrs foundeom = 1; 4799189790Srrs } 4800189790Srrs do_wakeup_routine = 1; 4801189790Srrs tp1->sent = SCTP_FORWARD_TSN_SKIP; 4802189790Srrs TAILQ_REMOVE(&stcb->asoc.send_queue, tp1, sctp_next); 4803189790Srrs /* 4804189790Srrs * on to the sent queue so we can wait for it to be 4805189790Srrs * passed by. 4806189790Srrs */ 4807189790Srrs TAILQ_INSERT_TAIL(&stcb->asoc.sent_queue, tp1, 4808189790Srrs sctp_next); 4809189790Srrs stcb->asoc.send_queue_cnt--; 4810189790Srrs stcb->asoc.sent_queue_cnt++; 4811163953Srrs } 4812163953Srrs } 4813189790Srrs if (foundeom == 0) { 4814189790Srrs /* 4815189790Srrs * Still no eom found. That means there is stuff left on the 4816189790Srrs * stream out queue.. yuck. 4817189790Srrs */ 4818252940Stuexen SCTP_TCB_SEND_LOCK(stcb); 4819189790Srrs strq = &stcb->asoc.strmout[stream]; 4820252940Stuexen sp = TAILQ_FIRST(&strq->outqueue); 4821252940Stuexen if (sp != NULL) { 4822252940Stuexen sp->discard_rest = 1; 4823252940Stuexen /* 4824252940Stuexen * We may need to put a chunk on the queue that 4825252940Stuexen * holds the TSN that would have been sent with the 4826252940Stuexen * LAST bit. 4827252940Stuexen */ 4828252940Stuexen if (chk == NULL) { 4829252940Stuexen /* Yep, we have to */ 4830252940Stuexen sctp_alloc_a_chunk(stcb, chk); 4831189790Srrs if (chk == NULL) { 4832189790Srrs /* 4833252940Stuexen * we are hosed. All we can do is 4834252940Stuexen * nothing.. which will cause an 4835252940Stuexen * abort if the peer is paying 4836252940Stuexen * attention. 4837189790Srrs */ 4838252940Stuexen goto oh_well; 4839189790Srrs } 4840252940Stuexen memset(chk, 0, sizeof(*chk)); 4841252940Stuexen chk->rec.data.rcv_flags = SCTP_DATA_LAST_FRAG; 4842252940Stuexen chk->sent = SCTP_FORWARD_TSN_SKIP; 4843252940Stuexen chk->asoc = &stcb->asoc; 4844252940Stuexen chk->rec.data.stream_seq = strq->next_sequence_send; 4845252940Stuexen chk->rec.data.stream_number = sp->stream; 4846252940Stuexen chk->rec.data.payloadtype = sp->ppid; 4847252940Stuexen chk->rec.data.context = sp->context; 4848252940Stuexen chk->flags = sp->act_flags; 4849252940Stuexen if (sp->net) 4850252940Stuexen chk->whoTo = sp->net; 4851252940Stuexen else 4852252940Stuexen chk->whoTo = stcb->asoc.primary_destination; 4853252940Stuexen atomic_add_int(&chk->whoTo->ref_count, 1); 4854252940Stuexen chk->rec.data.TSN_seq = atomic_fetchadd_int(&stcb->asoc.sending_seq, 1); 4855252940Stuexen stcb->asoc.pr_sctp_cnt++; 4856252940Stuexen TAILQ_INSERT_TAIL(&stcb->asoc.sent_queue, chk, sctp_next); 4857252940Stuexen stcb->asoc.sent_queue_cnt++; 4858252940Stuexen stcb->asoc.pr_sctp_cnt++; 4859252940Stuexen } else { 4860252940Stuexen chk->rec.data.rcv_flags |= SCTP_DATA_LAST_FRAG; 4861189790Srrs } 4862252940Stuexen strq->next_sequence_send++; 4863252940Stuexen oh_well: 4864252940Stuexen if (sp->data) { 4865252940Stuexen /* 4866252940Stuexen * Pull any data to free up the SB and allow 4867252940Stuexen * sender to "add more" while we will throw 4868252940Stuexen * away :-) 4869252940Stuexen */ 4870252940Stuexen sctp_free_spbufspace(stcb, &stcb->asoc, sp); 4871252940Stuexen ret_sz += sp->length; 4872252940Stuexen do_wakeup_routine = 1; 4873252940Stuexen sp->some_taken = 1; 4874252940Stuexen sctp_m_freem(sp->data); 4875252940Stuexen sp->data = NULL; 4876252940Stuexen sp->tail_mbuf = NULL; 4877252940Stuexen sp->length = 0; 4878252940Stuexen } 4879252940Stuexen } 4880189790Srrs SCTP_TCB_SEND_UNLOCK(stcb); 4881189790Srrs } 4882189790Srrs if (do_wakeup_routine) { 4883252882Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 4884190689Srrs struct socket *so; 4885190689Srrs 4886189790Srrs so = SCTP_INP_SO(stcb->sctp_ep); 4887189790Srrs if (!so_locked) { 4888189790Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 4889189790Srrs SCTP_TCB_UNLOCK(stcb); 4890189790Srrs SCTP_SOCKET_LOCK(so, 1); 4891189790Srrs SCTP_TCB_LOCK(stcb); 4892189790Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 4893189790Srrs if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) { 4894189790Srrs /* assoc was freed while we were unlocked */ 4895189790Srrs SCTP_SOCKET_UNLOCK(so, 1); 4896189790Srrs return (ret_sz); 4897189790Srrs } 4898189790Srrs } 4899189790Srrs#endif 4900189790Srrs sctp_sowwakeup(stcb->sctp_ep, stcb->sctp_socket); 4901252882Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 4902189790Srrs if (!so_locked) { 4903189790Srrs SCTP_SOCKET_UNLOCK(so, 1); 4904189790Srrs } 4905189790Srrs#endif 4906189790Srrs } 4907163953Srrs return (ret_sz); 4908163953Srrs} 4909163953Srrs 4910163953Srrs/* 4911163953Srrs * checks to see if the given address, sa, is one that is currently known by 4912163953Srrs * the kernel note: can't distinguish the same address on multiple interfaces 4913163953Srrs * and doesn't handle multiple addresses with different zone/scope id's note: 4914163953Srrs * ifa_ifwithaddr() compares the entire sockaddr struct 4915163953Srrs */ 4916167598Srrsstruct sctp_ifa * 4917170744Srrssctp_find_ifa_in_ep(struct sctp_inpcb *inp, struct sockaddr *addr, 4918170744Srrs int holds_lock) 4919163953Srrs{ 4920167598Srrs struct sctp_laddr *laddr; 4921163953Srrs 4922169420Srrs if (holds_lock == 0) { 4923167598Srrs SCTP_INP_RLOCK(inp); 4924169420Srrs } 4925167598Srrs LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) { 4926167598Srrs if (laddr->ifa == NULL) 4927167598Srrs continue; 4928167598Srrs if (addr->sa_family != laddr->ifa->address.sa.sa_family) 4929167598Srrs continue; 4930221249Stuexen#ifdef INET 4931167598Srrs if (addr->sa_family == AF_INET) { 4932167598Srrs if (((struct sockaddr_in *)addr)->sin_addr.s_addr == 4933167598Srrs laddr->ifa->address.sin.sin_addr.s_addr) { 4934167598Srrs /* found him. */ 4935169420Srrs if (holds_lock == 0) { 4936167598Srrs SCTP_INP_RUNLOCK(inp); 4937169420Srrs } 4938167598Srrs return (laddr->ifa); 4939167598Srrs break; 4940167598Srrs } 4941178251Srrs } 4942221249Stuexen#endif 4943178251Srrs#ifdef INET6 4944178251Srrs if (addr->sa_family == AF_INET6) { 4945179157Srrs if (SCTP6_ARE_ADDR_EQUAL((struct sockaddr_in6 *)addr, 4946179157Srrs &laddr->ifa->address.sin6)) { 4947167598Srrs /* found him. */ 4948169420Srrs if (holds_lock == 0) { 4949167598Srrs SCTP_INP_RUNLOCK(inp); 4950169420Srrs } 4951167598Srrs return (laddr->ifa); 4952167598Srrs break; 4953167598Srrs } 4954167598Srrs } 4955178251Srrs#endif 4956167598Srrs } 4957169420Srrs if (holds_lock == 0) { 4958167598Srrs SCTP_INP_RUNLOCK(inp); 4959169420Srrs } 4960167598Srrs return (NULL); 4961167598Srrs} 4962163953Srrs 4963167698Srrsuint32_t 4964167698Srrssctp_get_ifa_hash_val(struct sockaddr *addr) 4965167698Srrs{ 4966221328Stuexen switch (addr->sa_family) { 4967221328Stuexen#ifdef INET 4968221328Stuexen case AF_INET: 4969221328Stuexen { 4970221328Stuexen struct sockaddr_in *sin; 4971167698Srrs 4972221328Stuexen sin = (struct sockaddr_in *)addr; 4973221328Stuexen return (sin->sin_addr.s_addr ^ (sin->sin_addr.s_addr >> 16)); 4974221328Stuexen } 4975221328Stuexen#endif 4976221328Stuexen#ifdef INET6 4977252957Stuexen case AF_INET6: 4978221328Stuexen { 4979221328Stuexen struct sockaddr_in6 *sin6; 4980221328Stuexen uint32_t hash_of_addr; 4981167698Srrs 4982221328Stuexen sin6 = (struct sockaddr_in6 *)addr; 4983221328Stuexen hash_of_addr = (sin6->sin6_addr.s6_addr32[0] + 4984221328Stuexen sin6->sin6_addr.s6_addr32[1] + 4985221328Stuexen sin6->sin6_addr.s6_addr32[2] + 4986221328Stuexen sin6->sin6_addr.s6_addr32[3]); 4987221328Stuexen hash_of_addr = (hash_of_addr ^ (hash_of_addr >> 16)); 4988221328Stuexen return (hash_of_addr); 4989221328Stuexen } 4990221328Stuexen#endif 4991221328Stuexen default: 4992221328Stuexen break; 4993167698Srrs } 4994167698Srrs return (0); 4995167698Srrs} 4996167698Srrs 4997167598Srrsstruct sctp_ifa * 4998167598Srrssctp_find_ifa_by_addr(struct sockaddr *addr, uint32_t vrf_id, int holds_lock) 4999167598Srrs{ 5000167598Srrs struct sctp_ifa *sctp_ifap; 5001167598Srrs struct sctp_vrf *vrf; 5002167698Srrs struct sctp_ifalist *hash_head; 5003167698Srrs uint32_t hash_of_addr; 5004167598Srrs 5005168299Srrs if (holds_lock == 0) 5006172218Srrs SCTP_IPI_ADDR_RLOCK(); 5007168299Srrs 5008167598Srrs vrf = sctp_find_vrf(vrf_id); 5009168299Srrs if (vrf == NULL) { 5010182367Srrsstage_right: 5011168299Srrs if (holds_lock == 0) 5012172218Srrs SCTP_IPI_ADDR_RUNLOCK(); 5013167598Srrs return (NULL); 5014168299Srrs } 5015167698Srrs hash_of_addr = sctp_get_ifa_hash_val(addr); 5016167598Srrs 5017169352Srrs hash_head = &vrf->vrf_addr_hash[(hash_of_addr & vrf->vrf_addr_hashmark)]; 5018168299Srrs if (hash_head == NULL) { 5019169420Srrs SCTP_PRINTF("hash_of_addr:%x mask:%x table:%x - ", 5020172218Srrs hash_of_addr, (uint32_t) vrf->vrf_addr_hashmark, 5021172218Srrs (uint32_t) (hash_of_addr & vrf->vrf_addr_hashmark)); 5022168299Srrs sctp_print_address(addr); 5023169420Srrs SCTP_PRINTF("No such bucket for address\n"); 5024168299Srrs if (holds_lock == 0) 5025172218Srrs SCTP_IPI_ADDR_RUNLOCK(); 5026168299Srrs 5027168299Srrs return (NULL); 5028168299Srrs } 5029167698Srrs LIST_FOREACH(sctp_ifap, hash_head, next_bucket) { 5030168299Srrs if (sctp_ifap == NULL) { 5031182367Srrs#ifdef INVARIANTS 5032168299Srrs panic("Huh LIST_FOREACH corrupt"); 5033182367Srrs goto stage_right; 5034182367Srrs#else 5035182367Srrs SCTP_PRINTF("LIST corrupt of sctp_ifap's?\n"); 5036182367Srrs goto stage_right; 5037182367Srrs#endif 5038168299Srrs } 5039167698Srrs if (addr->sa_family != sctp_ifap->address.sa.sa_family) 5040167698Srrs continue; 5041221249Stuexen#ifdef INET 5042167698Srrs if (addr->sa_family == AF_INET) { 5043167698Srrs if (((struct sockaddr_in *)addr)->sin_addr.s_addr == 5044167698Srrs sctp_ifap->address.sin.sin_addr.s_addr) { 5045167698Srrs /* found him. */ 5046167698Srrs if (holds_lock == 0) 5047172218Srrs SCTP_IPI_ADDR_RUNLOCK(); 5048167698Srrs return (sctp_ifap); 5049167698Srrs break; 5050167698Srrs } 5051178251Srrs } 5052221249Stuexen#endif 5053178251Srrs#ifdef INET6 5054178251Srrs if (addr->sa_family == AF_INET6) { 5055179157Srrs if (SCTP6_ARE_ADDR_EQUAL((struct sockaddr_in6 *)addr, 5056179157Srrs &sctp_ifap->address.sin6)) { 5057167698Srrs /* found him. */ 5058167698Srrs if (holds_lock == 0) 5059172218Srrs SCTP_IPI_ADDR_RUNLOCK(); 5060167698Srrs return (sctp_ifap); 5061167698Srrs break; 5062167698Srrs } 5063167598Srrs } 5064178251Srrs#endif 5065167598Srrs } 5066167598Srrs if (holds_lock == 0) 5067172218Srrs SCTP_IPI_ADDR_RUNLOCK(); 5068167598Srrs return (NULL); 5069167598Srrs} 5070167598Srrs 5071163953Srrsstatic void 5072170140Srrssctp_user_rcvd(struct sctp_tcb *stcb, uint32_t * freed_so_far, int hold_rlock, 5073163953Srrs uint32_t rwnd_req) 5074163953Srrs{ 5075163953Srrs /* User pulled some data, do we need a rwnd update? */ 5076163953Srrs int r_unlocked = 0; 5077163953Srrs uint32_t dif, rwnd; 5078163953Srrs struct socket *so = NULL; 5079163953Srrs 5080163953Srrs if (stcb == NULL) 5081163953Srrs return; 5082163953Srrs 5083163996Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 5084163953Srrs 5085167736Srrs if (stcb->asoc.state & (SCTP_STATE_ABOUT_TO_BE_FREED | 5086167736Srrs SCTP_STATE_SHUTDOWN_RECEIVED | 5087170140Srrs SCTP_STATE_SHUTDOWN_ACK_SENT)) { 5088163953Srrs /* Pre-check If we are freeing no update */ 5089163953Srrs goto no_lock; 5090163953Srrs } 5091163953Srrs SCTP_INP_INCR_REF(stcb->sctp_ep); 5092163953Srrs if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) || 5093163953Srrs (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE)) { 5094163953Srrs goto out; 5095163953Srrs } 5096163953Srrs so = stcb->sctp_socket; 5097163953Srrs if (so == NULL) { 5098163953Srrs goto out; 5099163953Srrs } 5100163953Srrs atomic_add_int(&stcb->freed_by_sorcv_sincelast, *freed_so_far); 5101163953Srrs /* Have you have freed enough to look */ 5102163953Srrs *freed_so_far = 0; 5103163953Srrs /* Yep, its worth a look and the lock overhead */ 5104163953Srrs 5105163953Srrs /* Figure out what the rwnd would be */ 5106163953Srrs rwnd = sctp_calc_rwnd(stcb, &stcb->asoc); 5107163953Srrs if (rwnd >= stcb->asoc.my_last_reported_rwnd) { 5108163953Srrs dif = rwnd - stcb->asoc.my_last_reported_rwnd; 5109163953Srrs } else { 5110163953Srrs dif = 0; 5111163953Srrs } 5112163953Srrs if (dif >= rwnd_req) { 5113163953Srrs if (hold_rlock) { 5114163953Srrs SCTP_INP_READ_UNLOCK(stcb->sctp_ep); 5115163953Srrs r_unlocked = 1; 5116163953Srrs } 5117163953Srrs if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) { 5118163953Srrs /* 5119163953Srrs * One last check before we allow the guy possibly 5120163953Srrs * to get in. There is a race, where the guy has not 5121163953Srrs * reached the gate. In that case 5122163953Srrs */ 5123163953Srrs goto out; 5124163953Srrs } 5125163953Srrs SCTP_TCB_LOCK(stcb); 5126163953Srrs if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) { 5127163953Srrs /* No reports here */ 5128163953Srrs SCTP_TCB_UNLOCK(stcb); 5129163953Srrs goto out; 5130163953Srrs } 5131163953Srrs SCTP_STAT_INCR(sctps_wu_sacks_sent); 5132221627Stuexen sctp_send_sack(stcb, SCTP_SO_LOCKED); 5133185694Srrs 5134163953Srrs sctp_chunk_output(stcb->sctp_ep, stcb, 5135172090Srrs SCTP_OUTPUT_FROM_USR_RCVD, SCTP_SO_LOCKED); 5136163953Srrs /* make sure no timer is running */ 5137165220Srrs sctp_timer_stop(SCTP_TIMER_TYPE_RECV, stcb->sctp_ep, stcb, NULL, SCTP_FROM_SCTPUTIL + SCTP_LOC_6); 5138163953Srrs SCTP_TCB_UNLOCK(stcb); 5139163953Srrs } else { 5140163953Srrs /* Update how much we have pending */ 5141163953Srrs stcb->freed_by_sorcv_sincelast = dif; 5142163953Srrs } 5143163953Srrsout: 5144163953Srrs if (so && r_unlocked && hold_rlock) { 5145163953Srrs SCTP_INP_READ_LOCK(stcb->sctp_ep); 5146163953Srrs } 5147163953Srrs SCTP_INP_DECR_REF(stcb->sctp_ep); 5148163953Srrsno_lock: 5149163996Srrs atomic_add_int(&stcb->asoc.refcnt, -1); 5150163953Srrs return; 5151163953Srrs} 5152163953Srrs 5153163953Srrsint 5154163953Srrssctp_sorecvmsg(struct socket *so, 5155163953Srrs struct uio *uio, 5156163953Srrs struct mbuf **mp, 5157163953Srrs struct sockaddr *from, 5158163953Srrs int fromlen, 5159163953Srrs int *msg_flags, 5160163953Srrs struct sctp_sndrcvinfo *sinfo, 5161163953Srrs int filling_sinfo) 5162163953Srrs{ 5163163953Srrs /* 5164163953Srrs * MSG flags we will look at MSG_DONTWAIT - non-blocking IO. 5165163953Srrs * MSG_PEEK - Look don't touch :-D (only valid with OUT mbuf copy 5166163953Srrs * mp=NULL thus uio is the copy method to userland) MSG_WAITALL - ?? 5167163953Srrs * On the way out we may send out any combination of: 5168163953Srrs * MSG_NOTIFICATION MSG_EOR 5169163953Srrs * 5170163953Srrs */ 5171163953Srrs struct sctp_inpcb *inp = NULL; 5172163953Srrs int my_len = 0; 5173163953Srrs int cp_len = 0, error = 0; 5174163953Srrs struct sctp_queued_to_read *control = NULL, *ctl = NULL, *nxt = NULL; 5175212713Stuexen struct mbuf *m = NULL; 5176163953Srrs struct sctp_tcb *stcb = NULL; 5177163953Srrs int wakeup_read_socket = 0; 5178163953Srrs int freecnt_applied = 0; 5179163953Srrs int out_flags = 0, in_flags = 0; 5180163953Srrs int block_allowed = 1; 5181170140Srrs uint32_t freed_so_far = 0; 5182173509Srrs uint32_t copied_so_far = 0; 5183166086Srrs int in_eeor_mode = 0; 5184163953Srrs int no_rcv_needed = 0; 5185163953Srrs uint32_t rwnd_req = 0; 5186163953Srrs int hold_sblock = 0; 5187163953Srrs int hold_rlock = 0; 5188167598Srrs int slen = 0; 5189170140Srrs uint32_t held_length = 0; 5190169236Srwatson int sockbuf_lock = 0; 5191163953Srrs 5192169352Srrs if (uio == NULL) { 5193171943Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL); 5194169352Srrs return (EINVAL); 5195169352Srrs } 5196163953Srrs if (msg_flags) { 5197163953Srrs in_flags = *msg_flags; 5198168709Srrs if (in_flags & MSG_PEEK) 5199168709Srrs SCTP_STAT_INCR(sctps_read_peeks); 5200163953Srrs } else { 5201163953Srrs in_flags = 0; 5202163953Srrs } 5203169352Srrs slen = uio->uio_resid; 5204169352Srrs 5205163953Srrs /* Pull in and set up our int flags */ 5206163953Srrs if (in_flags & MSG_OOB) { 5207163953Srrs /* Out of band's NOT supported */ 5208163953Srrs return (EOPNOTSUPP); 5209163953Srrs } 5210163953Srrs if ((in_flags & MSG_PEEK) && (mp != NULL)) { 5211171943Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL); 5212163953Srrs return (EINVAL); 5213163953Srrs } 5214163953Srrs if ((in_flags & (MSG_DONTWAIT 5215163953Srrs | MSG_NBIO 5216163953Srrs )) || 5217167598Srrs SCTP_SO_IS_NBIO(so)) { 5218163953Srrs block_allowed = 0; 5219163953Srrs } 5220163953Srrs /* setup the endpoint */ 5221163953Srrs inp = (struct sctp_inpcb *)so->so_pcb; 5222163953Srrs if (inp == NULL) { 5223171943Srrs SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTPUTIL, EFAULT); 5224163953Srrs return (EFAULT); 5225163953Srrs } 5226167736Srrs rwnd_req = (SCTP_SB_LIMIT_RCV(so) >> SCTP_RWND_HIWAT_SHIFT); 5227163953Srrs /* Must be at least a MTU's worth */ 5228163953Srrs if (rwnd_req < SCTP_MIN_RWND) 5229163953Srrs rwnd_req = SCTP_MIN_RWND; 5230163953Srrs in_eeor_mode = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXPLICIT_EOR); 5231179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_RECV_RWND_LOGGING_ENABLE) { 5232170744Srrs sctp_misc_ints(SCTP_SORECV_ENTER, 5233170744Srrs rwnd_req, in_eeor_mode, so->so_rcv.sb_cc, uio->uio_resid); 5234170744Srrs } 5235179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_RECV_RWND_LOGGING_ENABLE) { 5236170744Srrs sctp_misc_ints(SCTP_SORECV_ENTERPL, 5237170744Srrs rwnd_req, block_allowed, so->so_rcv.sb_cc, uio->uio_resid); 5238170744Srrs } 5239175845Srwatson error = sblock(&so->so_rcv, (block_allowed ? SBL_WAIT : 0)); 5240163953Srrs if (error) { 5241163953Srrs goto release_unlocked; 5242163953Srrs } 5243242836Smjg sockbuf_lock = 1; 5244163953Srrsrestart: 5245163953Srrs 5246169236Srwatson 5247163953Srrsrestart_nosblocks: 5248163953Srrs if (hold_sblock == 0) { 5249163953Srrs SOCKBUF_LOCK(&so->so_rcv); 5250163953Srrs hold_sblock = 1; 5251163953Srrs } 5252163953Srrs if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) || 5253163953Srrs (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE)) { 5254163953Srrs goto out; 5255163953Srrs } 5256237885Stuexen if ((so->so_rcv.sb_state & SBS_CANTRCVMORE) && (so->so_rcv.sb_cc == 0)) { 5257163953Srrs if (so->so_error) { 5258163953Srrs error = so->so_error; 5259166023Srrs if ((in_flags & MSG_PEEK) == 0) 5260166023Srrs so->so_error = 0; 5261174257Srrs goto out; 5262163953Srrs } else { 5263174257Srrs if (so->so_rcv.sb_cc == 0) { 5264174257Srrs /* indicate EOF */ 5265174257Srrs error = 0; 5266174257Srrs goto out; 5267174257Srrs } 5268163953Srrs } 5269163953Srrs } 5270163953Srrs if ((so->so_rcv.sb_cc <= held_length) && block_allowed) { 5271163953Srrs /* we need to wait for data */ 5272163953Srrs if ((so->so_rcv.sb_cc == 0) && 5273163953Srrs ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 5274163953Srrs (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL))) { 5275163953Srrs if ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0) { 5276163953Srrs /* 5277163953Srrs * For active open side clear flags for 5278163953Srrs * re-use passive open is blocked by 5279163953Srrs * connect. 5280163953Srrs */ 5281163953Srrs if (inp->sctp_flags & SCTP_PCB_FLAGS_WAS_ABORTED) { 5282163953Srrs /* 5283163953Srrs * You were aborted, passive side 5284163953Srrs * always hits here 5285163953Srrs */ 5286171943Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, ECONNRESET); 5287163953Srrs error = ECONNRESET; 5288163953Srrs } 5289163953Srrs so->so_state &= ~(SS_ISCONNECTING | 5290163953Srrs SS_ISDISCONNECTING | 5291163953Srrs SS_ISCONFIRMING | 5292163953Srrs SS_ISCONNECTED); 5293163953Srrs if (error == 0) { 5294163953Srrs if ((inp->sctp_flags & SCTP_PCB_FLAGS_WAS_CONNECTED) == 0) { 5295171943Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, ENOTCONN); 5296163953Srrs error = ENOTCONN; 5297163953Srrs } 5298163953Srrs } 5299163953Srrs goto out; 5300163953Srrs } 5301163953Srrs } 5302163953Srrs error = sbwait(&so->so_rcv); 5303163953Srrs if (error) { 5304163953Srrs goto out; 5305163953Srrs } 5306163953Srrs held_length = 0; 5307163953Srrs goto restart_nosblocks; 5308163953Srrs } else if (so->so_rcv.sb_cc == 0) { 5309166023Srrs if (so->so_error) { 5310166023Srrs error = so->so_error; 5311166023Srrs if ((in_flags & MSG_PEEK) == 0) 5312166023Srrs so->so_error = 0; 5313166023Srrs } else { 5314166023Srrs if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 5315166023Srrs (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) { 5316166023Srrs if ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0) { 5317166023Srrs /* 5318166023Srrs * For active open side clear flags 5319166023Srrs * for re-use passive open is 5320166023Srrs * blocked by connect. 5321166023Srrs */ 5322166023Srrs if (inp->sctp_flags & SCTP_PCB_FLAGS_WAS_ABORTED) { 5323166023Srrs /* 5324166023Srrs * You were aborted, passive 5325166023Srrs * side always hits here 5326166023Srrs */ 5327171943Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, ECONNRESET); 5328166023Srrs error = ECONNRESET; 5329166023Srrs } 5330166023Srrs so->so_state &= ~(SS_ISCONNECTING | 5331166023Srrs SS_ISDISCONNECTING | 5332166023Srrs SS_ISCONFIRMING | 5333166023Srrs SS_ISCONNECTED); 5334166023Srrs if (error == 0) { 5335166023Srrs if ((inp->sctp_flags & SCTP_PCB_FLAGS_WAS_CONNECTED) == 0) { 5336171943Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, ENOTCONN); 5337166023Srrs error = ENOTCONN; 5338166023Srrs } 5339166023Srrs } 5340166023Srrs goto out; 5341166023Srrs } 5342166023Srrs } 5343171943Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EWOULDBLOCK); 5344166023Srrs error = EWOULDBLOCK; 5345166023Srrs } 5346163953Srrs goto out; 5347163953Srrs } 5348169208Srrs if (hold_sblock == 1) { 5349169208Srrs SOCKBUF_UNLOCK(&so->so_rcv); 5350169208Srrs hold_sblock = 0; 5351169208Srrs } 5352163953Srrs /* we possibly have data we can read */ 5353169655Srrs /* sa_ignore FREED_MEMORY */ 5354163953Srrs control = TAILQ_FIRST(&inp->read_queue); 5355163953Srrs if (control == NULL) { 5356163953Srrs /* 5357163953Srrs * This could be happening since the appender did the 5358163953Srrs * increment but as not yet did the tailq insert onto the 5359163953Srrs * read_queue 5360163953Srrs */ 5361163953Srrs if (hold_rlock == 0) { 5362163953Srrs SCTP_INP_READ_LOCK(inp); 5363163953Srrs } 5364163953Srrs control = TAILQ_FIRST(&inp->read_queue); 5365163953Srrs if ((control == NULL) && (so->so_rcv.sb_cc != 0)) { 5366165220Srrs#ifdef INVARIANTS 5367163953Srrs panic("Huh, its non zero and nothing on control?"); 5368163953Srrs#endif 5369163953Srrs so->so_rcv.sb_cc = 0; 5370163953Srrs } 5371163953Srrs SCTP_INP_READ_UNLOCK(inp); 5372163953Srrs hold_rlock = 0; 5373163953Srrs goto restart; 5374163953Srrs } 5375163953Srrs if ((control->length == 0) && 5376163953Srrs (control->do_not_ref_stcb)) { 5377163953Srrs /* 5378163953Srrs * Clean up code for freeing assoc that left behind a 5379163953Srrs * pdapi.. maybe a peer in EEOR that just closed after 5380163953Srrs * sending and never indicated a EOR. 5381163953Srrs */ 5382163953Srrs if (hold_rlock == 0) { 5383163953Srrs hold_rlock = 1; 5384163953Srrs SCTP_INP_READ_LOCK(inp); 5385163953Srrs } 5386163953Srrs control->held_length = 0; 5387163953Srrs if (control->data) { 5388163953Srrs /* Hmm there is data here .. fix */ 5389170140Srrs struct mbuf *m_tmp; 5390163953Srrs int cnt = 0; 5391163953Srrs 5392170140Srrs m_tmp = control->data; 5393170140Srrs while (m_tmp) { 5394170140Srrs cnt += SCTP_BUF_LEN(m_tmp); 5395170140Srrs if (SCTP_BUF_NEXT(m_tmp) == NULL) { 5396170140Srrs control->tail_mbuf = m_tmp; 5397163953Srrs control->end_added = 1; 5398163953Srrs } 5399170140Srrs m_tmp = SCTP_BUF_NEXT(m_tmp); 5400163953Srrs } 5401163953Srrs control->length = cnt; 5402163953Srrs } else { 5403163953Srrs /* remove it */ 5404163953Srrs TAILQ_REMOVE(&inp->read_queue, control, next); 5405163953Srrs /* Add back any hiddend data */ 5406163953Srrs sctp_free_remote_addr(control->whoFrom); 5407163953Srrs sctp_free_a_readq(stcb, control); 5408163953Srrs } 5409163953Srrs if (hold_rlock) { 5410163953Srrs hold_rlock = 0; 5411163953Srrs SCTP_INP_READ_UNLOCK(inp); 5412163953Srrs } 5413163953Srrs goto restart; 5414163953Srrs } 5415196260Stuexen if ((control->length == 0) && 5416196260Stuexen (control->end_added == 1)) { 5417196260Stuexen /* 5418196260Stuexen * Do we also need to check for (control->pdapi_aborted == 5419196260Stuexen * 1)? 5420196260Stuexen */ 5421196260Stuexen if (hold_rlock == 0) { 5422196260Stuexen hold_rlock = 1; 5423196260Stuexen SCTP_INP_READ_LOCK(inp); 5424196260Stuexen } 5425196260Stuexen TAILQ_REMOVE(&inp->read_queue, control, next); 5426196260Stuexen if (control->data) { 5427196260Stuexen#ifdef INVARIANTS 5428196260Stuexen panic("control->data not null but control->length == 0"); 5429196260Stuexen#else 5430196260Stuexen SCTP_PRINTF("Strange, data left in the control buffer. Cleaning up.\n"); 5431196260Stuexen sctp_m_freem(control->data); 5432196260Stuexen control->data = NULL; 5433196260Stuexen#endif 5434196260Stuexen } 5435196260Stuexen if (control->aux_data) { 5436196260Stuexen sctp_m_free(control->aux_data); 5437196260Stuexen control->aux_data = NULL; 5438196260Stuexen } 5439196260Stuexen sctp_free_remote_addr(control->whoFrom); 5440196260Stuexen sctp_free_a_readq(stcb, control); 5441196260Stuexen if (hold_rlock) { 5442196260Stuexen hold_rlock = 0; 5443196260Stuexen SCTP_INP_READ_UNLOCK(inp); 5444196260Stuexen } 5445196260Stuexen goto restart; 5446196260Stuexen } 5447163953Srrs if (control->length == 0) { 5448163953Srrs if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE)) && 5449163953Srrs (filling_sinfo)) { 5450163953Srrs /* find a more suitable one then this */ 5451163953Srrs ctl = TAILQ_NEXT(control, next); 5452163953Srrs while (ctl) { 5453168943Srrs if ((ctl->stcb != control->stcb) && (ctl->length) && 5454168943Srrs (ctl->some_taken || 5455169352Srrs (ctl->spec_flags & M_NOTIFICATION) || 5456168943Srrs ((ctl->do_not_ref_stcb == 0) && 5457168943Srrs (ctl->stcb->asoc.strmin[ctl->sinfo_stream].delivery_started == 0))) 5458168943Srrs ) { 5459168943Srrs /*- 5460168943Srrs * If we have a different TCB next, and there is data 5461168943Srrs * present. If we have already taken some (pdapi), OR we can 5462168943Srrs * ref the tcb and no delivery as started on this stream, we 5463169352Srrs * take it. Note we allow a notification on a different 5464169352Srrs * assoc to be delivered.. 5465168943Srrs */ 5466163953Srrs control = ctl; 5467163953Srrs goto found_one; 5468168943Srrs } else if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS)) && 5469168943Srrs (ctl->length) && 5470168943Srrs ((ctl->some_taken) || 5471168943Srrs ((ctl->do_not_ref_stcb == 0) && 5472169352Srrs ((ctl->spec_flags & M_NOTIFICATION) == 0) && 5473206137Stuexen (ctl->stcb->asoc.strmin[ctl->sinfo_stream].delivery_started == 0)))) { 5474168943Srrs /*- 5475168943Srrs * If we have the same tcb, and there is data present, and we 5476168943Srrs * have the strm interleave feature present. Then if we have 5477168943Srrs * taken some (pdapi) or we can refer to tht tcb AND we have 5478168943Srrs * not started a delivery for this stream, we can take it. 5479169352Srrs * Note we do NOT allow a notificaiton on the same assoc to 5480169352Srrs * be delivered. 5481168943Srrs */ 5482168943Srrs control = ctl; 5483168943Srrs goto found_one; 5484163953Srrs } 5485163953Srrs ctl = TAILQ_NEXT(ctl, next); 5486163953Srrs } 5487163953Srrs } 5488163953Srrs /* 5489163953Srrs * if we reach here, not suitable replacement is available 5490163953Srrs * <or> fragment interleave is NOT on. So stuff the sb_cc 5491163953Srrs * into the our held count, and its time to sleep again. 5492163953Srrs */ 5493163953Srrs held_length = so->so_rcv.sb_cc; 5494163953Srrs control->held_length = so->so_rcv.sb_cc; 5495163953Srrs goto restart; 5496163953Srrs } 5497163953Srrs /* Clear the held length since there is something to read */ 5498163953Srrs control->held_length = 0; 5499163953Srrs if (hold_rlock) { 5500163953Srrs SCTP_INP_READ_UNLOCK(inp); 5501163953Srrs hold_rlock = 0; 5502163953Srrs } 5503163953Srrsfound_one: 5504163953Srrs /* 5505163953Srrs * If we reach here, control has a some data for us to read off. 5506163953Srrs * Note that stcb COULD be NULL. 5507163953Srrs */ 5508174323Srrs control->some_taken++; 5509163953Srrs if (hold_sblock) { 5510163953Srrs SOCKBUF_UNLOCK(&so->so_rcv); 5511163953Srrs hold_sblock = 0; 5512163953Srrs } 5513163953Srrs stcb = control->stcb; 5514163953Srrs if (stcb) { 5515170138Srrs if ((control->do_not_ref_stcb == 0) && 5516170138Srrs (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED)) { 5517163996Srrs if (freecnt_applied == 0) 5518163996Srrs stcb = NULL; 5519163953Srrs } else if (control->do_not_ref_stcb == 0) { 5520163953Srrs /* you can't free it on me please */ 5521163953Srrs /* 5522163953Srrs * The lock on the socket buffer protects us so the 5523163953Srrs * free code will stop. But since we used the 5524163953Srrs * socketbuf lock and the sender uses the tcb_lock 5525163953Srrs * to increment, we need to use the atomic add to 5526163953Srrs * the refcnt 5527163953Srrs */ 5528172396Srrs if (freecnt_applied) { 5529172396Srrs#ifdef INVARIANTS 5530170091Srrs panic("refcnt already incremented"); 5531172396Srrs#else 5532235164Stuexen SCTP_PRINTF("refcnt already incremented?\n"); 5533172396Srrs#endif 5534172396Srrs } else { 5535172396Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 5536172396Srrs freecnt_applied = 1; 5537172396Srrs } 5538163953Srrs /* 5539163953Srrs * Setup to remember how much we have not yet told 5540163953Srrs * the peer our rwnd has opened up. Note we grab the 5541163953Srrs * value from the tcb from last time. Note too that 5542170138Srrs * sack sending clears this when a sack is sent, 5543163953Srrs * which is fine. Once we hit the rwnd_req, we then 5544163953Srrs * will go to the sctp_user_rcvd() that will not 5545163953Srrs * lock until it KNOWs it MUST send a WUP-SACK. 5546163953Srrs */ 5547163953Srrs freed_so_far = stcb->freed_by_sorcv_sincelast; 5548163953Srrs stcb->freed_by_sorcv_sincelast = 0; 5549163953Srrs } 5550163953Srrs } 5551169352Srrs if (stcb && 5552169352Srrs ((control->spec_flags & M_NOTIFICATION) == 0) && 5553169295Srrs control->do_not_ref_stcb == 0) { 5554169208Srrs stcb->asoc.strmin[control->sinfo_stream].delivery_started = 1; 5555169208Srrs } 5556163953Srrs /* First lets get off the sinfo and sockaddr info */ 5557163953Srrs if ((sinfo) && filling_sinfo) { 5558163953Srrs memcpy(sinfo, control, sizeof(struct sctp_nonpad_sndrcvinfo)); 5559163953Srrs nxt = TAILQ_NEXT(control, next); 5560223132Stuexen if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXT_RCVINFO) || 5561223132Stuexen sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVNXTINFO)) { 5562163953Srrs struct sctp_extrcvinfo *s_extra; 5563163953Srrs 5564163953Srrs s_extra = (struct sctp_extrcvinfo *)sinfo; 5565168943Srrs if ((nxt) && 5566168943Srrs (nxt->length)) { 5567168943Srrs s_extra->sreinfo_next_flags = SCTP_NEXT_MSG_AVAIL; 5568163953Srrs if (nxt->sinfo_flags & SCTP_UNORDERED) { 5569168943Srrs s_extra->sreinfo_next_flags |= SCTP_NEXT_MSG_IS_UNORDERED; 5570163953Srrs } 5571166675Srrs if (nxt->spec_flags & M_NOTIFICATION) { 5572168943Srrs s_extra->sreinfo_next_flags |= SCTP_NEXT_MSG_IS_NOTIFICATION; 5573166675Srrs } 5574168943Srrs s_extra->sreinfo_next_aid = nxt->sinfo_assoc_id; 5575168943Srrs s_extra->sreinfo_next_length = nxt->length; 5576168943Srrs s_extra->sreinfo_next_ppid = nxt->sinfo_ppid; 5577168943Srrs s_extra->sreinfo_next_stream = nxt->sinfo_stream; 5578163953Srrs if (nxt->tail_mbuf != NULL) { 5579165647Srrs if (nxt->end_added) { 5580168943Srrs s_extra->sreinfo_next_flags |= SCTP_NEXT_MSG_ISCOMPLETE; 5581163953Srrs } 5582163953Srrs } 5583163953Srrs } else { 5584163953Srrs /* 5585163953Srrs * we explicitly 0 this, since the memcpy 5586163953Srrs * got some other things beyond the older 5587163953Srrs * sinfo_ that is on the control's structure 5588163953Srrs * :-D 5589163953Srrs */ 5590168943Srrs nxt = NULL; 5591168943Srrs s_extra->sreinfo_next_flags = SCTP_NO_NEXT_MSG; 5592168943Srrs s_extra->sreinfo_next_aid = 0; 5593168943Srrs s_extra->sreinfo_next_length = 0; 5594168943Srrs s_extra->sreinfo_next_ppid = 0; 5595168943Srrs s_extra->sreinfo_next_stream = 0; 5596163953Srrs } 5597163953Srrs } 5598163953Srrs /* 5599163953Srrs * update off the real current cum-ack, if we have an stcb. 5600163953Srrs */ 5601170138Srrs if ((control->do_not_ref_stcb == 0) && stcb) 5602163953Srrs sinfo->sinfo_cumtsn = stcb->asoc.cumulative_tsn; 5603163953Srrs /* 5604163953Srrs * mask off the high bits, we keep the actual chunk bits in 5605163953Srrs * there. 5606163953Srrs */ 5607163953Srrs sinfo->sinfo_flags &= 0x00ff; 5608170354Srrs if ((control->sinfo_flags >> 8) & SCTP_DATA_UNORDERED) { 5609170354Srrs sinfo->sinfo_flags |= SCTP_UNORDERED; 5610170354Srrs } 5611163953Srrs } 5612171477Srrs#ifdef SCTP_ASOCLOG_OF_TSNS 5613171477Srrs { 5614171477Srrs int index, newindex; 5615171477Srrs struct sctp_pcbtsn_rlog *entry; 5616171477Srrs 5617171477Srrs do { 5618171477Srrs index = inp->readlog_index; 5619171477Srrs newindex = index + 1; 5620171477Srrs if (newindex >= SCTP_READ_LOG_SIZE) { 5621171477Srrs newindex = 0; 5622171477Srrs } 5623171477Srrs } while (atomic_cmpset_int(&inp->readlog_index, index, newindex) == 0); 5624171477Srrs entry = &inp->readlog[index]; 5625171477Srrs entry->vtag = control->sinfo_assoc_id; 5626171477Srrs entry->strm = control->sinfo_stream; 5627171477Srrs entry->seq = control->sinfo_ssn; 5628171477Srrs entry->sz = control->length; 5629171477Srrs entry->flgs = control->sinfo_flags; 5630171477Srrs } 5631171477Srrs#endif 5632163953Srrs if (fromlen && from) { 5633234787Stuexen cp_len = min((size_t)fromlen, (size_t)control->whoFrom->ro._l_addr.sa.sa_len); 5634234787Stuexen switch (control->whoFrom->ro._l_addr.sa.sa_family) { 5635234787Stuexen#ifdef INET6 5636234787Stuexen case AF_INET6: 5637234787Stuexen ((struct sockaddr_in6 *)from)->sin6_port = control->port_from; 5638234787Stuexen break; 5639234787Stuexen#endif 5640167598Srrs#ifdef INET 5641234787Stuexen case AF_INET: 5642234787Stuexen ((struct sockaddr_in *)from)->sin_port = control->port_from; 5643234787Stuexen break; 5644234787Stuexen#endif 5645234787Stuexen default: 5646234787Stuexen break; 5647234787Stuexen } 5648163953Srrs memcpy(from, &control->whoFrom->ro._l_addr, cp_len); 5649163953Srrs 5650167598Srrs#if defined(INET) && defined(INET6) 5651178251Srrs if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) && 5652234787Stuexen (from->sa_family == AF_INET) && 5653163953Srrs ((size_t)fromlen >= sizeof(struct sockaddr_in6))) { 5654163953Srrs struct sockaddr_in *sin; 5655163953Srrs struct sockaddr_in6 sin6; 5656163953Srrs 5657234787Stuexen sin = (struct sockaddr_in *)from; 5658163953Srrs bzero(&sin6, sizeof(sin6)); 5659163953Srrs sin6.sin6_family = AF_INET6; 5660163953Srrs sin6.sin6_len = sizeof(struct sockaddr_in6); 5661180955Srrs sin6.sin6_addr.s6_addr32[2] = htonl(0xffff); 5662163953Srrs bcopy(&sin->sin_addr, 5663180955Srrs &sin6.sin6_addr.s6_addr32[3], 5664180955Srrs sizeof(sin6.sin6_addr.s6_addr32[3])); 5665163953Srrs sin6.sin6_port = sin->sin_port; 5666234787Stuexen memcpy(from, &sin6, sizeof(struct sockaddr_in6)); 5667163953Srrs } 5668163953Srrs#endif 5669238578Stuexen#ifdef INET6 5670163953Srrs { 5671234787Stuexen struct sockaddr_in6 lsa6, *from6; 5672163953Srrs 5673234787Stuexen from6 = (struct sockaddr_in6 *)from; 5674234787Stuexen sctp_recover_scope_mac(from6, (&lsa6)); 5675163953Srrs } 5676163953Srrs#endif 5677163953Srrs } 5678163953Srrs /* now copy out what data we can */ 5679163953Srrs if (mp == NULL) { 5680163953Srrs /* copy out each mbuf in the chain up to length */ 5681163953Srrsget_more_data: 5682163953Srrs m = control->data; 5683163953Srrs while (m) { 5684163953Srrs /* Move out all we can */ 5685163953Srrs cp_len = (int)uio->uio_resid; 5686165647Srrs my_len = (int)SCTP_BUF_LEN(m); 5687163953Srrs if (cp_len > my_len) { 5688163953Srrs /* not enough in this buf */ 5689163953Srrs cp_len = my_len; 5690163953Srrs } 5691163953Srrs if (hold_rlock) { 5692163953Srrs SCTP_INP_READ_UNLOCK(inp); 5693163953Srrs hold_rlock = 0; 5694163953Srrs } 5695163953Srrs if (cp_len > 0) 5696163953Srrs error = uiomove(mtod(m, char *), cp_len, uio); 5697163953Srrs /* re-read */ 5698163953Srrs if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) { 5699163953Srrs goto release; 5700163953Srrs } 5701170138Srrs if ((control->do_not_ref_stcb == 0) && stcb && 5702163953Srrs stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) { 5703163953Srrs no_rcv_needed = 1; 5704163953Srrs } 5705163953Srrs if (error) { 5706163953Srrs /* error we are out of here */ 5707163953Srrs goto release; 5708163953Srrs } 5709165647Srrs if ((SCTP_BUF_NEXT(m) == NULL) && 5710165647Srrs (cp_len >= SCTP_BUF_LEN(m)) && 5711163953Srrs ((control->end_added == 0) || 5712170138Srrs (control->end_added && 5713170138Srrs (TAILQ_NEXT(control, next) == NULL))) 5714163953Srrs ) { 5715163953Srrs SCTP_INP_READ_LOCK(inp); 5716163953Srrs hold_rlock = 1; 5717163953Srrs } 5718165647Srrs if (cp_len == SCTP_BUF_LEN(m)) { 5719165647Srrs if ((SCTP_BUF_NEXT(m) == NULL) && 5720165647Srrs (control->end_added)) { 5721163953Srrs out_flags |= MSG_EOR; 5722212225Srrs if ((control->do_not_ref_stcb == 0) && 5723212225Srrs (control->stcb != NULL) && 5724212225Srrs ((control->spec_flags & M_NOTIFICATION) == 0)) 5725168961Srrs control->stcb->asoc.strmin[control->sinfo_stream].delivery_started = 0; 5726163953Srrs } 5727165647Srrs if (control->spec_flags & M_NOTIFICATION) { 5728163953Srrs out_flags |= MSG_NOTIFICATION; 5729163953Srrs } 5730163953Srrs /* we ate up the mbuf */ 5731163953Srrs if (in_flags & MSG_PEEK) { 5732163953Srrs /* just looking */ 5733165647Srrs m = SCTP_BUF_NEXT(m); 5734163953Srrs copied_so_far += cp_len; 5735163953Srrs } else { 5736163953Srrs /* dispose of the mbuf */ 5737179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) { 5738170744Srrs sctp_sblog(&so->so_rcv, 5739170744Srrs control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBFREE, SCTP_BUF_LEN(m)); 5740170744Srrs } 5741163953Srrs sctp_sbfree(control, stcb, &so->so_rcv, m); 5742179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) { 5743170744Srrs sctp_sblog(&so->so_rcv, 5744170744Srrs control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBRESULT, 0); 5745170744Srrs } 5746163953Srrs copied_so_far += cp_len; 5747163953Srrs freed_so_far += cp_len; 5748171943Srrs freed_so_far += MSIZE; 5749171477Srrs atomic_subtract_int(&control->length, cp_len); 5750163953Srrs control->data = sctp_m_free(m); 5751163953Srrs m = control->data; 5752163953Srrs /* 5753163953Srrs * been through it all, must hold sb 5754163953Srrs * lock ok to null tail 5755163953Srrs */ 5756163953Srrs if (control->data == NULL) { 5757165220Srrs#ifdef INVARIANTS 5758163953Srrs if ((control->end_added == 0) || 5759163953Srrs (TAILQ_NEXT(control, next) == NULL)) { 5760163953Srrs /* 5761163953Srrs * If the end is not 5762163953Srrs * added, OR the 5763163953Srrs * next is NOT null 5764163953Srrs * we MUST have the 5765163953Srrs * lock. 5766163953Srrs */ 5767163953Srrs if (mtx_owned(&inp->inp_rdata_mtx) == 0) { 5768163953Srrs panic("Hmm we don't own the lock?"); 5769163953Srrs } 5770163953Srrs } 5771163953Srrs#endif 5772163953Srrs control->tail_mbuf = NULL; 5773165220Srrs#ifdef INVARIANTS 5774163953Srrs if ((control->end_added) && ((out_flags & MSG_EOR) == 0)) { 5775163953Srrs panic("end_added, nothing left and no MSG_EOR"); 5776163953Srrs } 5777163953Srrs#endif 5778163953Srrs } 5779163953Srrs } 5780163953Srrs } else { 5781163953Srrs /* Do we need to trim the mbuf? */ 5782165647Srrs if (control->spec_flags & M_NOTIFICATION) { 5783163953Srrs out_flags |= MSG_NOTIFICATION; 5784163953Srrs } 5785163953Srrs if ((in_flags & MSG_PEEK) == 0) { 5786165647Srrs SCTP_BUF_RESV_UF(m, cp_len); 5787165647Srrs SCTP_BUF_LEN(m) -= cp_len; 5788179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) { 5789170744Srrs sctp_sblog(&so->so_rcv, control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBFREE, cp_len); 5790170744Srrs } 5791163953Srrs atomic_subtract_int(&so->so_rcv.sb_cc, cp_len); 5792170138Srrs if ((control->do_not_ref_stcb == 0) && 5793170138Srrs stcb) { 5794163953Srrs atomic_subtract_int(&stcb->asoc.sb_cc, cp_len); 5795163953Srrs } 5796163953Srrs copied_so_far += cp_len; 5797163953Srrs freed_so_far += cp_len; 5798171943Srrs freed_so_far += MSIZE; 5799179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) { 5800170744Srrs sctp_sblog(&so->so_rcv, control->do_not_ref_stcb ? NULL : stcb, 5801170744Srrs SCTP_LOG_SBRESULT, 0); 5802170744Srrs } 5803171477Srrs atomic_subtract_int(&control->length, cp_len); 5804163953Srrs } else { 5805163953Srrs copied_so_far += cp_len; 5806163953Srrs } 5807163953Srrs } 5808170056Srrs if ((out_flags & MSG_EOR) || (uio->uio_resid == 0)) { 5809163953Srrs break; 5810163953Srrs } 5811163953Srrs if (((stcb) && (in_flags & MSG_PEEK) == 0) && 5812163953Srrs (control->do_not_ref_stcb == 0) && 5813163953Srrs (freed_so_far >= rwnd_req)) { 5814163953Srrs sctp_user_rcvd(stcb, &freed_so_far, hold_rlock, rwnd_req); 5815163953Srrs } 5816163953Srrs } /* end while(m) */ 5817163953Srrs /* 5818163953Srrs * At this point we have looked at it all and we either have 5819163953Srrs * a MSG_EOR/or read all the user wants... <OR> 5820163953Srrs * control->length == 0. 5821163953Srrs */ 5822170056Srrs if ((out_flags & MSG_EOR) && ((in_flags & MSG_PEEK) == 0)) { 5823163953Srrs /* we are done with this control */ 5824163953Srrs if (control->length == 0) { 5825163953Srrs if (control->data) { 5826165220Srrs#ifdef INVARIANTS 5827163953Srrs panic("control->data not null at read eor?"); 5828163953Srrs#else 5829169420Srrs SCTP_PRINTF("Strange, data left in the control buffer .. invarients would panic?\n"); 5830163953Srrs sctp_m_freem(control->data); 5831163953Srrs control->data = NULL; 5832163953Srrs#endif 5833163953Srrs } 5834163953Srrs done_with_control: 5835163953Srrs if (TAILQ_NEXT(control, next) == NULL) { 5836163953Srrs /* 5837163953Srrs * If we don't have a next we need a 5838172703Srrs * lock, if there is a next 5839172703Srrs * interrupt is filling ahead of us 5840172703Srrs * and we don't need a lock to 5841172703Srrs * remove this guy (which is the 5842172703Srrs * head of the queue). 5843163953Srrs */ 5844163953Srrs if (hold_rlock == 0) { 5845163953Srrs SCTP_INP_READ_LOCK(inp); 5846163953Srrs hold_rlock = 1; 5847163953Srrs } 5848163953Srrs } 5849163953Srrs TAILQ_REMOVE(&inp->read_queue, control, next); 5850163953Srrs /* Add back any hiddend data */ 5851163953Srrs if (control->held_length) { 5852163953Srrs held_length = 0; 5853163953Srrs control->held_length = 0; 5854163953Srrs wakeup_read_socket = 1; 5855163953Srrs } 5856169352Srrs if (control->aux_data) { 5857169352Srrs sctp_m_free(control->aux_data); 5858169352Srrs control->aux_data = NULL; 5859169352Srrs } 5860163953Srrs no_rcv_needed = control->do_not_ref_stcb; 5861163953Srrs sctp_free_remote_addr(control->whoFrom); 5862163953Srrs control->data = NULL; 5863163953Srrs sctp_free_a_readq(stcb, control); 5864163953Srrs control = NULL; 5865170138Srrs if ((freed_so_far >= rwnd_req) && 5866170138Srrs (no_rcv_needed == 0)) 5867163953Srrs sctp_user_rcvd(stcb, &freed_so_far, hold_rlock, rwnd_req); 5868163953Srrs 5869163953Srrs } else { 5870163953Srrs /* 5871163953Srrs * The user did not read all of this 5872163953Srrs * message, turn off the returned MSG_EOR 5873163953Srrs * since we are leaving more behind on the 5874163953Srrs * control to read. 5875163953Srrs */ 5876165220Srrs#ifdef INVARIANTS 5877170138Srrs if (control->end_added && 5878170138Srrs (control->data == NULL) && 5879163953Srrs (control->tail_mbuf == NULL)) { 5880163953Srrs panic("Gak, control->length is corrupt?"); 5881163953Srrs } 5882163953Srrs#endif 5883163953Srrs no_rcv_needed = control->do_not_ref_stcb; 5884163953Srrs out_flags &= ~MSG_EOR; 5885163953Srrs } 5886163953Srrs } 5887163953Srrs if (out_flags & MSG_EOR) { 5888163953Srrs goto release; 5889163953Srrs } 5890163953Srrs if ((uio->uio_resid == 0) || 5891266068Stuexen ((in_eeor_mode) && 5892266068Stuexen (copied_so_far >= (uint32_t) max(so->so_rcv.sb_lowat, 1)))) { 5893163953Srrs goto release; 5894163953Srrs } 5895163953Srrs /* 5896163953Srrs * If I hit here the receiver wants more and this message is 5897163953Srrs * NOT done (pd-api). So two questions. Can we block? if not 5898163953Srrs * we are done. Did the user NOT set MSG_WAITALL? 5899163953Srrs */ 5900163953Srrs if (block_allowed == 0) { 5901163953Srrs goto release; 5902163953Srrs } 5903163953Srrs /* 5904163953Srrs * We need to wait for more data a few things: - We don't 5905163953Srrs * sbunlock() so we don't get someone else reading. - We 5906163953Srrs * must be sure to account for the case where what is added 5907163953Srrs * is NOT to our control when we wakeup. 5908163953Srrs */ 5909163953Srrs 5910163953Srrs /* 5911163953Srrs * Do we need to tell the transport a rwnd update might be 5912163953Srrs * needed before we go to sleep? 5913163953Srrs */ 5914163953Srrs if (((stcb) && (in_flags & MSG_PEEK) == 0) && 5915163953Srrs ((freed_so_far >= rwnd_req) && 5916163953Srrs (control->do_not_ref_stcb == 0) && 5917163953Srrs (no_rcv_needed == 0))) { 5918163953Srrs sctp_user_rcvd(stcb, &freed_so_far, hold_rlock, rwnd_req); 5919163953Srrs } 5920163953Srrswait_some_more: 5921166023Srrs if (so->so_rcv.sb_state & SBS_CANTRCVMORE) { 5922163953Srrs goto release; 5923163953Srrs } 5924163953Srrs if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) 5925163953Srrs goto release; 5926163953Srrs 5927163953Srrs if (hold_rlock == 1) { 5928163953Srrs SCTP_INP_READ_UNLOCK(inp); 5929163953Srrs hold_rlock = 0; 5930163953Srrs } 5931163953Srrs if (hold_sblock == 0) { 5932163953Srrs SOCKBUF_LOCK(&so->so_rcv); 5933163953Srrs hold_sblock = 1; 5934163953Srrs } 5935172091Srrs if ((copied_so_far) && (control->length == 0) && 5936206137Stuexen (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE))) { 5937172091Srrs goto release; 5938172091Srrs } 5939163953Srrs if (so->so_rcv.sb_cc <= control->held_length) { 5940163953Srrs error = sbwait(&so->so_rcv); 5941163953Srrs if (error) { 5942163953Srrs goto release; 5943163953Srrs } 5944163953Srrs control->held_length = 0; 5945163953Srrs } 5946163953Srrs if (hold_sblock) { 5947163953Srrs SOCKBUF_UNLOCK(&so->so_rcv); 5948163953Srrs hold_sblock = 0; 5949163953Srrs } 5950163953Srrs if (control->length == 0) { 5951163953Srrs /* still nothing here */ 5952163953Srrs if (control->end_added == 1) { 5953163953Srrs /* he aborted, or is done i.e.did a shutdown */ 5954163953Srrs out_flags |= MSG_EOR; 5955168943Srrs if (control->pdapi_aborted) { 5956169295Srrs if ((control->do_not_ref_stcb == 0) && ((control->spec_flags & M_NOTIFICATION) == 0)) 5957168961Srrs control->stcb->asoc.strmin[control->sinfo_stream].delivery_started = 0; 5958168943Srrs 5959164085Srrs out_flags |= MSG_TRUNC; 5960168943Srrs } else { 5961169295Srrs if ((control->do_not_ref_stcb == 0) && ((control->spec_flags & M_NOTIFICATION) == 0)) 5962168961Srrs control->stcb->asoc.strmin[control->sinfo_stream].delivery_started = 0; 5963168943Srrs } 5964163953Srrs goto done_with_control; 5965163953Srrs } 5966163953Srrs if (so->so_rcv.sb_cc > held_length) { 5967163953Srrs control->held_length = so->so_rcv.sb_cc; 5968163953Srrs held_length = 0; 5969163953Srrs } 5970163953Srrs goto wait_some_more; 5971163953Srrs } else if (control->data == NULL) { 5972163996Srrs /* 5973163996Srrs * we must re-sync since data is probably being 5974163996Srrs * added 5975163996Srrs */ 5976163996Srrs SCTP_INP_READ_LOCK(inp); 5977163996Srrs if ((control->length > 0) && (control->data == NULL)) { 5978163996Srrs /* 5979163996Srrs * big trouble.. we have the lock and its 5980163996Srrs * corrupt? 5981163996Srrs */ 5982174323Srrs#ifdef INVARIANTS 5983163996Srrs panic("Impossible data==NULL length !=0"); 5984174323Srrs#endif 5985174323Srrs out_flags |= MSG_EOR; 5986174323Srrs out_flags |= MSG_TRUNC; 5987174323Srrs control->length = 0; 5988174323Srrs SCTP_INP_READ_UNLOCK(inp); 5989174323Srrs goto done_with_control; 5990163996Srrs } 5991163996Srrs SCTP_INP_READ_UNLOCK(inp); 5992163996Srrs /* We will fall around to get more data */ 5993163953Srrs } 5994163953Srrs goto get_more_data; 5995163953Srrs } else { 5996169352Srrs /*- 5997169352Srrs * Give caller back the mbuf chain, 5998169352Srrs * store in uio_resid the length 5999163953Srrs */ 6000169352Srrs wakeup_read_socket = 0; 6001169352Srrs if ((control->end_added == 0) || 6002169352Srrs (TAILQ_NEXT(control, next) == NULL)) { 6003169352Srrs /* Need to get rlock */ 6004169352Srrs if (hold_rlock == 0) { 6005169352Srrs SCTP_INP_READ_LOCK(inp); 6006169352Srrs hold_rlock = 1; 6007163953Srrs } 6008169352Srrs } 6009169352Srrs if (control->end_added) { 6010169352Srrs out_flags |= MSG_EOR; 6011231039Stuexen if ((control->do_not_ref_stcb == 0) && 6012231039Stuexen (control->stcb != NULL) && 6013231039Stuexen ((control->spec_flags & M_NOTIFICATION) == 0)) 6014169352Srrs control->stcb->asoc.strmin[control->sinfo_stream].delivery_started = 0; 6015169352Srrs } 6016169352Srrs if (control->spec_flags & M_NOTIFICATION) { 6017169352Srrs out_flags |= MSG_NOTIFICATION; 6018169352Srrs } 6019169352Srrs uio->uio_resid = control->length; 6020169352Srrs *mp = control->data; 6021169352Srrs m = control->data; 6022169352Srrs while (m) { 6023179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) { 6024170744Srrs sctp_sblog(&so->so_rcv, 6025170744Srrs control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBFREE, SCTP_BUF_LEN(m)); 6026170744Srrs } 6027169352Srrs sctp_sbfree(control, stcb, &so->so_rcv, m); 6028169352Srrs freed_so_far += SCTP_BUF_LEN(m); 6029171943Srrs freed_so_far += MSIZE; 6030179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) { 6031170744Srrs sctp_sblog(&so->so_rcv, 6032170744Srrs control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBRESULT, 0); 6033170744Srrs } 6034169352Srrs m = SCTP_BUF_NEXT(m); 6035163953Srrs } 6036169352Srrs control->data = control->tail_mbuf = NULL; 6037169352Srrs control->length = 0; 6038169352Srrs if (out_flags & MSG_EOR) { 6039169352Srrs /* Done with this control */ 6040169352Srrs goto done_with_control; 6041169352Srrs } 6042163953Srrs } 6043163953Srrsrelease: 6044163953Srrs if (hold_rlock == 1) { 6045163953Srrs SCTP_INP_READ_UNLOCK(inp); 6046163953Srrs hold_rlock = 0; 6047163953Srrs } 6048169236Srwatson if (hold_sblock == 1) { 6049169236Srwatson SOCKBUF_UNLOCK(&so->so_rcv); 6050169236Srwatson hold_sblock = 0; 6051163953Srrs } 6052163953Srrs sbunlock(&so->so_rcv); 6053169236Srwatson sockbuf_lock = 0; 6054163953Srrs 6055163953Srrsrelease_unlocked: 6056163953Srrs if (hold_sblock) { 6057163953Srrs SOCKBUF_UNLOCK(&so->so_rcv); 6058163953Srrs hold_sblock = 0; 6059163953Srrs } 6060163953Srrs if ((stcb) && (in_flags & MSG_PEEK) == 0) { 6061163953Srrs if ((freed_so_far >= rwnd_req) && 6062163953Srrs (control && (control->do_not_ref_stcb == 0)) && 6063163953Srrs (no_rcv_needed == 0)) 6064163953Srrs sctp_user_rcvd(stcb, &freed_so_far, hold_rlock, rwnd_req); 6065163953Srrs } 6066184031Srrsout: 6067184031Srrs if (msg_flags) { 6068174323Srrs *msg_flags = out_flags; 6069184031Srrs } 6070168943Srrs if (((out_flags & MSG_EOR) == 0) && 6071168943Srrs ((in_flags & MSG_PEEK) == 0) && 6072168943Srrs (sinfo) && 6073223132Stuexen (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXT_RCVINFO) || 6074223132Stuexen sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVNXTINFO))) { 6075168943Srrs struct sctp_extrcvinfo *s_extra; 6076168943Srrs 6077168943Srrs s_extra = (struct sctp_extrcvinfo *)sinfo; 6078168943Srrs s_extra->sreinfo_next_flags = SCTP_NO_NEXT_MSG; 6079168943Srrs } 6080163953Srrs if (hold_rlock == 1) { 6081163953Srrs SCTP_INP_READ_UNLOCK(inp); 6082163953Srrs } 6083163953Srrs if (hold_sblock) { 6084163953Srrs SOCKBUF_UNLOCK(&so->so_rcv); 6085163953Srrs } 6086169236Srwatson if (sockbuf_lock) { 6087169236Srwatson sbunlock(&so->so_rcv); 6088169236Srwatson } 6089163996Srrs if (freecnt_applied) { 6090163953Srrs /* 6091163953Srrs * The lock on the socket buffer protects us so the free 6092163953Srrs * code will stop. But since we used the socketbuf lock and 6093163953Srrs * the sender uses the tcb_lock to increment, we need to use 6094163953Srrs * the atomic add to the refcnt. 6095163953Srrs */ 6096163996Srrs if (stcb == NULL) { 6097182367Srrs#ifdef INVARIANTS 6098163996Srrs panic("stcb for refcnt has gone NULL?"); 6099182367Srrs goto stage_left; 6100182367Srrs#else 6101182367Srrs goto stage_left; 6102182367Srrs#endif 6103163996Srrs } 6104163996Srrs atomic_add_int(&stcb->asoc.refcnt, -1); 6105163953Srrs /* Save the value back for next time */ 6106163953Srrs stcb->freed_by_sorcv_sincelast = freed_so_far; 6107163953Srrs } 6108179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_RECV_RWND_LOGGING_ENABLE) { 6109170744Srrs if (stcb) { 6110170744Srrs sctp_misc_ints(SCTP_SORECV_DONE, 6111170744Srrs freed_so_far, 6112170744Srrs ((uio) ? (slen - uio->uio_resid) : slen), 6113170744Srrs stcb->asoc.my_rwnd, 6114170744Srrs so->so_rcv.sb_cc); 6115170744Srrs } else { 6116170744Srrs sctp_misc_ints(SCTP_SORECV_DONE, 6117170744Srrs freed_so_far, 6118170744Srrs ((uio) ? (slen - uio->uio_resid) : slen), 6119170744Srrs 0, 6120170744Srrs so->so_rcv.sb_cc); 6121170744Srrs } 6122163953Srrs } 6123182367Srrsstage_left: 6124163953Srrs if (wakeup_read_socket) { 6125163953Srrs sctp_sorwakeup(inp, so); 6126163953Srrs } 6127163953Srrs return (error); 6128163953Srrs} 6129163953Srrs 6130163953Srrs 6131163953Srrs#ifdef SCTP_MBUF_LOGGING 6132163953Srrsstruct mbuf * 6133163953Srrssctp_m_free(struct mbuf *m) 6134163953Srrs{ 6135179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) { 6136170744Srrs if (SCTP_BUF_IS_EXTENDED(m)) { 6137170744Srrs sctp_log_mb(m, SCTP_MBUF_IFREE); 6138170744Srrs } 6139163953Srrs } 6140163953Srrs return (m_free(m)); 6141163953Srrs} 6142163953Srrs 6143163953Srrsvoid 6144163953Srrssctp_m_freem(struct mbuf *mb) 6145163953Srrs{ 6146163953Srrs while (mb != NULL) 6147163953Srrs mb = sctp_m_free(mb); 6148163953Srrs} 6149163953Srrs 6150163953Srrs#endif 6151163953Srrs 6152167598Srrsint 6153167598Srrssctp_dynamic_set_primary(struct sockaddr *sa, uint32_t vrf_id) 6154167598Srrs{ 6155167598Srrs /* 6156167598Srrs * Given a local address. For all associations that holds the 6157167598Srrs * address, request a peer-set-primary. 6158167598Srrs */ 6159167598Srrs struct sctp_ifa *ifa; 6160167598Srrs struct sctp_laddr *wi; 6161163953Srrs 6162167598Srrs ifa = sctp_find_ifa_by_addr(sa, vrf_id, 0); 6163167598Srrs if (ifa == NULL) { 6164171943Srrs SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTPUTIL, EADDRNOTAVAIL); 6165167598Srrs return (EADDRNOTAVAIL); 6166167598Srrs } 6167167598Srrs /* 6168167598Srrs * Now that we have the ifa we must awaken the iterator with this 6169167598Srrs * message. 6170167598Srrs */ 6171179783Srrs wi = SCTP_ZONE_GET(SCTP_BASE_INFO(ipi_zone_laddr), struct sctp_laddr); 6172167598Srrs if (wi == NULL) { 6173171943Srrs SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTPUTIL, ENOMEM); 6174167598Srrs return (ENOMEM); 6175167598Srrs } 6176167598Srrs /* Now incr the count and int wi structure */ 6177167598Srrs SCTP_INCR_LADDR_COUNT(); 6178167598Srrs bzero(wi, sizeof(*wi)); 6179170056Srrs (void)SCTP_GETTIME_TIMEVAL(&wi->start_time); 6180167598Srrs wi->ifa = ifa; 6181167598Srrs wi->action = SCTP_SET_PRIM_ADDR; 6182167598Srrs atomic_add_int(&ifa->refcount, 1); 6183167598Srrs 6184167598Srrs /* Now add it to the work queue */ 6185208160Srrs SCTP_WQ_ADDR_LOCK(); 6186167598Srrs /* 6187167598Srrs * Should this really be a tailq? As it is we will process the 6188167598Srrs * newest first :-0 6189167598Srrs */ 6190179783Srrs LIST_INSERT_HEAD(&SCTP_BASE_INFO(addr_wq), wi, sctp_nxt_addr); 6191208160Srrs SCTP_WQ_ADDR_UNLOCK(); 6192167598Srrs sctp_timer_start(SCTP_TIMER_TYPE_ADDR_WQ, 6193167598Srrs (struct sctp_inpcb *)NULL, 6194167598Srrs (struct sctp_tcb *)NULL, 6195167598Srrs (struct sctp_nets *)NULL); 6196167598Srrs return (0); 6197167598Srrs} 6198167598Srrs 6199167598Srrs 6200163953Srrsint 6201169352Srrssctp_soreceive(struct socket *so, 6202169352Srrs struct sockaddr **psa, 6203169352Srrs struct uio *uio, 6204169352Srrs struct mbuf **mp0, 6205169352Srrs struct mbuf **controlp, 6206169352Srrs int *flagsp) 6207163953Srrs{ 6208163953Srrs int error, fromlen; 6209163953Srrs uint8_t sockbuf[256]; 6210163953Srrs struct sockaddr *from; 6211163953Srrs struct sctp_extrcvinfo sinfo; 6212163953Srrs int filling_sinfo = 1; 6213163953Srrs struct sctp_inpcb *inp; 6214163953Srrs 6215163953Srrs inp = (struct sctp_inpcb *)so->so_pcb; 6216163953Srrs /* pickup the assoc we are reading from */ 6217163953Srrs if (inp == NULL) { 6218171943Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL); 6219163953Srrs return (EINVAL); 6220163953Srrs } 6221223132Stuexen if ((sctp_is_feature_off(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT) && 6222223132Stuexen sctp_is_feature_off(inp, SCTP_PCB_FLAGS_RECVRCVINFO) && 6223223132Stuexen sctp_is_feature_off(inp, SCTP_PCB_FLAGS_RECVNXTINFO)) || 6224163953Srrs (controlp == NULL)) { 6225163953Srrs /* user does not want the sndrcv ctl */ 6226163953Srrs filling_sinfo = 0; 6227163953Srrs } 6228163953Srrs if (psa) { 6229163953Srrs from = (struct sockaddr *)sockbuf; 6230163953Srrs fromlen = sizeof(sockbuf); 6231163953Srrs from->sa_len = 0; 6232163953Srrs } else { 6233163953Srrs from = NULL; 6234163953Srrs fromlen = 0; 6235163953Srrs } 6236163953Srrs 6237268433Sdelphij if (filling_sinfo) { 6238268433Sdelphij memset(&sinfo, 0, sizeof(struct sctp_extrcvinfo)); 6239268433Sdelphij } 6240163953Srrs error = sctp_sorecvmsg(so, uio, mp0, from, fromlen, flagsp, 6241163953Srrs (struct sctp_sndrcvinfo *)&sinfo, filling_sinfo); 6242268433Sdelphij if (controlp != NULL) { 6243163953Srrs /* copy back the sinfo in a CMSG format */ 6244163953Srrs if (filling_sinfo) 6245163953Srrs *controlp = sctp_build_ctl_nchunk(inp, 6246163953Srrs (struct sctp_sndrcvinfo *)&sinfo); 6247163953Srrs else 6248163953Srrs *controlp = NULL; 6249163953Srrs } 6250163953Srrs if (psa) { 6251163953Srrs /* copy back the address info */ 6252163953Srrs if (from && from->sa_len) { 6253163953Srrs *psa = sodupsockaddr(from, M_NOWAIT); 6254163953Srrs } else { 6255163953Srrs *psa = NULL; 6256163953Srrs } 6257163953Srrs } 6258163953Srrs return (error); 6259163953Srrs} 6260169352Srrs 6261169352Srrs 6262169352Srrs 6263169352Srrs 6264169352Srrs 6265169352Srrsint 6266170056Srrssctp_connectx_helper_add(struct sctp_tcb *stcb, struct sockaddr *addr, 6267170056Srrs int totaddr, int *error) 6268169352Srrs{ 6269169352Srrs int added = 0; 6270169352Srrs int i; 6271169352Srrs struct sctp_inpcb *inp; 6272169352Srrs struct sockaddr *sa; 6273169352Srrs size_t incr = 0; 6274169352Srrs 6275225571Stuexen#ifdef INET 6276225571Stuexen struct sockaddr_in *sin; 6277225571Stuexen 6278225571Stuexen#endif 6279225571Stuexen#ifdef INET6 6280225571Stuexen struct sockaddr_in6 *sin6; 6281225571Stuexen 6282225571Stuexen#endif 6283225571Stuexen 6284169352Srrs sa = addr; 6285169352Srrs inp = stcb->sctp_ep; 6286169352Srrs *error = 0; 6287169352Srrs for (i = 0; i < totaddr; i++) { 6288221328Stuexen switch (sa->sa_family) { 6289221328Stuexen#ifdef INET 6290221328Stuexen case AF_INET: 6291169352Srrs incr = sizeof(struct sockaddr_in); 6292225571Stuexen sin = (struct sockaddr_in *)sa; 6293225571Stuexen if ((sin->sin_addr.s_addr == INADDR_ANY) || 6294225571Stuexen (sin->sin_addr.s_addr == INADDR_BROADCAST) || 6295225571Stuexen IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) { 6296225571Stuexen SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, EINVAL); 6297225571Stuexen (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_7); 6298225571Stuexen *error = EINVAL; 6299225571Stuexen goto out_now; 6300225571Stuexen } 6301224641Stuexen if (sctp_add_remote_addr(stcb, sa, NULL, SCTP_DONOT_SETSCOPE, SCTP_ADDR_IS_CONFIRMED)) { 6302169352Srrs /* assoc gone no un-lock */ 6303171943Srrs SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ENOBUFS); 6304171943Srrs (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_7); 6305169352Srrs *error = ENOBUFS; 6306169352Srrs goto out_now; 6307169352Srrs } 6308169352Srrs added++; 6309221328Stuexen break; 6310221328Stuexen#endif 6311221328Stuexen#ifdef INET6 6312221328Stuexen case AF_INET6: 6313169352Srrs incr = sizeof(struct sockaddr_in6); 6314225571Stuexen sin6 = (struct sockaddr_in6 *)sa; 6315225571Stuexen if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) || 6316225571Stuexen IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) { 6317225571Stuexen SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, EINVAL); 6318225571Stuexen (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_8); 6319225571Stuexen *error = EINVAL; 6320225571Stuexen goto out_now; 6321225571Stuexen } 6322224641Stuexen if (sctp_add_remote_addr(stcb, sa, NULL, SCTP_DONOT_SETSCOPE, SCTP_ADDR_IS_CONFIRMED)) { 6323169352Srrs /* assoc gone no un-lock */ 6324171943Srrs SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ENOBUFS); 6325171943Srrs (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_8); 6326169352Srrs *error = ENOBUFS; 6327169352Srrs goto out_now; 6328169352Srrs } 6329169352Srrs added++; 6330221328Stuexen break; 6331221328Stuexen#endif 6332221328Stuexen default: 6333221328Stuexen break; 6334169352Srrs } 6335169352Srrs sa = (struct sockaddr *)((caddr_t)sa + incr); 6336169352Srrs } 6337169352Srrsout_now: 6338169352Srrs return (added); 6339169352Srrs} 6340169352Srrs 6341169352Srrsstruct sctp_tcb * 6342170056Srrssctp_connectx_helper_find(struct sctp_inpcb *inp, struct sockaddr *addr, 6343170056Srrs int *totaddr, int *num_v4, int *num_v6, int *error, 6344170056Srrs int limit, int *bad_addr) 6345169352Srrs{ 6346169352Srrs struct sockaddr *sa; 6347169352Srrs struct sctp_tcb *stcb = NULL; 6348169352Srrs size_t incr, at, i; 6349169352Srrs 6350169352Srrs at = incr = 0; 6351169352Srrs sa = addr; 6352221328Stuexen 6353169352Srrs *error = *num_v6 = *num_v4 = 0; 6354169352Srrs /* account and validate addresses */ 6355170140Srrs for (i = 0; i < (size_t)*totaddr; i++) { 6356221328Stuexen switch (sa->sa_family) { 6357221328Stuexen#ifdef INET 6358221328Stuexen case AF_INET: 6359169352Srrs (*num_v4) += 1; 6360169352Srrs incr = sizeof(struct sockaddr_in); 6361170056Srrs if (sa->sa_len != incr) { 6362171943Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL); 6363170056Srrs *error = EINVAL; 6364170056Srrs *bad_addr = 1; 6365170056Srrs return (NULL); 6366170056Srrs } 6367221328Stuexen break; 6368221328Stuexen#endif 6369221328Stuexen#ifdef INET6 6370221328Stuexen case AF_INET6: 6371221328Stuexen { 6372221328Stuexen struct sockaddr_in6 *sin6; 6373169352Srrs 6374221328Stuexen sin6 = (struct sockaddr_in6 *)sa; 6375221328Stuexen if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { 6376221328Stuexen /* Must be non-mapped for connectx */ 6377221328Stuexen SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL); 6378221328Stuexen *error = EINVAL; 6379221328Stuexen *bad_addr = 1; 6380221328Stuexen return (NULL); 6381221328Stuexen } 6382221328Stuexen (*num_v6) += 1; 6383221328Stuexen incr = sizeof(struct sockaddr_in6); 6384221328Stuexen if (sa->sa_len != incr) { 6385221328Stuexen SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL); 6386221328Stuexen *error = EINVAL; 6387221328Stuexen *bad_addr = 1; 6388221328Stuexen return (NULL); 6389221328Stuexen } 6390221328Stuexen break; 6391169352Srrs } 6392221328Stuexen#endif 6393221328Stuexen default: 6394169352Srrs *totaddr = i; 6395169352Srrs /* we are done */ 6396169352Srrs break; 6397169352Srrs } 6398221328Stuexen if (i == (size_t)*totaddr) { 6399221328Stuexen break; 6400221328Stuexen } 6401170056Srrs SCTP_INP_INCR_REF(inp); 6402169352Srrs stcb = sctp_findassociation_ep_addr(&inp, sa, NULL, NULL, NULL); 6403169352Srrs if (stcb != NULL) { 6404169352Srrs /* Already have or am bring up an association */ 6405169352Srrs return (stcb); 6406170056Srrs } else { 6407170056Srrs SCTP_INP_DECR_REF(inp); 6408169352Srrs } 6409170140Srrs if ((at + incr) > (size_t)limit) { 6410169352Srrs *totaddr = i; 6411169352Srrs break; 6412169352Srrs } 6413169352Srrs sa = (struct sockaddr *)((caddr_t)sa + incr); 6414169352Srrs } 6415169352Srrs return ((struct sctp_tcb *)NULL); 6416169352Srrs} 6417170606Srrs 6418170606Srrs/* 6419170606Srrs * sctp_bindx(ADD) for one address. 6420170606Srrs * assumes all arguments are valid/checked by caller. 6421170606Srrs */ 6422170606Srrsvoid 6423170606Srrssctp_bindx_add_address(struct socket *so, struct sctp_inpcb *inp, 6424170606Srrs struct sockaddr *sa, sctp_assoc_t assoc_id, 6425170606Srrs uint32_t vrf_id, int *error, void *p) 6426170606Srrs{ 6427170606Srrs struct sockaddr *addr_touse; 6428178251Srrs 6429178251Srrs#ifdef INET6 6430170606Srrs struct sockaddr_in sin; 6431170606Srrs 6432178251Srrs#endif 6433178251Srrs 6434170606Srrs /* see if we're bound all already! */ 6435170606Srrs if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) { 6436171943Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL); 6437170606Srrs *error = EINVAL; 6438170606Srrs return; 6439170606Srrs } 6440170606Srrs addr_touse = sa; 6441221328Stuexen#ifdef INET6 6442170606Srrs if (sa->sa_family == AF_INET6) { 6443170606Srrs struct sockaddr_in6 *sin6; 6444170606Srrs 6445170606Srrs if (sa->sa_len != sizeof(struct sockaddr_in6)) { 6446171943Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL); 6447170606Srrs *error = EINVAL; 6448170606Srrs return; 6449170606Srrs } 6450170665Srrs if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) { 6451170665Srrs /* can only bind v6 on PF_INET6 sockets */ 6452171943Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL); 6453170665Srrs *error = EINVAL; 6454170665Srrs return; 6455170665Srrs } 6456170606Srrs sin6 = (struct sockaddr_in6 *)addr_touse; 6457170606Srrs if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { 6458170665Srrs if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) && 6459170665Srrs SCTP_IPV6_V6ONLY(inp)) { 6460170665Srrs /* can't bind v4-mapped on PF_INET sockets */ 6461171943Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL); 6462170665Srrs *error = EINVAL; 6463170665Srrs return; 6464170665Srrs } 6465170606Srrs in6_sin6_2_sin(&sin, sin6); 6466170606Srrs addr_touse = (struct sockaddr *)&sin; 6467170606Srrs } 6468170606Srrs } 6469170606Srrs#endif 6470221328Stuexen#ifdef INET 6471170606Srrs if (sa->sa_family == AF_INET) { 6472170606Srrs if (sa->sa_len != sizeof(struct sockaddr_in)) { 6473171943Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL); 6474170606Srrs *error = EINVAL; 6475170606Srrs return; 6476170606Srrs } 6477170665Srrs if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) && 6478170665Srrs SCTP_IPV6_V6ONLY(inp)) { 6479170665Srrs /* can't bind v4 on PF_INET sockets */ 6480171943Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL); 6481170665Srrs *error = EINVAL; 6482170665Srrs return; 6483170665Srrs } 6484170606Srrs } 6485221328Stuexen#endif 6486170606Srrs if (inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) { 6487170606Srrs if (p == NULL) { 6488170606Srrs /* Can't get proc for Net/Open BSD */ 6489171943Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL); 6490170606Srrs *error = EINVAL; 6491170606Srrs return; 6492170606Srrs } 6493171572Srrs *error = sctp_inpcb_bind(so, addr_touse, NULL, p); 6494170606Srrs return; 6495170606Srrs } 6496170606Srrs /* 6497170606Srrs * No locks required here since bind and mgmt_ep_sa all do their own 6498170606Srrs * locking. If we do something for the FIX: below we may need to 6499170606Srrs * lock in that case. 6500170606Srrs */ 6501170606Srrs if (assoc_id == 0) { 6502170606Srrs /* add the address */ 6503170606Srrs struct sctp_inpcb *lep; 6504171032Srrs struct sockaddr_in *lsin = (struct sockaddr_in *)addr_touse; 6505170606Srrs 6506171032Srrs /* validate the incoming port */ 6507171032Srrs if ((lsin->sin_port != 0) && 6508171032Srrs (lsin->sin_port != inp->sctp_lport)) { 6509171943Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL); 6510171032Srrs *error = EINVAL; 6511171032Srrs return; 6512171032Srrs } else { 6513171032Srrs /* user specified 0 port, set it to existing port */ 6514171032Srrs lsin->sin_port = inp->sctp_lport; 6515171032Srrs } 6516171032Srrs 6517170606Srrs lep = sctp_pcb_findep(addr_touse, 1, 0, vrf_id); 6518170606Srrs if (lep != NULL) { 6519170606Srrs /* 6520170606Srrs * We must decrement the refcount since we have the 6521170606Srrs * ep already and are binding. No remove going on 6522170606Srrs * here. 6523170606Srrs */ 6524181054Srrs SCTP_INP_DECR_REF(lep); 6525170606Srrs } 6526170606Srrs if (lep == inp) { 6527170606Srrs /* already bound to it.. ok */ 6528170606Srrs return; 6529170606Srrs } else if (lep == NULL) { 6530170606Srrs ((struct sockaddr_in *)addr_touse)->sin_port = 0; 6531170606Srrs *error = sctp_addr_mgmt_ep_sa(inp, addr_touse, 6532170606Srrs SCTP_ADD_IP_ADDRESS, 6533170744Srrs vrf_id, NULL); 6534170606Srrs } else { 6535170606Srrs *error = EADDRINUSE; 6536170606Srrs } 6537170606Srrs if (*error) 6538170606Srrs return; 6539170606Srrs } else { 6540170606Srrs /* 6541170606Srrs * FIX: decide whether we allow assoc based bindx 6542170606Srrs */ 6543170606Srrs } 6544170606Srrs} 6545170606Srrs 6546170606Srrs/* 6547170606Srrs * sctp_bindx(DELETE) for one address. 6548170606Srrs * assumes all arguments are valid/checked by caller. 6549170606Srrs */ 6550170606Srrsvoid 6551231038Stuexensctp_bindx_delete_address(struct sctp_inpcb *inp, 6552170606Srrs struct sockaddr *sa, sctp_assoc_t assoc_id, 6553170606Srrs uint32_t vrf_id, int *error) 6554170606Srrs{ 6555170606Srrs struct sockaddr *addr_touse; 6556178251Srrs 6557178251Srrs#ifdef INET6 6558170606Srrs struct sockaddr_in sin; 6559170606Srrs 6560178251Srrs#endif 6561178251Srrs 6562170606Srrs /* see if we're bound all already! */ 6563170606Srrs if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) { 6564171943Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL); 6565170606Srrs *error = EINVAL; 6566170606Srrs return; 6567170606Srrs } 6568170606Srrs addr_touse = sa; 6569238578Stuexen#ifdef INET6 6570170606Srrs if (sa->sa_family == AF_INET6) { 6571170606Srrs struct sockaddr_in6 *sin6; 6572170606Srrs 6573170606Srrs if (sa->sa_len != sizeof(struct sockaddr_in6)) { 6574171943Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL); 6575170606Srrs *error = EINVAL; 6576170606Srrs return; 6577170606Srrs } 6578170665Srrs if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) { 6579170665Srrs /* can only bind v6 on PF_INET6 sockets */ 6580171943Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL); 6581170665Srrs *error = EINVAL; 6582170665Srrs return; 6583170665Srrs } 6584170606Srrs sin6 = (struct sockaddr_in6 *)addr_touse; 6585170606Srrs if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { 6586170665Srrs if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) && 6587170665Srrs SCTP_IPV6_V6ONLY(inp)) { 6588170665Srrs /* can't bind mapped-v4 on PF_INET sockets */ 6589171943Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL); 6590170665Srrs *error = EINVAL; 6591170665Srrs return; 6592170665Srrs } 6593170606Srrs in6_sin6_2_sin(&sin, sin6); 6594170606Srrs addr_touse = (struct sockaddr *)&sin; 6595170606Srrs } 6596170606Srrs } 6597170606Srrs#endif 6598221328Stuexen#ifdef INET 6599170606Srrs if (sa->sa_family == AF_INET) { 6600170606Srrs if (sa->sa_len != sizeof(struct sockaddr_in)) { 6601171943Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL); 6602170606Srrs *error = EINVAL; 6603170606Srrs return; 6604170606Srrs } 6605170665Srrs if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) && 6606170665Srrs SCTP_IPV6_V6ONLY(inp)) { 6607170665Srrs /* can't bind v4 on PF_INET sockets */ 6608171943Srrs SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL); 6609170665Srrs *error = EINVAL; 6610170665Srrs return; 6611170665Srrs } 6612170606Srrs } 6613221328Stuexen#endif 6614170606Srrs /* 6615170606Srrs * No lock required mgmt_ep_sa does its own locking. If the FIX: 6616170606Srrs * below is ever changed we may need to lock before calling 6617170606Srrs * association level binding. 6618170606Srrs */ 6619170606Srrs if (assoc_id == 0) { 6620170606Srrs /* delete the address */ 6621170606Srrs *error = sctp_addr_mgmt_ep_sa(inp, addr_touse, 6622170606Srrs SCTP_DEL_IP_ADDRESS, 6623170744Srrs vrf_id, NULL); 6624170606Srrs } else { 6625170606Srrs /* 6626170606Srrs * FIX: decide whether we allow assoc based bindx 6627170606Srrs */ 6628170606Srrs } 6629170606Srrs} 6630171572Srrs 6631171572Srrs/* 6632171572Srrs * returns the valid local address count for an assoc, taking into account 6633171572Srrs * all scoping rules 6634171572Srrs */ 6635171572Srrsint 6636171572Srrssctp_local_addr_count(struct sctp_tcb *stcb) 6637171572Srrs{ 6638266054Stuexen int loopback_scope; 6639266054Stuexen 6640266054Stuexen#if defined(INET) 6641266054Stuexen int ipv4_local_scope, ipv4_addr_legal; 6642266054Stuexen 6643266054Stuexen#endif 6644266054Stuexen#if defined (INET6) 6645266054Stuexen int local_scope, site_scope, ipv6_addr_legal; 6646266054Stuexen 6647266054Stuexen#endif 6648171572Srrs struct sctp_vrf *vrf; 6649171572Srrs struct sctp_ifn *sctp_ifn; 6650171572Srrs struct sctp_ifa *sctp_ifa; 6651171572Srrs int count = 0; 6652171572Srrs 6653171572Srrs /* Turn on all the appropriate scopes */ 6654252961Stuexen loopback_scope = stcb->asoc.scope.loopback_scope; 6655266054Stuexen#if defined(INET) 6656252961Stuexen ipv4_local_scope = stcb->asoc.scope.ipv4_local_scope; 6657266054Stuexen ipv4_addr_legal = stcb->asoc.scope.ipv4_addr_legal; 6658266054Stuexen#endif 6659266054Stuexen#if defined(INET6) 6660252961Stuexen local_scope = stcb->asoc.scope.local_scope; 6661252961Stuexen site_scope = stcb->asoc.scope.site_scope; 6662252961Stuexen ipv6_addr_legal = stcb->asoc.scope.ipv6_addr_legal; 6663266054Stuexen#endif 6664172218Srrs SCTP_IPI_ADDR_RLOCK(); 6665171572Srrs vrf = sctp_find_vrf(stcb->asoc.vrf_id); 6666171572Srrs if (vrf == NULL) { 6667171572Srrs /* no vrf, no addresses */ 6668172218Srrs SCTP_IPI_ADDR_RUNLOCK(); 6669171572Srrs return (0); 6670171572Srrs } 6671171572Srrs if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) { 6672171572Srrs /* 6673171572Srrs * bound all case: go through all ifns on the vrf 6674171572Srrs */ 6675171572Srrs LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) { 6676171572Srrs if ((loopback_scope == 0) && 6677171572Srrs SCTP_IFN_IS_IFT_LOOP(sctp_ifn)) { 6678171572Srrs continue; 6679171572Srrs } 6680171572Srrs LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) { 6681171572Srrs if (sctp_is_addr_restricted(stcb, sctp_ifa)) 6682171572Srrs continue; 6683178251Srrs switch (sctp_ifa->address.sa.sa_family) { 6684221328Stuexen#ifdef INET 6685178251Srrs case AF_INET: 6686178251Srrs if (ipv4_addr_legal) { 6687178251Srrs struct sockaddr_in *sin; 6688171572Srrs 6689178251Srrs sin = (struct sockaddr_in *)&sctp_ifa->address.sa; 6690178251Srrs if (sin->sin_addr.s_addr == 0) { 6691178251Srrs /* 6692178251Srrs * skip unspecified 6693178251Srrs * addrs 6694178251Srrs */ 6695178251Srrs continue; 6696178251Srrs } 6697267799Stuexen if (prison_check_ip4(stcb->sctp_ep->ip_inp.inp.inp_cred, 6698267799Stuexen &sin->sin_addr) != 0) { 6699267799Stuexen continue; 6700267799Stuexen } 6701178251Srrs if ((ipv4_local_scope == 0) && 6702178251Srrs (IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))) { 6703178251Srrs continue; 6704178251Srrs } 6705178251Srrs /* count this one */ 6706178251Srrs count++; 6707178251Srrs } else { 6708171572Srrs continue; 6709171572Srrs } 6710178251Srrs break; 6711221328Stuexen#endif 6712178251Srrs#ifdef INET6 6713178251Srrs case AF_INET6: 6714178251Srrs if (ipv6_addr_legal) { 6715178251Srrs struct sockaddr_in6 *sin6; 6716171572Srrs 6717178251Srrs sin6 = (struct sockaddr_in6 *)&sctp_ifa->address.sa; 6718178251Srrs if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 6719171572Srrs continue; 6720178251Srrs } 6721267799Stuexen if (prison_check_ip6(stcb->sctp_ep->ip_inp.inp.inp_cred, 6722267799Stuexen &sin6->sin6_addr) != 0) { 6723267799Stuexen continue; 6724267799Stuexen } 6725178251Srrs if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { 6726178251Srrs if (local_scope == 0) 6727171572Srrs continue; 6728178251Srrs if (sin6->sin6_scope_id == 0) { 6729178251Srrs if (sa6_recoverscope(sin6) != 0) 6730178251Srrs /* 6731178251Srrs * 6732178251Srrs * bad 6733178251Srrs * 6734178251Srrs * li 6735178251Srrs * nk 6736178251Srrs * 6737178251Srrs * loc 6738178251Srrs * al 6739178251Srrs * 6740178251Srrs * add 6741178251Srrs * re 6742178251Srrs * ss 6743178251Srrs * */ 6744178251Srrs continue; 6745178251Srrs } 6746171572Srrs } 6747178251Srrs if ((site_scope == 0) && 6748178251Srrs (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr))) { 6749178251Srrs continue; 6750178251Srrs } 6751178251Srrs /* count this one */ 6752178251Srrs count++; 6753171572Srrs } 6754178251Srrs break; 6755178251Srrs#endif 6756178251Srrs default: 6757178251Srrs /* TSNH */ 6758178251Srrs break; 6759171572Srrs } 6760171572Srrs } 6761171572Srrs } 6762171572Srrs } else { 6763171572Srrs /* 6764171572Srrs * subset bound case 6765171572Srrs */ 6766171572Srrs struct sctp_laddr *laddr; 6767171572Srrs 6768171572Srrs LIST_FOREACH(laddr, &stcb->sctp_ep->sctp_addr_list, 6769171572Srrs sctp_nxt_addr) { 6770171572Srrs if (sctp_is_addr_restricted(stcb, laddr->ifa)) { 6771171572Srrs continue; 6772171572Srrs } 6773171572Srrs /* count this one */ 6774171572Srrs count++; 6775171572Srrs } 6776171572Srrs } 6777172218Srrs SCTP_IPI_ADDR_RUNLOCK(); 6778171572Srrs return (count); 6779171572Srrs} 6780171943Srrs 6781171943Srrs#if defined(SCTP_LOCAL_TRACE_BUF) 6782171943Srrs 6783171943Srrsvoid 6784172157Srrssctp_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) 6785171943Srrs{ 6786172157Srrs uint32_t saveindex, newindex; 6787171943Srrs 6788171943Srrs do { 6789179783Srrs saveindex = SCTP_BASE_SYSCTL(sctp_log).index; 6790171943Srrs if (saveindex >= SCTP_MAX_LOGGING_SIZE) { 6791171943Srrs newindex = 1; 6792171943Srrs } else { 6793171943Srrs newindex = saveindex + 1; 6794171943Srrs } 6795179783Srrs } while (atomic_cmpset_int(&SCTP_BASE_SYSCTL(sctp_log).index, saveindex, newindex) == 0); 6796171943Srrs if (saveindex >= SCTP_MAX_LOGGING_SIZE) { 6797171943Srrs saveindex = 0; 6798171943Srrs } 6799179783Srrs SCTP_BASE_SYSCTL(sctp_log).entry[saveindex].timestamp = SCTP_GET_CYCLECOUNT; 6800179783Srrs SCTP_BASE_SYSCTL(sctp_log).entry[saveindex].subsys = subsys; 6801179783Srrs SCTP_BASE_SYSCTL(sctp_log).entry[saveindex].params[0] = a; 6802179783Srrs SCTP_BASE_SYSCTL(sctp_log).entry[saveindex].params[1] = b; 6803179783Srrs SCTP_BASE_SYSCTL(sctp_log).entry[saveindex].params[2] = c; 6804179783Srrs SCTP_BASE_SYSCTL(sctp_log).entry[saveindex].params[3] = d; 6805179783Srrs SCTP_BASE_SYSCTL(sctp_log).entry[saveindex].params[4] = e; 6806179783Srrs SCTP_BASE_SYSCTL(sctp_log).entry[saveindex].params[5] = f; 6807171943Srrs} 6808171943Srrs 6809171943Srrs#endif 6810188067Srrsstatic void 6811188067Srrssctp_recv_udp_tunneled_packet(struct mbuf *m, int off, struct inpcb *ignored) 6812188067Srrs{ 6813188067Srrs struct ip *iph; 6814252944Stuexen 6815252944Stuexen#ifdef INET6 6816252944Stuexen struct ip6_hdr *ip6; 6817252944Stuexen 6818252944Stuexen#endif 6819188067Srrs struct mbuf *sp, *last; 6820188067Srrs struct udphdr *uhdr; 6821237912Stuexen uint16_t port; 6822188067Srrs 6823188067Srrs if ((m->m_flags & M_PKTHDR) == 0) { 6824188067Srrs /* Can't handle one that is not a pkt hdr */ 6825188067Srrs goto out; 6826188067Srrs } 6827237912Stuexen /* Pull the src port */ 6828188067Srrs iph = mtod(m, struct ip *); 6829188067Srrs uhdr = (struct udphdr *)((caddr_t)iph + off); 6830188067Srrs port = uhdr->uh_sport; 6831237912Stuexen /* 6832237912Stuexen * Split out the mbuf chain. Leave the IP header in m, place the 6833237912Stuexen * rest in the sp. 6834237912Stuexen */ 6835188067Srrs sp = m_split(m, off, M_DONTWAIT); 6836188067Srrs if (sp == NULL) { 6837188067Srrs /* Gak, drop packet, we can't do a split */ 6838188067Srrs goto out; 6839188067Srrs } 6840237912Stuexen if (sp->m_pkthdr.len < sizeof(struct udphdr) + sizeof(struct sctphdr)) { 6841237912Stuexen /* Gak, packet can't have an SCTP header in it - too small */ 6842188067Srrs m_freem(sp); 6843188067Srrs goto out; 6844188067Srrs } 6845237912Stuexen /* Now pull up the UDP header and SCTP header together */ 6846237912Stuexen sp = m_pullup(sp, sizeof(struct udphdr) + sizeof(struct sctphdr)); 6847188067Srrs if (sp == NULL) { 6848188067Srrs /* Gak pullup failed */ 6849188067Srrs goto out; 6850188067Srrs } 6851237912Stuexen /* Trim out the UDP header */ 6852188067Srrs m_adj(sp, sizeof(struct udphdr)); 6853188067Srrs 6854188067Srrs /* Now reconstruct the mbuf chain */ 6855237912Stuexen for (last = m; last->m_next; last = last->m_next); 6856188067Srrs last->m_next = sp; 6857188067Srrs m->m_pkthdr.len += sp->m_pkthdr.len; 6858188067Srrs iph = mtod(m, struct ip *); 6859188067Srrs switch (iph->ip_v) { 6860221249Stuexen#ifdef INET 6861188067Srrs case IPVERSION: 6862237912Stuexen iph->ip_len -= sizeof(struct udphdr); 6863237912Stuexen sctp_input_with_port(m, off, port); 6864237912Stuexen break; 6865221249Stuexen#endif 6866188067Srrs#ifdef INET6 6867188067Srrs case IPV6_VERSION >> 4: 6868252944Stuexen ip6 = mtod(m, struct ip6_hdr *); 6869252944Stuexen ip6->ip6_plen = htons(ntohs(ip6->ip6_plen) - sizeof(struct udphdr)); 6870252944Stuexen sctp6_input_with_port(&m, &off, port); 6871237912Stuexen break; 6872188067Srrs#endif 6873188067Srrs default: 6874237912Stuexen goto out; 6875237912Stuexen break; 6876188067Srrs } 6877188067Srrs return; 6878188067Srrsout: 6879188067Srrs m_freem(m); 6880188067Srrs} 6881188067Srrs 6882221328Stuexenvoid 6883179157Srrssctp_over_udp_stop(void) 6884179157Srrs{ 6885188067Srrs /* 6886188067Srrs * This function assumes sysctl caller holds sctp_sysctl_info_lock() 6887188067Srrs * for writting! 6888188067Srrs */ 6889252944Stuexen#ifdef INET 6890252944Stuexen if (SCTP_BASE_INFO(udp4_tun_socket) != NULL) { 6891252944Stuexen soclose(SCTP_BASE_INFO(udp4_tun_socket)); 6892252944Stuexen SCTP_BASE_INFO(udp4_tun_socket) = NULL; 6893188067Srrs } 6894252944Stuexen#endif 6895252944Stuexen#ifdef INET6 6896252944Stuexen if (SCTP_BASE_INFO(udp6_tun_socket) != NULL) { 6897252944Stuexen soclose(SCTP_BASE_INFO(udp6_tun_socket)); 6898252944Stuexen SCTP_BASE_INFO(udp6_tun_socket) = NULL; 6899252944Stuexen } 6900252944Stuexen#endif 6901179157Srrs} 6902221328Stuexen 6903221328Stuexenint 6904179157Srrssctp_over_udp_start(void) 6905179157Srrs{ 6906188067Srrs uint16_t port; 6907188067Srrs int ret; 6908252944Stuexen 6909252944Stuexen#ifdef INET 6910188067Srrs struct sockaddr_in sin; 6911188067Srrs 6912252944Stuexen#endif 6913252944Stuexen#ifdef INET6 6914252944Stuexen struct sockaddr_in6 sin6; 6915252944Stuexen 6916252944Stuexen#endif 6917188067Srrs /* 6918188067Srrs * This function assumes sysctl caller holds sctp_sysctl_info_lock() 6919188067Srrs * for writting! 6920188067Srrs */ 6921188067Srrs port = SCTP_BASE_SYSCTL(sctp_udp_tunneling_port); 6922252944Stuexen if (ntohs(port) == 0) { 6923188067Srrs /* Must have a port set */ 6924188067Srrs return (EINVAL); 6925188067Srrs } 6926252944Stuexen#ifdef INET 6927252944Stuexen if (SCTP_BASE_INFO(udp4_tun_socket) != NULL) { 6928188067Srrs /* Already running -- must stop first */ 6929188067Srrs return (EALREADY); 6930188067Srrs } 6931252944Stuexen#endif 6932252944Stuexen#ifdef INET6 6933252944Stuexen if (SCTP_BASE_INFO(udp6_tun_socket) != NULL) { 6934252944Stuexen /* Already running -- must stop first */ 6935252944Stuexen return (EALREADY); 6936252944Stuexen } 6937252944Stuexen#endif 6938252944Stuexen#ifdef INET 6939252944Stuexen if ((ret = socreate(PF_INET, &SCTP_BASE_INFO(udp4_tun_socket), 6940252944Stuexen SOCK_DGRAM, IPPROTO_UDP, 6941252944Stuexen curthread->td_ucred, curthread))) { 6942252944Stuexen sctp_over_udp_stop(); 6943188067Srrs return (ret); 6944188067Srrs } 6945252944Stuexen /* Call the special UDP hook. */ 6946252944Stuexen if ((ret = udp_set_kernel_tunneling(SCTP_BASE_INFO(udp4_tun_socket), 6947252944Stuexen sctp_recv_udp_tunneled_packet))) { 6948252944Stuexen sctp_over_udp_stop(); 6949252944Stuexen return (ret); 6950188067Srrs } 6951252944Stuexen /* Ok, we have a socket, bind it to the port. */ 6952252944Stuexen memset(&sin, 0, sizeof(struct sockaddr_in)); 6953252944Stuexen sin.sin_len = sizeof(struct sockaddr_in); 6954188067Srrs sin.sin_family = AF_INET; 6955188067Srrs sin.sin_port = htons(port); 6956252944Stuexen if ((ret = sobind(SCTP_BASE_INFO(udp4_tun_socket), 6957252944Stuexen (struct sockaddr *)&sin, curthread))) { 6958188067Srrs sctp_over_udp_stop(); 6959188067Srrs return (ret); 6960188067Srrs } 6961252944Stuexen#endif 6962252944Stuexen#ifdef INET6 6963252944Stuexen if ((ret = socreate(PF_INET6, &SCTP_BASE_INFO(udp6_tun_socket), 6964252944Stuexen SOCK_DGRAM, IPPROTO_UDP, 6965252944Stuexen curthread->td_ucred, curthread))) { 6966252944Stuexen sctp_over_udp_stop(); 6967252944Stuexen return (ret); 6968252944Stuexen } 6969252944Stuexen /* Call the special UDP hook. */ 6970252944Stuexen if ((ret = udp_set_kernel_tunneling(SCTP_BASE_INFO(udp6_tun_socket), 6971252944Stuexen sctp_recv_udp_tunneled_packet))) { 6972252944Stuexen sctp_over_udp_stop(); 6973252944Stuexen return (ret); 6974252944Stuexen } 6975252944Stuexen /* Ok, we have a socket, bind it to the port. */ 6976252944Stuexen memset(&sin6, 0, sizeof(struct sockaddr_in6)); 6977252944Stuexen sin6.sin6_len = sizeof(struct sockaddr_in6); 6978252944Stuexen sin6.sin6_family = AF_INET6; 6979252944Stuexen sin6.sin6_port = htons(port); 6980252944Stuexen if ((ret = sobind(SCTP_BASE_INFO(udp6_tun_socket), 6981252944Stuexen (struct sockaddr *)&sin6, curthread))) { 6982252944Stuexen sctp_over_udp_stop(); 6983252944Stuexen return (ret); 6984252944Stuexen } 6985252944Stuexen#endif 6986188067Srrs return (0); 6987179157Srrs} 6988