1 /*- 2 * Copyright (c) 2001-2006, Cisco Systems, Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are met: 6 * 7 * a) Redistributions of source code must retain the above copyright notice, 8 * this list of conditions and the following disclaimer. 9 * 10 * b) Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in 12 * the documentation and/or other materials provided with the distribution. 13 * 14 * c) Neither the name of Cisco Systems, Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived 16 * from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 20 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 28 * THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 /* $KAME: sctp_var.h,v 1.24 2005/03/06 16:04:19 itojun Exp $ */ 32 33 #include <sys/cdefs.h> 34 __FBSDID("$FreeBSD$"); 35 36 #ifndef _NETINET_SCTP_VAR_H_ 37 #define _NETINET_SCTP_VAR_H_ 38 39 #include <sys/socketvar.h> 40 #include <netinet/sctp_uio.h> 41 42 /* SCTP Kernel structures */ 43 44 /* 45 * Names for SCTP sysctl objects 46 */ 47 #define SCTPCTL_MAXDGRAM 1 /* max datagram size */ 48 #define SCTPCTL_RECVSPACE 2 /* default receive buffer space */ 49 #define SCTPCTL_AUTOASCONF 3 /* auto asconf enable/disable flag */ 50 #define SCTPCTL_ECN_ENABLE 4 /* Is ecn allowed */ 51 #define SCTPCTL_ECN_NONCE 5 /* Is ecn nonce allowed */ 52 #define SCTPCTL_STRICT_SACK 6 /* strictly require sack'd TSN's to be 53 * smaller than sndnxt. */ 54 #define SCTPCTL_NOCSUM_LO 7 /* Require that the Loopback NOT have 55 * the crc32 checksum on packets 56 * routed over it. */ 57 #define SCTPCTL_STRICT_INIT 8 58 #define SCTPCTL_PEER_CHK_OH 9 59 #define SCTPCTL_MAXBURST 10 60 #define SCTPCTL_MAXCHUNKONQ 11 61 #define SCTPCTL_DELAYED_SACK 12 62 #define SCTPCTL_HB_INTERVAL 13 63 #define SCTPCTL_PMTU_RAISE 14 64 #define SCTPCTL_SHUTDOWN_GUARD 15 65 #define SCTPCTL_SECRET_LIFETIME 16 66 #define SCTPCTL_RTO_MAX 17 67 #define SCTPCTL_RTO_MIN 18 68 #define SCTPCTL_RTO_INITIAL 19 69 #define SCTPCTL_INIT_RTO_MAX 20 70 #define SCTPCTL_COOKIE_LIFE 21 71 #define SCTPCTL_INIT_RTX_MAX 22 72 #define SCTPCTL_ASSOC_RTX_MAX 23 73 #define SCTPCTL_PATH_RTX_MAX 24 74 #define SCTPCTL_NR_OUTGOING_STREAMS 25 75 #define SCTPCTL_CMT_ON_OFF 26 76 #define SCTPCTL_CWND_MAXBURST 27 77 #define SCTPCTL_EARLY_FR 28 78 #define SCTPCTL_RTTVAR_CC 29 79 #define SCTPCTL_DEADLOCK_DET 30 80 #define SCTPCTL_EARLY_FR_MSEC 31 81 #define SCTPCTL_ASCONF_AUTH_NOCHK 32 82 #define SCTPCTL_AUTH_DISABLE 33 83 #define SCTPCTL_AUTH_RANDOM_LEN 34 84 #define SCTPCTL_AUTH_HMAC_ID 35 85 #define SCTPCTL_ABC_L_VAR 36 86 #define SCTPCTL_MAX_MBUF_CHAIN 37 87 #define SCTPCTL_CMT_USE_DAC 38 88 #define SCTPCTL_DO_DRAIN 39 89 #define SCTPCTL_WARM_CRC32 40 90 #define SCTPCTL_QLIMIT_ABORT 41 91 #define SCTPCTL_STRICT_ORDER 42 92 #define SCTPCTL_TCBHASHSIZE 43 93 #define SCTPCTL_PCBHASHSIZE 44 94 #define SCTPCTL_CHUNKSCALE 45 95 #define SCTPCTL_MINSPLIT 46 96 #define SCTPCTL_ADD_MORE 47 97 #define SCTPCTL_SYS_RESC 48 98 #define SCTPCTL_ASOC_RESC 49 99 #ifdef SCTP_DEBUG 100 #define SCTPCTL_DEBUG 50 101 #define SCTPCTL_MAXID 50 102 #else 103 #define SCTPCTL_MAXID 49 104 #endif 105 106 #ifdef SCTP_DEBUG 107 #define SCTPCTL_NAMES { \ 108 { 0, 0 }, \ 109 { "sendspace", CTLTYPE_INT }, \ 110 { "recvspace", CTLTYPE_INT }, \ 111 { "autoasconf", CTLTYPE_INT }, \ 112 { "ecn_enable", CTLTYPE_INT }, \ 113 { "ecn_nonce", CTLTYPE_INT }, \ 114 { "strict_sack", CTLTYPE_INT }, \ 115 { "looback_nocsum", CTLTYPE_INT }, \ 116 { "strict_init", CTLTYPE_INT }, \ 117 { "peer_chkoh", CTLTYPE_INT }, \ 118 { "maxburst", CTLTYPE_INT }, \ 119 { "maxchunks", CTLTYPE_INT }, \ 120 { "delayed_sack_time", CTLTYPE_INT }, \ 121 { "heartbeat_interval", CTLTYPE_INT }, \ 122 { "pmtu_raise_time", CTLTYPE_INT }, \ 123 { "shutdown_guard_time", CTLTYPE_INT }, \ 124 { "secret_lifetime", CTLTYPE_INT }, \ 125 { "rto_max", CTLTYPE_INT }, \ 126 { "rto_min", CTLTYPE_INT }, \ 127 { "rto_initial", CTLTYPE_INT }, \ 128 { "init_rto_max", CTLTYPE_INT }, \ 129 { "valid_cookie_life", CTLTYPE_INT }, \ 130 { "init_rtx_max", CTLTYPE_INT }, \ 131 { "assoc_rtx_max", CTLTYPE_INT }, \ 132 { "path_rtx_max", CTLTYPE_INT }, \ 133 { "nr_outgoing_streams", CTLTYPE_INT }, \ 134 { "cmt_on_off", CTLTYPE_INT }, \ 135 { "cwnd_maxburst", CTLTYPE_INT }, \ 136 { "early_fast_retran", CTLTYPE_INT }, \ 137 { "use_rttvar_congctrl", CTLTYPE_INT }, \ 138 { "deadlock_detect", CTLTYPE_INT }, \ 139 { "early_fast_retran_msec", CTLTYPE_INT }, \ 140 { "asconf_auth_nochk", CTLTYPE_INT }, \ 141 { "auth_disable", CTLTYPE_INT }, \ 142 { "auth_random_len", CTLTYPE_INT }, \ 143 { "auth_hmac_id", CTLTYPE_INT }, \ 144 { "abc_l_var", CTLTYPE_INT }, \ 145 { "max_mbuf_chain", CTLTYPE_INT }, \ 146 { "cmt_use_dac", CTLTYPE_INT }, \ 147 { "do_sctp_drain", CTLTYPE_INT }, \ 148 { "warm_crc_table", CTLTYPE_INT }, \ 149 { "abort_at_limit", CTLTYPE_INT }, \ 150 { "strict_data_order", CTLTYPE_INT }, \ 151 { "tcbhashsize", CTLTYPE_INT }, \ 152 { "pcbhashsize", CTLTYPE_INT }, \ 153 { "chunkscale", CTLTYPE_INT }, \ 154 { "min_split_point", CTLTYPE_INT }, \ 155 { "add_more_on_output", CTLTYPE_INT }, \ 156 { "sys_resource", CTLTYPE_INT }, \ 157 { "asoc_resource", CTLTYPE_INT }, \ 158 { "debug", CTLTYPE_INT }, \ 159 } 160 #else 161 #define SCTPCTL_NAMES { \ 162 { 0, 0 }, \ 163 { "sendspace", CTLTYPE_INT }, \ 164 { "recvspace", CTLTYPE_INT }, \ 165 { "autoasconf", CTLTYPE_INT }, \ 166 { "ecn_enable", CTLTYPE_INT }, \ 167 { "ecn_nonce", CTLTYPE_INT }, \ 168 { "strict_sack", CTLTYPE_INT }, \ 169 { "looback_nocsum", CTLTYPE_INT }, \ 170 { "strict_init", CTLTYPE_INT }, \ 171 { "peer_chkoh", CTLTYPE_INT }, \ 172 { "maxburst", CTLTYPE_INT }, \ 173 { "maxchunks", CTLTYPE_INT }, \ 174 { "delayed_sack_time", CTLTYPE_INT }, \ 175 { "heartbeat_interval", CTLTYPE_INT }, \ 176 { "pmtu_raise_time", CTLTYPE_INT }, \ 177 { "shutdown_guard_time", CTLTYPE_INT }, \ 178 { "secret_lifetime", CTLTYPE_INT }, \ 179 { "rto_max", CTLTYPE_INT }, \ 180 { "rto_min", CTLTYPE_INT }, \ 181 { "rto_initial", CTLTYPE_INT }, \ 182 { "init_rto_max", CTLTYPE_INT }, \ 183 { "valid_cookie_life", CTLTYPE_INT }, \ 184 { "init_rtx_max", CTLTYPE_INT }, \ 185 { "assoc_rtx_max", CTLTYPE_INT }, \ 186 { "path_rtx_max", CTLTYPE_INT }, \ 187 { "nr_outgoing_streams", CTLTYPE_INT }, \ 188 { "cmt_on_off", CTLTYPE_INT }, \ 189 { "cwnd_maxburst", CTLTYPE_INT }, \ 190 { "early_fast_retran", CTLTYPE_INT }, \ 191 { "use_rttvar_congctrl", CTLTYPE_INT }, \ 192 { "deadlock_detect", CTLTYPE_INT }, \ 193 { "early_fast_retran_msec", CTLTYPE_INT }, \ 194 { "asconf_auth_nochk", CTLTYPE_INT }, \ 195 { "auth_disable", CTLTYPE_INT }, \ 196 { "auth_random_len", CTLTYPE_INT }, \ 197 { "auth_hmac_id", CTLTYPE_INT }, \ 198 { "abc_l_var", CTLTYPE_INT }, \ 199 { "max_mbuf_chain", CTLTYPE_INT }, \ 200 { "cmt_use_dac", CTLTYPE_INT }, \ 201 { "do_sctp_drain", CTLTYPE_INT }, \ 202 { "warm_crc_table", CTLTYPE_INT }, \ 203 { "abort_at_limit", CTLTYPE_INT }, \ 204 { "strict_data_order", CTLTYPE_INT }, \ 205 { "tcbhashsize", CTLTYPE_INT }, \ 206 { "pcbhashsize", CTLTYPE_INT }, \ 207 { "chunkscale", CTLTYPE_INT }, \ 208 { "min_split_point", CTLTYPE_INT }, \ 209 { "add_more_on_output", CTLTYPE_INT }, \ 210 { "sys_resource", CTLTYPE_INT }, \ 211 { "asoc_resource", CTLTYPE_INT }, \ 212 } 213 #endif 214 215 216 217 218 #if defined(_KERNEL) 219 220 #ifdef SYSCTL_DECL 221 SYSCTL_DECL(_net_inet_sctp); 222 #endif 223 extern struct pr_usrreqs sctp_usrreqs; 224 225 226 #define sctp_feature_on(inp, feature) (inp->sctp_features |= feature) 227 #define sctp_feature_off(inp, feature) (inp->sctp_features &= ~feature) 228 #define sctp_is_feature_on(inp, feature) (inp->sctp_features & feature) 229 #define sctp_is_feature_off(inp, feature) ((inp->sctp_features & feature) == 0) 230 231 #define sctp_sbspace(asoc, sb) ((long) (((sb)->sb_hiwat > (asoc)->sb_cc) ? ((sb)->sb_hiwat - (asoc)->sb_cc) : 0)) 232 233 #define sctp_sbspace_failedmsgs(sb) ((long) (((sb)->sb_hiwat > (sb)->sb_cc) ? ((sb)->sb_hiwat - (sb)->sb_cc) : 0)) 234 235 #define sctp_sbspace_sub(a,b) ((a > b) ? (a - b) : 0) 236 237 extern uint32_t sctp_asoc_free_resc_limit; 238 extern uint32_t sctp_system_free_resc_limit; 239 240 /* I tried to cache the readq entries at one 241 * point. But the reality is that it did not 242 * add any performance since this meant 243 * we had to lock the STCB on read. And at that point 244 * once you have to do an extra lock, it really does 245 * not matter if the lock is in the ZONE stuff or 246 * in our code. Note that this same problem would 247 * occur with an mbuf cache as well so it is 248 * not really worth doing, at least right now :-D 249 */ 250 251 #define sctp_free_a_readq(_stcb, _readq) { \ 252 SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_readq, (_readq)); \ 253 SCTP_DECR_READQ_COUNT(); \ 254 } 255 256 #define sctp_alloc_a_readq(_stcb, _readq) { \ 257 (_readq) = (struct sctp_queued_to_read *)SCTP_ZONE_GET(sctppcbinfo.ipi_zone_readq); \ 258 if ((_readq)) { \ 259 SCTP_INCR_READQ_COUNT(); \ 260 } \ 261 } 262 263 264 265 #define sctp_free_a_strmoq(_stcb, _strmoq) { \ 266 if (((_stcb)->asoc.free_strmoq_cnt > sctp_asoc_free_resc_limit) || \ 267 (sctppcbinfo.ipi_free_strmoq > sctp_system_free_resc_limit)) { \ 268 SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_strmoq, (_strmoq)); \ 269 SCTP_DECR_STRMOQ_COUNT(); \ 270 } else { \ 271 TAILQ_INSERT_TAIL(&(_stcb)->asoc.free_strmoq, (_strmoq), next); \ 272 (_stcb)->asoc.free_strmoq_cnt++; \ 273 atomic_add_int(&sctppcbinfo.ipi_free_strmoq, 1); \ 274 } \ 275 } 276 277 #define sctp_alloc_a_strmoq(_stcb, _strmoq) { \ 278 if(TAILQ_EMPTY(&(_stcb)->asoc.free_strmoq)) { \ 279 (_strmoq) = (struct sctp_stream_queue_pending *)SCTP_ZONE_GET(sctppcbinfo.ipi_zone_strmoq); \ 280 if ((_strmoq)) { \ 281 SCTP_INCR_STRMOQ_COUNT(); \ 282 } \ 283 } else { \ 284 (_strmoq) = TAILQ_FIRST(&(_stcb)->asoc.free_strmoq); \ 285 TAILQ_REMOVE(&(_stcb)->asoc.free_strmoq, (_strmoq), next); \ 286 atomic_subtract_int(&sctppcbinfo.ipi_free_strmoq, 1); \ 287 (_stcb)->asoc.free_strmoq_cnt--; \ 288 } \ 289 } 290 291 292 #define sctp_free_a_chunk(_stcb, _chk) { \ 293 if (((_stcb)->asoc.free_chunk_cnt > sctp_asoc_free_resc_limit) || \ 294 (sctppcbinfo.ipi_free_chunks > sctp_system_free_resc_limit)) { \ 295 SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_chunk, (_chk)); \ 296 SCTP_DECR_CHK_COUNT(); \ 297 } else { \ 298 TAILQ_INSERT_TAIL(&(_stcb)->asoc.free_chunks, (_chk), sctp_next); \ 299 (_stcb)->asoc.free_chunk_cnt++; \ 300 atomic_add_int(&sctppcbinfo.ipi_free_chunks, 1); \ 301 } \ 302 } 303 304 #define sctp_alloc_a_chunk(_stcb, _chk) { \ 305 if(TAILQ_EMPTY(&(_stcb)->asoc.free_chunks)) { \ 306 (_chk) = (struct sctp_tmit_chunk *)SCTP_ZONE_GET(sctppcbinfo.ipi_zone_chunk); \ 307 if ((_chk)) { \ 308 SCTP_INCR_CHK_COUNT(); \ 309 } \ 310 } else { \ 311 (_chk) = TAILQ_FIRST(&(_stcb)->asoc.free_chunks); \ 312 TAILQ_REMOVE(&(_stcb)->asoc.free_chunks, (_chk), sctp_next); \ 313 atomic_subtract_int(&sctppcbinfo.ipi_free_chunks, 1); \ 314 (_stcb)->asoc.free_chunk_cnt--; \ 315 } \ 316 } 317 318 319 320 321 322 #define sctp_free_remote_addr(__net) { \ 323 if ((__net)) { \ 324 if (atomic_fetchadd_int(&(__net)->ref_count, -1) == 1) { \ 325 callout_stop(&(__net)->rxt_timer.timer); \ 326 callout_stop(&(__net)->pmtu_timer.timer); \ 327 callout_stop(&(__net)->fr_timer.timer); \ 328 (__net)->dest_state = SCTP_ADDR_NOT_REACHABLE; \ 329 SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_net, (__net)); \ 330 SCTP_DECR_RADDR_COUNT(); \ 331 } \ 332 } \ 333 } 334 335 336 #define sctp_sbfree(ctl, stcb, sb, m) { \ 337 uint32_t val; \ 338 val = atomic_fetchadd_int(&(sb)->sb_cc,-((m)->m_len)); \ 339 if(val < (m)->m_len) { \ 340 panic("sb_cc goes negative"); \ 341 } \ 342 val = atomic_fetchadd_int(&(sb)->sb_mbcnt,-(MSIZE)); \ 343 if(val < MSIZE) { \ 344 panic("sb_mbcnt goes negative"); \ 345 } \ 346 if ((m)->m_flags & M_EXT) { \ 347 val = atomic_fetchadd_int(&(sb)->sb_mbcnt,-((m)->m_ext.ext_size)); \ 348 if(val < (m)->m_ext.ext_size) { \ 349 panic("sb_mbcnt goes negative2"); \ 350 } \ 351 } \ 352 if (((ctl)->do_not_ref_stcb == 0) && stcb) {\ 353 val = atomic_fetchadd_int(&(stcb)->asoc.sb_cc,-((m)->m_len)); \ 354 if(val < (m)->m_len) {\ 355 panic("stcb->sb_cc goes negative"); \ 356 } \ 357 val = atomic_fetchadd_int(&(stcb)->asoc.sb_mbcnt,-(MSIZE)); \ 358 if(val < MSIZE) { \ 359 panic("asoc->mbcnt goes negative"); \ 360 } \ 361 if ((m)->m_flags & M_EXT) { \ 362 val = atomic_fetchadd_int(&(stcb)->asoc.sb_mbcnt,-((m)->m_ext.ext_size)); \ 363 if(val < (m)->m_ext.ext_size) { \ 364 panic("assoc stcb->mbcnt would go negative"); \ 365 } \ 366 } \ 367 } \ 368 if ((m)->m_type != MT_DATA && (m)->m_type != MT_HEADER && \ 369 (m)->m_type != MT_OOBDATA) \ 370 atomic_subtract_int(&(sb)->sb_ctl,(m)->m_len); \ 371 } 372 373 374 #define sctp_sballoc(stcb, sb, m) { \ 375 atomic_add_int(&(sb)->sb_cc,(m)->m_len); \ 376 atomic_add_int(&(sb)->sb_mbcnt, MSIZE); \ 377 if ((m)->m_flags & M_EXT) \ 378 atomic_add_int(&(sb)->sb_mbcnt,(m)->m_ext.ext_size); \ 379 if(stcb) { \ 380 atomic_add_int(&(stcb)->asoc.sb_cc,(m)->m_len); \ 381 atomic_add_int(&(stcb)->asoc.sb_mbcnt, MSIZE); \ 382 if ((m)->m_flags & M_EXT) \ 383 atomic_add_int(&(stcb)->asoc.sb_mbcnt,(m)->m_ext.ext_size); \ 384 } \ 385 if ((m)->m_type != MT_DATA && (m)->m_type != MT_HEADER && \ 386 (m)->m_type != MT_OOBDATA) \ 387 atomic_add_int(&(sb)->sb_ctl,(m)->m_len); \ 388 } 389 390 391 #define sctp_ucount_incr(val) { \ 392 val++; \ 393 } 394 395 #define sctp_ucount_decr(val) { \ 396 if (val > 0) { \ 397 val--; \ 398 } else { \ 399 val = 0; \ 400 } \ 401 } 402 403 #define sctp_mbuf_crush(data) do { \ 404 struct mbuf *_m; \ 405 _m = (data); \ 406 while(_m && (_m->m_len == 0)) { \ 407 (data) = _m->m_next; \ 408 _m->m_next = NULL; \ 409 sctp_m_free(_m); \ 410 _m = (data); \ 411 } \ 412 } while (0) 413 414 415 extern int sctp_sendspace; 416 extern int sctp_recvspace; 417 extern int sctp_ecn_enable; 418 extern int sctp_ecn_nonce; 419 extern int sctp_use_cwnd_based_maxburst; 420 extern unsigned int sctp_cmt_on_off; 421 extern unsigned int sctp_cmt_use_dac; 422 extern unsigned int sctp_cmt_sockopt_on_off; 423 struct sctp_nets; 424 struct sctp_inpcb; 425 struct sctp_tcb; 426 struct sctphdr; 427 428 429 void sctp_ctlinput __P((int, struct sockaddr *, void *)); 430 int sctp_ctloutput __P((struct socket *, struct sockopt *)); 431 void sctp_input __P((struct mbuf *, int)); 432 433 void sctp_drain __P((void)); 434 void sctp_init __P((void)); 435 436 int sctp_shutdown __P((struct socket *)); 437 void sctp_notify 438 __P((struct sctp_inpcb *, int, struct sctphdr *, 439 struct sockaddr *, struct sctp_tcb *, 440 struct sctp_nets *)); 441 442 #if defined(INET6) 443 void ip_2_ip6_hdr __P((struct ip6_hdr *, struct ip *)); 444 445 #endif 446 447 int sctp_bindx(struct socket *, int, struct sockaddr_storage *, 448 int, int, struct proc *); 449 450 /* can't use sctp_assoc_t here */ 451 int sctp_peeloff(struct socket *, struct socket *, int, caddr_t, int *); 452 453 454 sctp_assoc_t sctp_getassocid(struct sockaddr *); 455 456 457 458 int sctp_ingetaddr(struct socket *, 459 struct sockaddr ** 460 ); 461 462 int sctp_peeraddr(struct socket *, 463 struct sockaddr ** 464 ); 465 466 int sctp_listen(struct socket *, int, struct thread *); 467 468 469 int sctp_accept(struct socket *, struct sockaddr **); 470 471 472 473 474 #endif /* _KERNEL */ 475 476 #endif /* !_NETINET_SCTP_VAR_H_ */ 477