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#ifndef _NETINET_SCTP_VAR_H_ 37163953Srrs#define _NETINET_SCTP_VAR_H_ 38163953Srrs 39163953Srrs#include <netinet/sctp_uio.h> 40163953Srrs 41180387Srrs#if defined(_KERNEL) || defined(__Userspace__) 42163953Srrs 43163953Srrsextern struct pr_usrreqs sctp_usrreqs; 44163953Srrs 45163953Srrs 46163953Srrs#define sctp_feature_on(inp, feature) (inp->sctp_features |= feature) 47163953Srrs#define sctp_feature_off(inp, feature) (inp->sctp_features &= ~feature) 48181054Srrs#define sctp_is_feature_on(inp, feature) ((inp->sctp_features & feature) == feature) 49163953Srrs#define sctp_is_feature_off(inp, feature) ((inp->sctp_features & feature) == 0) 50163953Srrs 51223132Stuexen#define sctp_stcb_feature_on(inp, stcb, feature) {\ 52223132Stuexen if (stcb) { \ 53223132Stuexen stcb->asoc.sctp_features |= feature; \ 54231039Stuexen } else if (inp) { \ 55223132Stuexen inp->sctp_features |= feature; \ 56223132Stuexen } \ 57223132Stuexen} 58223132Stuexen#define sctp_stcb_feature_off(inp, stcb, feature) {\ 59223132Stuexen if (stcb) { \ 60223132Stuexen stcb->asoc.sctp_features &= ~feature; \ 61231039Stuexen } else if (inp) { \ 62223132Stuexen inp->sctp_features &= ~feature; \ 63223132Stuexen } \ 64223132Stuexen} 65223132Stuexen#define sctp_stcb_is_feature_on(inp, stcb, feature) \ 66223132Stuexen (((stcb != NULL) && \ 67223132Stuexen ((stcb->asoc.sctp_features & feature) == feature)) || \ 68231039Stuexen ((stcb == NULL) && (inp != NULL) && \ 69223132Stuexen ((inp->sctp_features & feature) == feature))) 70223132Stuexen#define sctp_stcb_is_feature_off(inp, stcb, feature) \ 71223132Stuexen (((stcb != NULL) && \ 72223132Stuexen ((stcb->asoc.sctp_features & feature) == 0)) || \ 73231039Stuexen ((stcb == NULL) && (inp != NULL) && \ 74231039Stuexen ((inp->sctp_features & feature) == 0)) || \ 75231039Stuexen ((stcb == NULL) && (inp == NULL))) 76181054Srrs 77171990Srrs/* managing mobility_feature in inpcb (by micchie) */ 78171990Srrs#define sctp_mobility_feature_on(inp, feature) (inp->sctp_mobility_features |= feature) 79171990Srrs#define sctp_mobility_feature_off(inp, feature) (inp->sctp_mobility_features &= ~feature) 80171990Srrs#define sctp_is_mobility_feature_on(inp, feature) (inp->sctp_mobility_features & feature) 81171990Srrs#define sctp_is_mobility_feature_off(inp, feature) ((inp->sctp_mobility_features & feature) == 0) 82171990Srrs 83172396Srrs#define sctp_maxspace(sb) (max((sb)->sb_hiwat,SCTP_MINIMAL_RWND)) 84163953Srrs 85172703Srrs#define sctp_sbspace(asoc, sb) ((long) ((sctp_maxspace(sb) > (asoc)->sb_cc) ? (sctp_maxspace(sb) - (asoc)->sb_cc) : 0)) 86163953Srrs 87172396Srrs#define sctp_sbspace_failedmsgs(sb) ((long) ((sctp_maxspace(sb) > (sb)->sb_cc) ? (sctp_maxspace(sb) - (sb)->sb_cc) : 0)) 88172396Srrs 89163953Srrs#define sctp_sbspace_sub(a,b) ((a > b) ? (a - b) : 0) 90163953Srrs 91167598Srrs/* 92167598Srrs * I tried to cache the readq entries at one point. But the reality 93167598Srrs * is that it did not add any performance since this meant we had to 94167598Srrs * lock the STCB on read. And at that point once you have to do an 95167598Srrs * extra lock, it really does not matter if the lock is in the ZONE 96167598Srrs * stuff or in our code. Note that this same problem would occur with 97167598Srrs * an mbuf cache as well so it is not really worth doing, at least 98167598Srrs * right now :-D 99163953Srrs */ 100163953Srrs 101163953Srrs#define sctp_free_a_readq(_stcb, _readq) { \ 102179783Srrs SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_readq), (_readq)); \ 103166675Srrs SCTP_DECR_READQ_COUNT(); \ 104163953Srrs} 105163953Srrs 106163953Srrs#define sctp_alloc_a_readq(_stcb, _readq) { \ 107179783Srrs (_readq) = SCTP_ZONE_GET(SCTP_BASE_INFO(ipi_zone_readq), struct sctp_queued_to_read); \ 108163953Srrs if ((_readq)) { \ 109163953Srrs SCTP_INCR_READQ_COUNT(); \ 110163953Srrs } \ 111163953Srrs} 112163953Srrs 113221627Stuexen#define sctp_free_a_strmoq(_stcb, _strmoq, _so_locked) { \ 114185694Srrs if ((_strmoq)->holds_key_ref) { \ 115221627Stuexen sctp_auth_key_release(stcb, sp->auth_keyid, _so_locked); \ 116185694Srrs (_strmoq)->holds_key_ref = 0; \ 117185694Srrs } \ 118179783Srrs SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_strmoq), (_strmoq)); \ 119168859Srrs SCTP_DECR_STRMOQ_COUNT(); \ 120163953Srrs} 121163953Srrs 122163953Srrs#define sctp_alloc_a_strmoq(_stcb, _strmoq) { \ 123179783Srrs (_strmoq) = SCTP_ZONE_GET(SCTP_BASE_INFO(ipi_zone_strmoq), struct sctp_stream_queue_pending); \ 124189790Srrs if ((_strmoq)) { \ 125189790Srrs memset(_strmoq, 0, sizeof(struct sctp_stream_queue_pending)); \ 126168859Srrs SCTP_INCR_STRMOQ_COUNT(); \ 127185694Srrs (_strmoq)->holds_key_ref = 0; \ 128168859Srrs } \ 129163953Srrs} 130163953Srrs 131221627Stuexen#define sctp_free_a_chunk(_stcb, _chk, _so_locked) { \ 132185694Srrs if ((_chk)->holds_key_ref) {\ 133221627Stuexen sctp_auth_key_release((_stcb), (_chk)->auth_keyid, _so_locked); \ 134185694Srrs (_chk)->holds_key_ref = 0; \ 135185694Srrs } \ 136206137Stuexen if (_stcb) { \ 137171990Srrs SCTP_TCB_LOCK_ASSERT((_stcb)); \ 138171990Srrs if ((_chk)->whoTo) { \ 139171990Srrs sctp_free_remote_addr((_chk)->whoTo); \ 140171990Srrs (_chk)->whoTo = NULL; \ 141171990Srrs } \ 142179783Srrs if (((_stcb)->asoc.free_chunk_cnt > SCTP_BASE_SYSCTL(sctp_asoc_free_resc_limit)) || \ 143179783Srrs (SCTP_BASE_INFO(ipi_free_chunks) > SCTP_BASE_SYSCTL(sctp_system_free_resc_limit))) { \ 144179783Srrs SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_chunk), (_chk)); \ 145171990Srrs SCTP_DECR_CHK_COUNT(); \ 146171990Srrs } else { \ 147171990Srrs TAILQ_INSERT_TAIL(&(_stcb)->asoc.free_chunks, (_chk), sctp_next); \ 148171990Srrs (_stcb)->asoc.free_chunk_cnt++; \ 149179783Srrs atomic_add_int(&SCTP_BASE_INFO(ipi_free_chunks), 1); \ 150171990Srrs } \ 151171990Srrs } else { \ 152179783Srrs SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_chunk), (_chk)); \ 153163953Srrs SCTP_DECR_CHK_COUNT(); \ 154166675Srrs } \ 155163953Srrs} 156163953Srrs 157163953Srrs#define sctp_alloc_a_chunk(_stcb, _chk) { \ 158234798Stuexen if (TAILQ_EMPTY(&(_stcb)->asoc.free_chunks)) { \ 159179783Srrs (_chk) = SCTP_ZONE_GET(SCTP_BASE_INFO(ipi_zone_chunk), struct sctp_tmit_chunk); \ 160166675Srrs if ((_chk)) { \ 161166675Srrs SCTP_INCR_CHK_COUNT(); \ 162171158Srrs (_chk)->whoTo = NULL; \ 163185694Srrs (_chk)->holds_key_ref = 0; \ 164166675Srrs } \ 165166675Srrs } else { \ 166166675Srrs (_chk) = TAILQ_FIRST(&(_stcb)->asoc.free_chunks); \ 167166675Srrs TAILQ_REMOVE(&(_stcb)->asoc.free_chunks, (_chk), sctp_next); \ 168179783Srrs atomic_subtract_int(&SCTP_BASE_INFO(ipi_free_chunks), 1); \ 169185694Srrs (_chk)->holds_key_ref = 0; \ 170168755Srrs SCTP_STAT_INCR(sctps_cached_chk); \ 171166675Srrs (_stcb)->asoc.free_chunk_cnt--; \ 172163953Srrs } \ 173163953Srrs} 174163953Srrs 175163953Srrs 176163953Srrs#define sctp_free_remote_addr(__net) { \ 177167598Srrs if ((__net)) { \ 178185694Srrs if (SCTP_DECREMENT_AND_CHECK_REFCOUNT(&(__net)->ref_count)) { \ 179169378Srrs (void)SCTP_OS_TIMER_STOP(&(__net)->rxt_timer.timer); \ 180169378Srrs (void)SCTP_OS_TIMER_STOP(&(__net)->pmtu_timer.timer); \ 181167598Srrs if ((__net)->ro.ro_rt) { \ 182167598Srrs RTFREE((__net)->ro.ro_rt); \ 183167598Srrs (__net)->ro.ro_rt = NULL; \ 184167598Srrs } \ 185167598Srrs if ((__net)->src_addr_selected) { \ 186167598Srrs sctp_free_ifa((__net)->ro._s_addr); \ 187167598Srrs (__net)->ro._s_addr = NULL; \ 188167598Srrs } \ 189167598Srrs (__net)->src_addr_selected = 0; \ 190224641Stuexen (__net)->dest_state &= ~SCTP_ADDR_REACHABLE; \ 191179783Srrs SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_net), (__net)); \ 192163953Srrs SCTP_DECR_RADDR_COUNT(); \ 193163953Srrs } \ 194163953Srrs } \ 195163953Srrs} 196163953Srrs 197163953Srrs#define sctp_sbfree(ctl, stcb, sb, m) { \ 198185694Srrs SCTP_SAVE_ATOMIC_DECREMENT(&(sb)->sb_cc, SCTP_BUF_LEN((m))); \ 199185694Srrs SCTP_SAVE_ATOMIC_DECREMENT(&(sb)->sb_mbcnt, MSIZE); \ 200166675Srrs if (((ctl)->do_not_ref_stcb == 0) && stcb) {\ 201185694Srrs SCTP_SAVE_ATOMIC_DECREMENT(&(stcb)->asoc.sb_cc, SCTP_BUF_LEN((m))); \ 202185694Srrs SCTP_SAVE_ATOMIC_DECREMENT(&(stcb)->asoc.my_rwnd_control_len, MSIZE); \ 203166675Srrs } \ 204165647Srrs if (SCTP_BUF_TYPE(m) != MT_DATA && SCTP_BUF_TYPE(m) != MT_HEADER && \ 205165647Srrs SCTP_BUF_TYPE(m) != MT_OOBDATA) \ 206165647Srrs atomic_subtract_int(&(sb)->sb_ctl,SCTP_BUF_LEN((m))); \ 207163953Srrs} 208163953Srrs 209163953Srrs#define sctp_sballoc(stcb, sb, m) { \ 210165647Srrs atomic_add_int(&(sb)->sb_cc,SCTP_BUF_LEN((m))); \ 211163953Srrs atomic_add_int(&(sb)->sb_mbcnt, MSIZE); \ 212166675Srrs if (stcb) { \ 213166675Srrs atomic_add_int(&(stcb)->asoc.sb_cc,SCTP_BUF_LEN((m))); \ 214171943Srrs atomic_add_int(&(stcb)->asoc.my_rwnd_control_len, MSIZE); \ 215166675Srrs } \ 216165647Srrs if (SCTP_BUF_TYPE(m) != MT_DATA && SCTP_BUF_TYPE(m) != MT_HEADER && \ 217165647Srrs SCTP_BUF_TYPE(m) != MT_OOBDATA) \ 218165647Srrs atomic_add_int(&(sb)->sb_ctl,SCTP_BUF_LEN((m))); \ 219163953Srrs} 220163953Srrs 221163953Srrs 222163953Srrs#define sctp_ucount_incr(val) { \ 223163953Srrs val++; \ 224163953Srrs} 225163953Srrs 226163953Srrs#define sctp_ucount_decr(val) { \ 227163953Srrs if (val > 0) { \ 228163953Srrs val--; \ 229163953Srrs } else { \ 230163953Srrs val = 0; \ 231163953Srrs } \ 232163953Srrs} 233163953Srrs 234163953Srrs#define sctp_mbuf_crush(data) do { \ 235166675Srrs struct mbuf *_m; \ 236166675Srrs _m = (data); \ 237231039Stuexen while (_m && (SCTP_BUF_LEN(_m) == 0)) { \ 238166675Srrs (data) = SCTP_BUF_NEXT(_m); \ 239166675Srrs SCTP_BUF_NEXT(_m) = NULL; \ 240166675Srrs sctp_m_free(_m); \ 241163953Srrs _m = (data); \ 242166675Srrs } \ 243163953Srrs} while (0) 244163953Srrs 245168709Srrs#define sctp_flight_size_decrease(tp1) do { \ 246168709Srrs if (tp1->whoTo->flight_size >= tp1->book_size) \ 247168709Srrs tp1->whoTo->flight_size -= tp1->book_size; \ 248168709Srrs else \ 249168709Srrs tp1->whoTo->flight_size = 0; \ 250168709Srrs} while (0) 251163953Srrs 252171440Srrs#define sctp_flight_size_increase(tp1) do { \ 253171440Srrs (tp1)->whoTo->flight_size += (tp1)->book_size; \ 254171440Srrs} while (0) 255168709Srrs 256171440Srrs#ifdef SCTP_FS_SPEC_LOG 257168709Srrs#define sctp_total_flight_decrease(stcb, tp1) do { \ 258206137Stuexen if (stcb->asoc.fs_index > SCTP_FS_SPEC_LOG_SIZE) \ 259171440Srrs stcb->asoc.fs_index = 0;\ 260171440Srrs stcb->asoc.fslog[stcb->asoc.fs_index].total_flight = stcb->asoc.total_flight; \ 261171440Srrs stcb->asoc.fslog[stcb->asoc.fs_index].tsn = tp1->rec.data.TSN_seq; \ 262171440Srrs stcb->asoc.fslog[stcb->asoc.fs_index].book = tp1->book_size; \ 263171440Srrs stcb->asoc.fslog[stcb->asoc.fs_index].sent = tp1->sent; \ 264171440Srrs stcb->asoc.fslog[stcb->asoc.fs_index].incr = 0; \ 265171440Srrs stcb->asoc.fslog[stcb->asoc.fs_index].decr = 1; \ 266171440Srrs stcb->asoc.fs_index++; \ 267171477Srrs tp1->window_probe = 0; \ 268168709Srrs if (stcb->asoc.total_flight >= tp1->book_size) { \ 269168709Srrs stcb->asoc.total_flight -= tp1->book_size; \ 270168709Srrs if (stcb->asoc.total_flight_count > 0) \ 271168709Srrs stcb->asoc.total_flight_count--; \ 272168709Srrs } else { \ 273168709Srrs stcb->asoc.total_flight = 0; \ 274168709Srrs stcb->asoc.total_flight_count = 0; \ 275168709Srrs } \ 276168709Srrs} while (0) 277168709Srrs 278171440Srrs#define sctp_total_flight_increase(stcb, tp1) do { \ 279206137Stuexen if (stcb->asoc.fs_index > SCTP_FS_SPEC_LOG_SIZE) \ 280171440Srrs stcb->asoc.fs_index = 0;\ 281171440Srrs stcb->asoc.fslog[stcb->asoc.fs_index].total_flight = stcb->asoc.total_flight; \ 282171440Srrs stcb->asoc.fslog[stcb->asoc.fs_index].tsn = tp1->rec.data.TSN_seq; \ 283171440Srrs stcb->asoc.fslog[stcb->asoc.fs_index].book = tp1->book_size; \ 284171440Srrs stcb->asoc.fslog[stcb->asoc.fs_index].sent = tp1->sent; \ 285171440Srrs stcb->asoc.fslog[stcb->asoc.fs_index].incr = 1; \ 286171440Srrs stcb->asoc.fslog[stcb->asoc.fs_index].decr = 0; \ 287171440Srrs stcb->asoc.fs_index++; \ 288171440Srrs (stcb)->asoc.total_flight_count++; \ 289171440Srrs (stcb)->asoc.total_flight += (tp1)->book_size; \ 290168709Srrs} while (0) 291168709Srrs 292171440Srrs#else 293168709Srrs 294168709Srrs#define sctp_total_flight_decrease(stcb, tp1) do { \ 295189790Srrs tp1->window_probe = 0; \ 296168709Srrs if (stcb->asoc.total_flight >= tp1->book_size) { \ 297168709Srrs stcb->asoc.total_flight -= tp1->book_size; \ 298168709Srrs if (stcb->asoc.total_flight_count > 0) \ 299168709Srrs stcb->asoc.total_flight_count--; \ 300168709Srrs } else { \ 301171440Srrs stcb->asoc.total_flight = 0; \ 302171440Srrs stcb->asoc.total_flight_count = 0; \ 303168709Srrs } \ 304168709Srrs} while (0) 305168709Srrs 306168709Srrs#define sctp_total_flight_increase(stcb, tp1) do { \ 307168709Srrs (stcb)->asoc.total_flight_count++; \ 308168709Srrs (stcb)->asoc.total_flight += (tp1)->book_size; \ 309168709Srrs} while (0) 310168709Srrs 311171440Srrs#endif 312171440Srrs 313224641Stuexen#define SCTP_PF_ENABLED(_net) (_net->pf_threshold < _net->failure_threshold) 314224641Stuexen#define SCTP_NET_IS_PF(_net) (_net->pf_threshold < _net->error_count) 315171943Srrs 316163953Srrsstruct sctp_nets; 317163953Srrsstruct sctp_inpcb; 318163953Srrsstruct sctp_tcb; 319163953Srrsstruct sctphdr; 320163953Srrs 321171990Srrs 322171990Srrsvoid sctp_close(struct socket *so); 323171990Srrsint sctp_disconnect(struct socket *so); 324244524Sdelphijvoid sctp_ctlinput(int, struct sockaddr *, void *); 325244524Sdelphijint sctp_ctloutput(struct socket *, struct sockopt *); 326221249Stuexen 327221249Stuexen#ifdef INET 328244524Sdelphijvoid sctp_input_with_port(struct mbuf *, int, uint16_t); 329244524Sdelphijvoid sctp_input(struct mbuf *, int); 330221249Stuexen 331221249Stuexen#endif 332244524Sdelphijvoid sctp_pathmtu_adjustment(struct sctp_tcb *, uint16_t); 333244524Sdelphijvoid sctp_drain(void); 334244524Sdelphijvoid sctp_init(void); 335179783Srrsvoid sctp_finish(void); 336178202Srrsint sctp_flush(struct socket *, int); 337244524Sdelphijint sctp_shutdown(struct socket *); 338252938Stuexenvoid 339252938Stuexensctp_notify(struct sctp_inpcb *, struct ip *ip, struct sctphdr *, 340163953Srrs struct sockaddr *, struct sctp_tcb *, 341244524Sdelphij struct sctp_nets *); 342252938Stuexenint 343252938Stuexensctp_bindx(struct socket *, int, struct sockaddr_storage *, 344252938Stuexen int, int, struct proc *); 345163953Srrs 346163953Srrs/* can't use sctp_assoc_t here */ 347252938Stuexenint sctp_peeloff(struct socket *, struct socket *, int, caddr_t, int *); 348252938Stuexenint sctp_ingetaddr(struct socket *, struct sockaddr **); 349252938Stuexenint sctp_peeraddr(struct socket *, struct sockaddr **); 350252938Stuexenint sctp_listen(struct socket *, int, struct thread *); 351252938Stuexenint sctp_accept(struct socket *, struct sockaddr **); 352163953Srrs 353163953Srrs#endif /* _KERNEL */ 354163953Srrs 355163953Srrs#endif /* !_NETINET_SCTP_VAR_H_ */ 356