sctp_var.h (15956B)
1 /*- 2 * SPDX-License-Identifier: BSD-3-Clause 3 * 4 * Copyright (c) 2001-2008, by Cisco Systems, Inc. All rights reserved. 5 * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved. 6 * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions are met: 10 * 11 * a) Redistributions of source code must retain the above copyright notice, 12 * this list of conditions and the following disclaimer. 13 * 14 * b) Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in 16 * the documentation and/or other materials provided with the distribution. 17 * 18 * c) Neither the name of Cisco Systems, Inc. nor the names of its 19 * contributors may be used to endorse or promote products derived 20 * from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 24 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 26 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 32 * THE POSSIBILITY OF SUCH DAMAGE. 33 */ 34 35 #ifndef _NETINET_SCTP_VAR_H_ 36 #define _NETINET_SCTP_VAR_H_ 37 38 #include <netinet/sctp_uio.h> 39 40 #if defined(_KERNEL) || defined(__Userspace__) 41 42 #if !defined(__Userspace__) 43 #if defined(__FreeBSD__) 44 extern struct protosw sctp_seqpacket_protosw, sctp_stream_protosw; 45 #else 46 extern struct pr_usrreqs sctp_usrreqs; 47 #endif 48 #endif 49 50 #define sctp_feature_on(inp, feature) (inp->sctp_features |= feature) 51 #define sctp_feature_off(inp, feature) (inp->sctp_features &= ~feature) 52 #define sctp_is_feature_on(inp, feature) ((inp->sctp_features & feature) == feature) 53 #define sctp_is_feature_off(inp, feature) ((inp->sctp_features & feature) == 0) 54 55 #define sctp_stcb_feature_on(inp, stcb, feature) {\ 56 if (stcb) { \ 57 stcb->asoc.sctp_features |= feature; \ 58 } else if (inp) { \ 59 inp->sctp_features |= feature; \ 60 } \ 61 } 62 #define sctp_stcb_feature_off(inp, stcb, feature) {\ 63 if (stcb) { \ 64 stcb->asoc.sctp_features &= ~feature; \ 65 } else if (inp) { \ 66 inp->sctp_features &= ~feature; \ 67 } \ 68 } 69 #define sctp_stcb_is_feature_on(inp, stcb, feature) \ 70 (((stcb != NULL) && \ 71 ((stcb->asoc.sctp_features & feature) == feature)) || \ 72 ((stcb == NULL) && (inp != NULL) && \ 73 ((inp->sctp_features & feature) == feature))) 74 #define sctp_stcb_is_feature_off(inp, stcb, feature) \ 75 (((stcb != NULL) && \ 76 ((stcb->asoc.sctp_features & feature) == 0)) || \ 77 ((stcb == NULL) && (inp != NULL) && \ 78 ((inp->sctp_features & feature) == 0)) || \ 79 ((stcb == NULL) && (inp == NULL))) 80 81 /* managing mobility_feature in inpcb (by micchie) */ 82 #define sctp_mobility_feature_on(inp, feature) (inp->sctp_mobility_features |= feature) 83 #define sctp_mobility_feature_off(inp, feature) (inp->sctp_mobility_features &= ~feature) 84 #define sctp_is_mobility_feature_on(inp, feature) (inp->sctp_mobility_features & feature) 85 #define sctp_is_mobility_feature_off(inp, feature) ((inp->sctp_mobility_features & feature) == 0) 86 87 #define sctp_maxspace(sb) (max((sb)->sb_hiwat,SCTP_MINIMAL_RWND)) 88 89 #define sctp_sbspace(asoc, sb) ((long) ((sctp_maxspace(sb) > (asoc)->sb_cc) ? (sctp_maxspace(sb) - (asoc)->sb_cc) : 0)) 90 91 #define sctp_sbspace_failedmsgs(sb) ((long) ((sctp_maxspace(sb) > SCTP_SBAVAIL(sb)) ? (sctp_maxspace(sb) - SCTP_SBAVAIL(sb)) : 0)) 92 93 #define sctp_sbspace_sub(a,b) (((a) > (b)) ? ((a) - (b)) : 0) 94 95 /* 96 * I tried to cache the readq entries at one point. But the reality 97 * is that it did not add any performance since this meant we had to 98 * lock the STCB on read. And at that point once you have to do an 99 * extra lock, it really does not matter if the lock is in the ZONE 100 * stuff or in our code. Note that this same problem would occur with 101 * an mbuf cache as well so it is not really worth doing, at least 102 * right now :-D 103 */ 104 #ifdef INVARIANTS 105 #define sctp_free_a_readq(_stcb, _readq) { \ 106 if ((_readq)->on_strm_q) \ 107 panic("On strm q stcb:%p readq:%p", (_stcb), (_readq)); \ 108 SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_readq), (_readq)); \ 109 SCTP_DECR_READQ_COUNT(); \ 110 } 111 #else 112 #define sctp_free_a_readq(_stcb, _readq) { \ 113 SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_readq), (_readq)); \ 114 SCTP_DECR_READQ_COUNT(); \ 115 } 116 #endif 117 118 #define sctp_alloc_a_readq(_stcb, _readq) { \ 119 (_readq) = SCTP_ZONE_GET(SCTP_BASE_INFO(ipi_zone_readq), struct sctp_queued_to_read); \ 120 if ((_readq)) { \ 121 SCTP_INCR_READQ_COUNT(); \ 122 } \ 123 } 124 125 #define sctp_free_a_strmoq(_stcb, _strmoq, _so_locked) { \ 126 if ((_strmoq)->holds_key_ref) { \ 127 sctp_auth_key_release(stcb, sp->auth_keyid, _so_locked); \ 128 (_strmoq)->holds_key_ref = 0; \ 129 } \ 130 SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_strmoq), (_strmoq)); \ 131 SCTP_DECR_STRMOQ_COUNT(); \ 132 } 133 134 #define sctp_alloc_a_strmoq(_stcb, _strmoq) { \ 135 (_strmoq) = SCTP_ZONE_GET(SCTP_BASE_INFO(ipi_zone_strmoq), struct sctp_stream_queue_pending); \ 136 if ((_strmoq)) { \ 137 memset(_strmoq, 0, sizeof(struct sctp_stream_queue_pending)); \ 138 SCTP_INCR_STRMOQ_COUNT(); \ 139 (_strmoq)->holds_key_ref = 0; \ 140 } \ 141 } 142 143 #define sctp_free_a_chunk(_stcb, _chk, _so_locked) { \ 144 if ((_chk)->holds_key_ref) {\ 145 sctp_auth_key_release((_stcb), (_chk)->auth_keyid, _so_locked); \ 146 (_chk)->holds_key_ref = 0; \ 147 } \ 148 if (_stcb) { \ 149 SCTP_TCB_LOCK_ASSERT((_stcb)); \ 150 if ((_chk)->whoTo) { \ 151 sctp_free_remote_addr((_chk)->whoTo); \ 152 (_chk)->whoTo = NULL; \ 153 } \ 154 if (((_stcb)->asoc.free_chunk_cnt > SCTP_BASE_SYSCTL(sctp_asoc_free_resc_limit)) || \ 155 (SCTP_BASE_INFO(ipi_free_chunks) > SCTP_BASE_SYSCTL(sctp_system_free_resc_limit))) { \ 156 SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_chunk), (_chk)); \ 157 SCTP_DECR_CHK_COUNT(); \ 158 } else { \ 159 TAILQ_INSERT_TAIL(&(_stcb)->asoc.free_chunks, (_chk), sctp_next); \ 160 (_stcb)->asoc.free_chunk_cnt++; \ 161 atomic_add_int(&SCTP_BASE_INFO(ipi_free_chunks), 1); \ 162 } \ 163 } else { \ 164 SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_chunk), (_chk)); \ 165 SCTP_DECR_CHK_COUNT(); \ 166 } \ 167 } 168 169 #define sctp_alloc_a_chunk(_stcb, _chk) { \ 170 if (TAILQ_EMPTY(&(_stcb)->asoc.free_chunks)) { \ 171 (_chk) = SCTP_ZONE_GET(SCTP_BASE_INFO(ipi_zone_chunk), struct sctp_tmit_chunk); \ 172 if ((_chk)) { \ 173 SCTP_INCR_CHK_COUNT(); \ 174 (_chk)->whoTo = NULL; \ 175 (_chk)->holds_key_ref = 0; \ 176 } \ 177 } else { \ 178 (_chk) = TAILQ_FIRST(&(_stcb)->asoc.free_chunks); \ 179 TAILQ_REMOVE(&(_stcb)->asoc.free_chunks, (_chk), sctp_next); \ 180 atomic_subtract_int(&SCTP_BASE_INFO(ipi_free_chunks), 1); \ 181 (_chk)->holds_key_ref = 0; \ 182 SCTP_STAT_INCR(sctps_cached_chk); \ 183 (_stcb)->asoc.free_chunk_cnt--; \ 184 } \ 185 } 186 187 #if defined(__FreeBSD__) && !defined(__Userspace__) 188 #define sctp_free_remote_addr(__net) { \ 189 if ((__net)) { \ 190 if (SCTP_DECREMENT_AND_CHECK_REFCOUNT(&(__net)->ref_count)) { \ 191 RO_NHFREE(&(__net)->ro); \ 192 if ((__net)->src_addr_selected) { \ 193 sctp_free_ifa((__net)->ro._s_addr); \ 194 (__net)->ro._s_addr = NULL; \ 195 } \ 196 (__net)->src_addr_selected = 0; \ 197 (__net)->dest_state &= ~SCTP_ADDR_REACHABLE; \ 198 SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_net), (__net)); \ 199 SCTP_DECR_RADDR_COUNT(); \ 200 } \ 201 } \ 202 } 203 204 #define sctp_sbfree(ctl, stcb, sb, m) { \ 205 SCTP_SB_DECR(sb, SCTP_BUF_LEN((m))); \ 206 SCTP_SAVE_ATOMIC_DECREMENT(&(sb)->sb_mbcnt, MSIZE); \ 207 if (((ctl)->do_not_ref_stcb == 0) && stcb) {\ 208 SCTP_SAVE_ATOMIC_DECREMENT(&(stcb)->asoc.sb_cc, SCTP_BUF_LEN((m))); \ 209 SCTP_SAVE_ATOMIC_DECREMENT(&(stcb)->asoc.my_rwnd_control_len, MSIZE); \ 210 } \ 211 if (SCTP_BUF_TYPE(m) != MT_DATA && SCTP_BUF_TYPE(m) != MT_HEADER && \ 212 SCTP_BUF_TYPE(m) != MT_OOBDATA) \ 213 atomic_subtract_int(&(sb)->sb_ctl,SCTP_BUF_LEN((m))); \ 214 } 215 216 #define sctp_sballoc(stcb, sb, m) { \ 217 SCTP_SB_INCR(sb, SCTP_BUF_LEN((m))); \ 218 atomic_add_int(&(sb)->sb_mbcnt, MSIZE); \ 219 if (stcb) { \ 220 atomic_add_int(&(stcb)->asoc.sb_cc, SCTP_BUF_LEN((m))); \ 221 atomic_add_int(&(stcb)->asoc.my_rwnd_control_len, MSIZE); \ 222 } \ 223 if (SCTP_BUF_TYPE(m) != MT_DATA && SCTP_BUF_TYPE(m) != MT_HEADER && \ 224 SCTP_BUF_TYPE(m) != MT_OOBDATA) \ 225 atomic_add_int(&(sb)->sb_ctl,SCTP_BUF_LEN((m))); \ 226 } 227 #else /* FreeBSD Version <= 500000 or non-FreeBSD */ 228 #define sctp_free_remote_addr(__net) { \ 229 if ((__net)) { \ 230 if (SCTP_DECREMENT_AND_CHECK_REFCOUNT(&(__net)->ref_count)) { \ 231 if ((__net)->ro.ro_rt) { \ 232 RTFREE((__net)->ro.ro_rt); \ 233 (__net)->ro.ro_rt = NULL; \ 234 } \ 235 if ((__net)->src_addr_selected) { \ 236 sctp_free_ifa((__net)->ro._s_addr); \ 237 (__net)->ro._s_addr = NULL; \ 238 } \ 239 (__net)->src_addr_selected = 0; \ 240 (__net)->dest_state &=~SCTP_ADDR_REACHABLE; \ 241 SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_net), (__net)); \ 242 SCTP_DECR_RADDR_COUNT(); \ 243 } \ 244 } \ 245 } 246 247 #define sctp_sbfree(ctl, stcb, sb, m) { \ 248 SCTP_SB_DECR(sb, SCTP_BUF_LEN((m))); \ 249 SCTP_SAVE_ATOMIC_DECREMENT(&(sb)->sb_mbcnt, MSIZE); \ 250 if (((ctl)->do_not_ref_stcb == 0) && stcb) { \ 251 SCTP_SAVE_ATOMIC_DECREMENT(&(stcb)->asoc.sb_cc, SCTP_BUF_LEN((m))); \ 252 SCTP_SAVE_ATOMIC_DECREMENT(&(stcb)->asoc.my_rwnd_control_len, MSIZE); \ 253 } \ 254 } 255 256 #define sctp_sballoc(stcb, sb, m) { \ 257 SCTP_SB_INCR(sb, SCTP_BUF_LEN((m))); \ 258 atomic_add_int(&(sb)->sb_mbcnt, MSIZE); \ 259 if (stcb) { \ 260 atomic_add_int(&(stcb)->asoc.sb_cc, SCTP_BUF_LEN((m))); \ 261 atomic_add_int(&(stcb)->asoc.my_rwnd_control_len, MSIZE); \ 262 } \ 263 } 264 #endif 265 266 #define sctp_ucount_incr(val) { \ 267 val++; \ 268 } 269 270 #define sctp_ucount_decr(val) { \ 271 if (val > 0) { \ 272 val--; \ 273 } else { \ 274 val = 0; \ 275 } \ 276 } 277 278 #define sctp_mbuf_crush(data) do { \ 279 struct mbuf *_m; \ 280 _m = (data); \ 281 while (_m && (SCTP_BUF_LEN(_m) == 0)) { \ 282 (data) = SCTP_BUF_NEXT(_m); \ 283 SCTP_BUF_NEXT(_m) = NULL; \ 284 sctp_m_free(_m); \ 285 _m = (data); \ 286 } \ 287 } while (0) 288 289 #define sctp_flight_size_decrease(tp1) do { \ 290 if (tp1->whoTo->flight_size >= tp1->book_size) \ 291 tp1->whoTo->flight_size -= tp1->book_size; \ 292 else \ 293 tp1->whoTo->flight_size = 0; \ 294 } while (0) 295 296 #define sctp_flight_size_increase(tp1) do { \ 297 (tp1)->whoTo->flight_size += (tp1)->book_size; \ 298 } while (0) 299 300 #ifdef SCTP_FS_SPEC_LOG 301 #define sctp_total_flight_decrease(stcb, tp1) do { \ 302 if (stcb->asoc.fs_index > SCTP_FS_SPEC_LOG_SIZE) \ 303 stcb->asoc.fs_index = 0;\ 304 stcb->asoc.fslog[stcb->asoc.fs_index].total_flight = stcb->asoc.total_flight; \ 305 stcb->asoc.fslog[stcb->asoc.fs_index].tsn = tp1->rec.data.tsn; \ 306 stcb->asoc.fslog[stcb->asoc.fs_index].book = tp1->book_size; \ 307 stcb->asoc.fslog[stcb->asoc.fs_index].sent = tp1->sent; \ 308 stcb->asoc.fslog[stcb->asoc.fs_index].incr = 0; \ 309 stcb->asoc.fslog[stcb->asoc.fs_index].decr = 1; \ 310 stcb->asoc.fs_index++; \ 311 tp1->window_probe = 0; \ 312 if (stcb->asoc.total_flight >= tp1->book_size) { \ 313 stcb->asoc.total_flight -= tp1->book_size; \ 314 if (stcb->asoc.total_flight_count > 0) \ 315 stcb->asoc.total_flight_count--; \ 316 } else { \ 317 stcb->asoc.total_flight = 0; \ 318 stcb->asoc.total_flight_count = 0; \ 319 } \ 320 } while (0) 321 322 #define sctp_total_flight_increase(stcb, tp1) do { \ 323 if (stcb->asoc.fs_index > SCTP_FS_SPEC_LOG_SIZE) \ 324 stcb->asoc.fs_index = 0;\ 325 stcb->asoc.fslog[stcb->asoc.fs_index].total_flight = stcb->asoc.total_flight; \ 326 stcb->asoc.fslog[stcb->asoc.fs_index].tsn = tp1->rec.data.tsn; \ 327 stcb->asoc.fslog[stcb->asoc.fs_index].book = tp1->book_size; \ 328 stcb->asoc.fslog[stcb->asoc.fs_index].sent = tp1->sent; \ 329 stcb->asoc.fslog[stcb->asoc.fs_index].incr = 1; \ 330 stcb->asoc.fslog[stcb->asoc.fs_index].decr = 0; \ 331 stcb->asoc.fs_index++; \ 332 (stcb)->asoc.total_flight_count++; \ 333 (stcb)->asoc.total_flight += (tp1)->book_size; \ 334 } while (0) 335 336 #else 337 338 #define sctp_total_flight_decrease(stcb, tp1) do { \ 339 tp1->window_probe = 0; \ 340 if (stcb->asoc.total_flight >= tp1->book_size) { \ 341 stcb->asoc.total_flight -= tp1->book_size; \ 342 if (stcb->asoc.total_flight_count > 0) \ 343 stcb->asoc.total_flight_count--; \ 344 } else { \ 345 stcb->asoc.total_flight = 0; \ 346 stcb->asoc.total_flight_count = 0; \ 347 } \ 348 } while (0) 349 350 #define sctp_total_flight_increase(stcb, tp1) do { \ 351 (stcb)->asoc.total_flight_count++; \ 352 (stcb)->asoc.total_flight += (tp1)->book_size; \ 353 } while (0) 354 355 #endif 356 357 #define SCTP_PF_ENABLED(_net) (_net->pf_threshold < _net->failure_threshold) 358 #define SCTP_NET_IS_PF(_net) (_net->pf_threshold < _net->error_count) 359 360 struct sctp_nets; 361 struct sctp_inpcb; 362 struct sctp_tcb; 363 struct sctphdr; 364 365 #if defined(__FreeBSD__) || defined(_WIN32) || defined(__Userspace__) 366 void sctp_close(struct socket *so); 367 #else 368 int sctp_detach(struct socket *so); 369 #endif 370 #if defined(__FreeBSD__) && !defined(__Userspace__) 371 void sctp_abort(struct socket *so); 372 #else 373 int sctp_abort(struct socket *so); 374 #endif 375 int sctp_disconnect(struct socket *so); 376 #if !defined(__Userspace__) 377 #if defined(__APPLE__) && !defined(APPLE_LEOPARD) && !defined(APPLE_SNOWLEOPARD) && !defined(APPLE_LION) && !defined(APPLE_MOUNTAINLION) && !defined(APPLE_ELCAPITAN) 378 void sctp_ctlinput(int, struct sockaddr *, void *, struct ifnet * SCTP_UNUSED); 379 #elif defined(__FreeBSD__) 380 ipproto_ctlinput_t sctp_ctlinput; 381 #else 382 void sctp_ctlinput(int, struct sockaddr *, void *); 383 #endif 384 int sctp_ctloutput(struct socket *, struct sockopt *); 385 #ifdef INET 386 void sctp_input_with_port(struct mbuf *, int, uint16_t); 387 #if defined(__FreeBSD__) && !defined(__Userspace__) 388 int sctp_input(struct mbuf **, int *, int); 389 #else 390 void sctp_input(struct mbuf *, int); 391 #endif 392 #endif 393 void sctp_pathmtu_adjustment(struct sctp_tcb *, uint32_t, bool); 394 #else 395 #if defined(__Userspace__) 396 void sctp_pathmtu_adjustment(struct sctp_tcb *, uint32_t, bool); 397 #else 398 void sctp_input(struct mbuf *,...); 399 #endif 400 void *sctp_ctlinput(int, struct sockaddr *, void *); 401 int sctp_ctloutput(int, struct socket *, int, int, struct mbuf **); 402 #endif 403 #if !(defined(__FreeBSD__) && !defined(__Userspace__)) 404 void sctp_drain(void); 405 #endif 406 #if defined(__Userspace__) 407 void sctp_init(uint16_t, 408 int (*)(void *addr, void *buffer, size_t length, uint8_t tos, uint8_t set_df), 409 void (*)(const char *, ...), int start_threads); 410 #elif defined(__APPLE__) && (!defined(APPLE_LEOPARD) && !defined(APPLE_SNOWLEOPARD) &&!defined(APPLE_LION) && !defined(APPLE_MOUNTAINLION)) 411 void sctp_init(struct protosw *pp, struct domain *dp); 412 #else 413 #if !defined(__FreeBSD__) 414 void sctp_init(void); 415 #endif 416 void sctp_notify(struct sctp_inpcb *, struct sctp_tcb *, struct sctp_nets *, 417 uint8_t, uint8_t, uint16_t, uint32_t); 418 #endif 419 #if !defined(__FreeBSD__) && !defined(__Userspace__) 420 void sctp_finish(void); 421 #endif 422 #if defined(__FreeBSD__) || defined(_WIN32) || defined(__Userspace__) 423 int sctp_flush(struct socket *, int); 424 #endif 425 int sctp_shutdown(struct socket *); 426 int sctp_bindx(struct socket *, int, struct sockaddr_storage *, 427 int, int, struct proc *); 428 /* can't use sctp_assoc_t here */ 429 int sctp_peeloff(struct socket *, struct socket *, int, caddr_t, int *); 430 #if !defined(__Userspace__) 431 int sctp_ingetaddr(struct socket *, struct sockaddr **); 432 #else 433 int sctp_ingetaddr(struct socket *, struct mbuf *); 434 #endif 435 #if !defined(__Userspace__) 436 int sctp_peeraddr(struct socket *, struct sockaddr **); 437 #else 438 int sctp_peeraddr(struct socket *, struct mbuf *); 439 #endif 440 #if defined(__FreeBSD__) && !defined(__Userspace__) 441 int sctp_listen(struct socket *, int, struct thread *); 442 #elif defined(_WIN32) && !defined(__Userspace__) 443 int sctp_listen(struct socket *, int, PKTHREAD); 444 #elif defined(__Userspace__) 445 int sctp_listen(struct socket *, int, struct proc *); 446 #else 447 int sctp_listen(struct socket *, struct proc *); 448 #endif 449 int sctp_accept(struct socket *, struct sockaddr **); 450 451 #endif /* _KERNEL */ 452 453 #endif /* !_NETINET_SCTP_VAR_H_ */