160c778b2SVlad Yasevich /* SCTP kernel implementation 21da177e4SLinus Torvalds * (C) Copyright IBM Corp. 2001, 2004 31da177e4SLinus Torvalds * Copyright (c) 1999-2000 Cisco, Inc. 41da177e4SLinus Torvalds * Copyright (c) 1999-2001 Motorola, Inc. 51da177e4SLinus Torvalds * Copyright (c) 2001-2003 Intel Corp. 61da177e4SLinus Torvalds * 760c778b2SVlad Yasevich * This file is part of the SCTP kernel implementation 81da177e4SLinus Torvalds * 91da177e4SLinus Torvalds * The base lksctp header. 101da177e4SLinus Torvalds * 1160c778b2SVlad Yasevich * This SCTP implementation is free software; 121da177e4SLinus Torvalds * you can redistribute it and/or modify it under the terms of 131da177e4SLinus Torvalds * the GNU General Public License as published by 141da177e4SLinus Torvalds * the Free Software Foundation; either version 2, or (at your option) 151da177e4SLinus Torvalds * any later version. 161da177e4SLinus Torvalds * 1760c778b2SVlad Yasevich * This SCTP implementation is distributed in the hope that it 181da177e4SLinus Torvalds * will be useful, but WITHOUT ANY WARRANTY; without even the implied 191da177e4SLinus Torvalds * ************************ 201da177e4SLinus Torvalds * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 211da177e4SLinus Torvalds * See the GNU General Public License for more details. 221da177e4SLinus Torvalds * 231da177e4SLinus Torvalds * You should have received a copy of the GNU General Public License 244b2f13a2SJeff Kirsher * along with GNU CC; see the file COPYING. If not, see 254b2f13a2SJeff Kirsher * <http://www.gnu.org/licenses/>. 261da177e4SLinus Torvalds * 271da177e4SLinus Torvalds * Please send any bug reports or fixes you make to the 281da177e4SLinus Torvalds * email address(es): 2991705c61SDaniel Borkmann * lksctp developers <linux-sctp@vger.kernel.org> 301da177e4SLinus Torvalds * 311da177e4SLinus Torvalds * Written or modified by: 321da177e4SLinus Torvalds * La Monte H.P. Yarroll <piggy@acm.org> 331da177e4SLinus Torvalds * Xingang Guo <xingang.guo@intel.com> 341da177e4SLinus Torvalds * Jon Grimm <jgrimm@us.ibm.com> 351da177e4SLinus Torvalds * Daisy Chang <daisyc@us.ibm.com> 361da177e4SLinus Torvalds * Sridhar Samudrala <sri@us.ibm.com> 371da177e4SLinus Torvalds * Ardelle Fan <ardelle.fan@intel.com> 381da177e4SLinus Torvalds * Ryan Layer <rmlayer@us.ibm.com> 391da177e4SLinus Torvalds * Kevin Gao <kevin.gao@intel.com> 401da177e4SLinus Torvalds */ 411da177e4SLinus Torvalds 421da177e4SLinus Torvalds #ifndef __net_sctp_h__ 431da177e4SLinus Torvalds #define __net_sctp_h__ 441da177e4SLinus Torvalds 451da177e4SLinus Torvalds /* Header Strategy. 461da177e4SLinus Torvalds * Start getting some control over the header file depencies: 471da177e4SLinus Torvalds * includes 481da177e4SLinus Torvalds * constants 491da177e4SLinus Torvalds * structs 501da177e4SLinus Torvalds * prototypes 511da177e4SLinus Torvalds * macros, externs, and inlines 521da177e4SLinus Torvalds * 531da177e4SLinus Torvalds * Move test_frame specific items out of the kernel headers 541da177e4SLinus Torvalds * and into the test frame headers. This is not perfect in any sense 551da177e4SLinus Torvalds * and will continue to evolve. 561da177e4SLinus Torvalds */ 571da177e4SLinus Torvalds 581da177e4SLinus Torvalds #include <linux/types.h> 591da177e4SLinus Torvalds #include <linux/slab.h> 601da177e4SLinus Torvalds #include <linux/in.h> 611da177e4SLinus Torvalds #include <linux/tty.h> 621da177e4SLinus Torvalds #include <linux/proc_fs.h> 631da177e4SLinus Torvalds #include <linux/spinlock.h> 641da177e4SLinus Torvalds #include <linux/jiffies.h> 651da177e4SLinus Torvalds #include <linux/idr.h> 661da177e4SLinus Torvalds 67dfd56b8bSEric Dumazet #if IS_ENABLED(CONFIG_IPV6) 681da177e4SLinus Torvalds #include <net/ipv6.h> 691da177e4SLinus Torvalds #include <net/ip6_route.h> 701da177e4SLinus Torvalds #endif 711da177e4SLinus Torvalds 721da177e4SLinus Torvalds #include <asm/uaccess.h> 731da177e4SLinus Torvalds #include <asm/page.h> 741da177e4SLinus Torvalds #include <net/sock.h> 751da177e4SLinus Torvalds #include <net/snmp.h> 761da177e4SLinus Torvalds #include <net/sctp/structs.h> 771da177e4SLinus Torvalds #include <net/sctp/constants.h> 781da177e4SLinus Torvalds 791da177e4SLinus Torvalds #ifdef CONFIG_IP_SCTP_MODULE 801da177e4SLinus Torvalds #define SCTP_PROTOSW_FLAG 0 811da177e4SLinus Torvalds #else /* static! */ 821da177e4SLinus Torvalds #define SCTP_PROTOSW_FLAG INET_PROTOSW_PERMANENT 831da177e4SLinus Torvalds #endif 841da177e4SLinus Torvalds 851da177e4SLinus Torvalds /* 861da177e4SLinus Torvalds * Function declarations. 871da177e4SLinus Torvalds */ 881da177e4SLinus Torvalds 891da177e4SLinus Torvalds /* 901da177e4SLinus Torvalds * sctp/protocol.c 911da177e4SLinus Torvalds */ 927b584460SJoe Perches int sctp_copy_local_addr_list(struct net *, struct sctp_bind_addr *, 937b584460SJoe Perches sctp_scope_t, gfp_t gfp, int flags); 947b584460SJoe Perches struct sctp_pf *sctp_get_pf_specific(sa_family_t family); 957b584460SJoe Perches int sctp_register_pf(struct sctp_pf *, sa_family_t); 967b584460SJoe Perches void sctp_addr_wq_mgmt(struct net *, struct sctp_sockaddr_entry *, int); 971da177e4SLinus Torvalds 981da177e4SLinus Torvalds /* 991da177e4SLinus Torvalds * sctp/socket.c 1001da177e4SLinus Torvalds */ 1011da177e4SLinus Torvalds int sctp_backlog_rcv(struct sock *sk, struct sk_buff *skb); 1021da177e4SLinus Torvalds int sctp_inet_listen(struct socket *sock, int backlog); 1031da177e4SLinus Torvalds void sctp_write_space(struct sock *sk); 104676d2369SDavid S. Miller void sctp_data_ready(struct sock *sk); 1051da177e4SLinus Torvalds unsigned int sctp_poll(struct file *file, struct socket *sock, 1061da177e4SLinus Torvalds poll_table *wait); 107331c4ee7SVlad Yasevich void sctp_sock_rfree(struct sk_buff *skb); 108914e1c8bSVlad Yasevich void sctp_copy_sock(struct sock *newsk, struct sock *sk, 109914e1c8bSVlad Yasevich struct sctp_association *asoc); 1101748376bSEric Dumazet extern struct percpu_counter sctp_sockets_allocated; 1117b584460SJoe Perches int sctp_asconf_mgmt(struct sctp_sock *, struct sctp_sockaddr_entry *); 1122347c80fSGeir Ola Vaagland struct sk_buff *sctp_skb_recv_datagram(struct sock *, int, int, int *); 1131da177e4SLinus Torvalds 1141da177e4SLinus Torvalds /* 1151da177e4SLinus Torvalds * sctp/primitive.c 1161da177e4SLinus Torvalds */ 11755e26eb9SEric W. Biederman int sctp_primitive_ASSOCIATE(struct net *, struct sctp_association *, void *arg); 11855e26eb9SEric W. Biederman int sctp_primitive_SHUTDOWN(struct net *, struct sctp_association *, void *arg); 11955e26eb9SEric W. Biederman int sctp_primitive_ABORT(struct net *, struct sctp_association *, void *arg); 12055e26eb9SEric W. Biederman int sctp_primitive_SEND(struct net *, struct sctp_association *, void *arg); 12155e26eb9SEric W. Biederman int sctp_primitive_REQUESTHEARTBEAT(struct net *, struct sctp_association *, void *arg); 12255e26eb9SEric W. Biederman int sctp_primitive_ASCONF(struct net *, struct sctp_association *, void *arg); 1231da177e4SLinus Torvalds 1241da177e4SLinus Torvalds /* 1251da177e4SLinus Torvalds * sctp/input.c 1261da177e4SLinus Torvalds */ 1271da177e4SLinus Torvalds int sctp_rcv(struct sk_buff *skb); 1281da177e4SLinus Torvalds void sctp_v4_err(struct sk_buff *skb, u32 info); 1291da177e4SLinus Torvalds void sctp_hash_established(struct sctp_association *); 1301da177e4SLinus Torvalds void sctp_unhash_established(struct sctp_association *); 1311da177e4SLinus Torvalds void sctp_hash_endpoint(struct sctp_endpoint *); 1321da177e4SLinus Torvalds void sctp_unhash_endpoint(struct sctp_endpoint *); 1334110cc25SEric W. Biederman struct sock *sctp_err_lookup(struct net *net, int family, struct sk_buff *, 134d1ad1ff2SSridhar Samudrala struct sctphdr *, struct sctp_association **, 1351da177e4SLinus Torvalds struct sctp_transport **); 136d1ad1ff2SSridhar Samudrala void sctp_err_finish(struct sock *, struct sctp_association *); 1371da177e4SLinus Torvalds void sctp_icmp_frag_needed(struct sock *, struct sctp_association *, 1381da177e4SLinus Torvalds struct sctp_transport *t, __u32 pmtu); 139ec18d9a2SDavid S. Miller void sctp_icmp_redirect(struct sock *, struct sctp_transport *, 140ec18d9a2SDavid S. Miller struct sk_buff *); 1411da177e4SLinus Torvalds void sctp_icmp_proto_unreachable(struct sock *sk, 1421da177e4SLinus Torvalds struct sctp_association *asoc, 1431da177e4SLinus Torvalds struct sctp_transport *t); 144c4d2444eSSridhar Samudrala void sctp_backlog_migrate(struct sctp_association *assoc, 145c4d2444eSSridhar Samudrala struct sock *oldsk, struct sock *newsk); 1461da177e4SLinus Torvalds 1471da177e4SLinus Torvalds /* 14816164366SAdrian Bunk * sctp/proc.c 14916164366SAdrian Bunk */ 15013d782f6SEric W. Biederman int sctp_snmp_proc_init(struct net *net); 15113d782f6SEric W. Biederman void sctp_snmp_proc_exit(struct net *net); 15213d782f6SEric W. Biederman int sctp_eps_proc_init(struct net *net); 15313d782f6SEric W. Biederman void sctp_eps_proc_exit(struct net *net); 15413d782f6SEric W. Biederman int sctp_assocs_proc_init(struct net *net); 15513d782f6SEric W. Biederman void sctp_assocs_proc_exit(struct net *net); 15613d782f6SEric W. Biederman int sctp_remaddr_proc_init(struct net *net); 15713d782f6SEric W. Biederman void sctp_remaddr_proc_exit(struct net *net); 15816164366SAdrian Bunk 15916164366SAdrian Bunk 16016164366SAdrian Bunk /* 1610a5fcb9cSsebastian@breakpoint.cc * Module global variables 1620a5fcb9cSsebastian@breakpoint.cc */ 1630a5fcb9cSsebastian@breakpoint.cc 1640a5fcb9cSsebastian@breakpoint.cc /* 1650a5fcb9cSsebastian@breakpoint.cc * sctp/protocol.c 1660a5fcb9cSsebastian@breakpoint.cc */ 1670a5fcb9cSsebastian@breakpoint.cc extern struct kmem_cache *sctp_chunk_cachep __read_mostly; 1680a5fcb9cSsebastian@breakpoint.cc extern struct kmem_cache *sctp_bucket_cachep __read_mostly; 1690a5fcb9cSsebastian@breakpoint.cc 1700a5fcb9cSsebastian@breakpoint.cc /* 1711da177e4SLinus Torvalds * Section: Macros, externs, and inlines 1721da177e4SLinus Torvalds */ 1731da177e4SLinus Torvalds 1741da177e4SLinus Torvalds /* SCTP SNMP MIB stats handlers */ 175b01a2407SEric W. Biederman #define SCTP_INC_STATS(net, field) SNMP_INC_STATS((net)->sctp.sctp_statistics, field) 176b01a2407SEric W. Biederman #define SCTP_INC_STATS_BH(net, field) SNMP_INC_STATS_BH((net)->sctp.sctp_statistics, field) 177b01a2407SEric W. Biederman #define SCTP_INC_STATS_USER(net, field) SNMP_INC_STATS_USER((net)->sctp.sctp_statistics, field) 178b01a2407SEric W. Biederman #define SCTP_DEC_STATS(net, field) SNMP_DEC_STATS((net)->sctp.sctp_statistics, field) 1791da177e4SLinus Torvalds 180ac0b0462SSridhar Samudrala /* sctp mib definitions */ 181fd2c3ef7SEric Dumazet enum { 182ac0b0462SSridhar Samudrala SCTP_MIB_NUM = 0, 183ac0b0462SSridhar Samudrala SCTP_MIB_CURRESTAB, /* CurrEstab */ 184ac0b0462SSridhar Samudrala SCTP_MIB_ACTIVEESTABS, /* ActiveEstabs */ 185ac0b0462SSridhar Samudrala SCTP_MIB_PASSIVEESTABS, /* PassiveEstabs */ 186ac0b0462SSridhar Samudrala SCTP_MIB_ABORTEDS, /* Aborteds */ 187ac0b0462SSridhar Samudrala SCTP_MIB_SHUTDOWNS, /* Shutdowns */ 188ac0b0462SSridhar Samudrala SCTP_MIB_OUTOFBLUES, /* OutOfBlues */ 189ac0b0462SSridhar Samudrala SCTP_MIB_CHECKSUMERRORS, /* ChecksumErrors */ 190ac0b0462SSridhar Samudrala SCTP_MIB_OUTCTRLCHUNKS, /* OutCtrlChunks */ 191ac0b0462SSridhar Samudrala SCTP_MIB_OUTORDERCHUNKS, /* OutOrderChunks */ 192ac0b0462SSridhar Samudrala SCTP_MIB_OUTUNORDERCHUNKS, /* OutUnorderChunks */ 193ac0b0462SSridhar Samudrala SCTP_MIB_INCTRLCHUNKS, /* InCtrlChunks */ 194ac0b0462SSridhar Samudrala SCTP_MIB_INORDERCHUNKS, /* InOrderChunks */ 195ac0b0462SSridhar Samudrala SCTP_MIB_INUNORDERCHUNKS, /* InUnorderChunks */ 196ac0b0462SSridhar Samudrala SCTP_MIB_FRAGUSRMSGS, /* FragUsrMsgs */ 197ac0b0462SSridhar Samudrala SCTP_MIB_REASMUSRMSGS, /* ReasmUsrMsgs */ 198ac0b0462SSridhar Samudrala SCTP_MIB_OUTSCTPPACKS, /* OutSCTPPacks */ 199ac0b0462SSridhar Samudrala SCTP_MIB_INSCTPPACKS, /* InSCTPPacks */ 200ac0b0462SSridhar Samudrala SCTP_MIB_T1_INIT_EXPIREDS, 201ac0b0462SSridhar Samudrala SCTP_MIB_T1_COOKIE_EXPIREDS, 202ac0b0462SSridhar Samudrala SCTP_MIB_T2_SHUTDOWN_EXPIREDS, 203ac0b0462SSridhar Samudrala SCTP_MIB_T3_RTX_EXPIREDS, 204ac0b0462SSridhar Samudrala SCTP_MIB_T4_RTO_EXPIREDS, 205ac0b0462SSridhar Samudrala SCTP_MIB_T5_SHUTDOWN_GUARD_EXPIREDS, 206ac0b0462SSridhar Samudrala SCTP_MIB_DELAY_SACK_EXPIREDS, 207ac0b0462SSridhar Samudrala SCTP_MIB_AUTOCLOSE_EXPIREDS, 208b6157d8eSVlad Yasevich SCTP_MIB_T1_RETRANSMITS, 209ac0b0462SSridhar Samudrala SCTP_MIB_T3_RETRANSMITS, 210ac0b0462SSridhar Samudrala SCTP_MIB_PMTUD_RETRANSMITS, 211ac0b0462SSridhar Samudrala SCTP_MIB_FAST_RETRANSMITS, 212ac0b0462SSridhar Samudrala SCTP_MIB_IN_PKT_SOFTIRQ, 213ac0b0462SSridhar Samudrala SCTP_MIB_IN_PKT_BACKLOG, 214ac0b0462SSridhar Samudrala SCTP_MIB_IN_PKT_DISCARDS, 215ac0b0462SSridhar Samudrala SCTP_MIB_IN_DATA_CHUNK_DISCARDS, 216ac0b0462SSridhar Samudrala __SCTP_MIB_MAX 217ac0b0462SSridhar Samudrala }; 218ac0b0462SSridhar Samudrala 219ac0b0462SSridhar Samudrala #define SCTP_MIB_MAX __SCTP_MIB_MAX 220ac0b0462SSridhar Samudrala struct sctp_mib { 221ac0b0462SSridhar Samudrala unsigned long mibs[SCTP_MIB_MAX]; 222ec733b15SEric Dumazet }; 223ac0b0462SSridhar Samudrala 224196d6759SMichele Baldessari /* helper function to track stats about max rto and related transport */ 225196d6759SMichele Baldessari static inline void sctp_max_rto(struct sctp_association *asoc, 226196d6759SMichele Baldessari struct sctp_transport *trans) 227196d6759SMichele Baldessari { 228196d6759SMichele Baldessari if (asoc->stats.max_obs_rto < (__u64)trans->rto) { 229196d6759SMichele Baldessari asoc->stats.max_obs_rto = trans->rto; 230196d6759SMichele Baldessari memset(&asoc->stats.obs_rto_ipaddr, 0, 231196d6759SMichele Baldessari sizeof(struct sockaddr_storage)); 232196d6759SMichele Baldessari memcpy(&asoc->stats.obs_rto_ipaddr, &trans->ipaddr, 233196d6759SMichele Baldessari trans->af_specific->sockaddr_len); 234196d6759SMichele Baldessari } 235196d6759SMichele Baldessari } 2361da177e4SLinus Torvalds 2371da177e4SLinus Torvalds /* 2381da177e4SLinus Torvalds * Macros for keeping a global reference of object allocations. 2391da177e4SLinus Torvalds */ 2401da177e4SLinus Torvalds #ifdef CONFIG_SCTP_DBG_OBJCNT 2411da177e4SLinus Torvalds 2421da177e4SLinus Torvalds extern atomic_t sctp_dbg_objcnt_sock; 2431da177e4SLinus Torvalds extern atomic_t sctp_dbg_objcnt_ep; 2441da177e4SLinus Torvalds extern atomic_t sctp_dbg_objcnt_assoc; 2451da177e4SLinus Torvalds extern atomic_t sctp_dbg_objcnt_transport; 2461da177e4SLinus Torvalds extern atomic_t sctp_dbg_objcnt_chunk; 2471da177e4SLinus Torvalds extern atomic_t sctp_dbg_objcnt_bind_addr; 2481da177e4SLinus Torvalds extern atomic_t sctp_dbg_objcnt_bind_bucket; 2491da177e4SLinus Torvalds extern atomic_t sctp_dbg_objcnt_addr; 2501da177e4SLinus Torvalds extern atomic_t sctp_dbg_objcnt_ssnmap; 2511da177e4SLinus Torvalds extern atomic_t sctp_dbg_objcnt_datamsg; 2521f485649SVlad Yasevich extern atomic_t sctp_dbg_objcnt_keys; 2531da177e4SLinus Torvalds 2541da177e4SLinus Torvalds /* Macros to atomically increment/decrement objcnt counters. */ 2551da177e4SLinus Torvalds #define SCTP_DBG_OBJCNT_INC(name) \ 2561da177e4SLinus Torvalds atomic_inc(&sctp_dbg_objcnt_## name) 2571da177e4SLinus Torvalds #define SCTP_DBG_OBJCNT_DEC(name) \ 2581da177e4SLinus Torvalds atomic_dec(&sctp_dbg_objcnt_## name) 2591da177e4SLinus Torvalds #define SCTP_DBG_OBJCNT(name) \ 2601da177e4SLinus Torvalds atomic_t sctp_dbg_objcnt_## name = ATOMIC_INIT(0) 2611da177e4SLinus Torvalds 2621da177e4SLinus Torvalds /* Macro to help create new entries in in the global array of 2631da177e4SLinus Torvalds * objcnt counters. 2641da177e4SLinus Torvalds */ 2651da177e4SLinus Torvalds #define SCTP_DBG_OBJCNT_ENTRY(name) \ 2661da177e4SLinus Torvalds {.label= #name, .counter= &sctp_dbg_objcnt_## name} 2671da177e4SLinus Torvalds 26813d782f6SEric W. Biederman void sctp_dbg_objcnt_init(struct net *); 26913d782f6SEric W. Biederman void sctp_dbg_objcnt_exit(struct net *); 2701da177e4SLinus Torvalds 2711da177e4SLinus Torvalds #else 2721da177e4SLinus Torvalds 2731da177e4SLinus Torvalds #define SCTP_DBG_OBJCNT_INC(name) 2741da177e4SLinus Torvalds #define SCTP_DBG_OBJCNT_DEC(name) 2751da177e4SLinus Torvalds 2761f07b62fSCong Wang static inline void sctp_dbg_objcnt_init(struct net *net) { return; } 2771f07b62fSCong Wang static inline void sctp_dbg_objcnt_exit(struct net *net) { return; } 2781da177e4SLinus Torvalds 2791da177e4SLinus Torvalds #endif /* CONFIG_SCTP_DBG_OBJCOUNT */ 2801da177e4SLinus Torvalds 2811da177e4SLinus Torvalds #if defined CONFIG_SYSCTL 2821da177e4SLinus Torvalds void sctp_sysctl_register(void); 2831da177e4SLinus Torvalds void sctp_sysctl_unregister(void); 284ebb7e95dSEric W. Biederman int sctp_sysctl_net_register(struct net *net); 285ebb7e95dSEric W. Biederman void sctp_sysctl_net_unregister(struct net *net); 2861da177e4SLinus Torvalds #else 2871da177e4SLinus Torvalds static inline void sctp_sysctl_register(void) { return; } 2881da177e4SLinus Torvalds static inline void sctp_sysctl_unregister(void) { return; } 289ebb7e95dSEric W. Biederman static inline int sctp_sysctl_net_register(struct net *net) { return 0; } 290ebb7e95dSEric W. Biederman static inline void sctp_sysctl_net_unregister(struct net *net) { return; } 2911da177e4SLinus Torvalds #endif 2921da177e4SLinus Torvalds 2931da177e4SLinus Torvalds /* Size of Supported Address Parameter for 'x' address types. */ 2941da177e4SLinus Torvalds #define SCTP_SAT_LEN(x) (sizeof(struct sctp_paramhdr) + (x) * sizeof(__u16)) 2951da177e4SLinus Torvalds 296dfd56b8bSEric Dumazet #if IS_ENABLED(CONFIG_IPV6) 2971da177e4SLinus Torvalds 298270637abSVlad Yasevich void sctp_v6_pf_init(void); 299270637abSVlad Yasevich void sctp_v6_pf_exit(void); 300270637abSVlad Yasevich int sctp_v6_protosw_init(void); 301270637abSVlad Yasevich void sctp_v6_protosw_exit(void); 302827bf122SSridhar Samudrala int sctp_v6_add_protocol(void); 303827bf122SSridhar Samudrala void sctp_v6_del_protocol(void); 3041da177e4SLinus Torvalds 3051da177e4SLinus Torvalds #else /* #ifdef defined(CONFIG_IPV6) */ 3061da177e4SLinus Torvalds 3071233823bSDavid S. Miller static inline void sctp_v6_pf_init(void) { return; } 308270637abSVlad Yasevich static inline void sctp_v6_pf_exit(void) { return; } 309270637abSVlad Yasevich static inline int sctp_v6_protosw_init(void) { return 0; } 310270637abSVlad Yasevich static inline void sctp_v6_protosw_exit(void) { return; } 311827bf122SSridhar Samudrala static inline int sctp_v6_add_protocol(void) { return 0; } 312827bf122SSridhar Samudrala static inline void sctp_v6_del_protocol(void) { return; } 3131da177e4SLinus Torvalds 3141da177e4SLinus Torvalds #endif /* #if defined(CONFIG_IPV6) */ 3151da177e4SLinus Torvalds 3161da177e4SLinus Torvalds 3171da177e4SLinus Torvalds /* Map an association to an assoc_id. */ 3181da177e4SLinus Torvalds static inline sctp_assoc_t sctp_assoc2id(const struct sctp_association *asoc) 3191da177e4SLinus Torvalds { 320a02cec21SEric Dumazet return asoc ? asoc->assoc_id : 0; 3211da177e4SLinus Torvalds } 3221da177e4SLinus Torvalds 3231da177e4SLinus Torvalds /* Look up the association by its id. */ 3241da177e4SLinus Torvalds struct sctp_association *sctp_id2assoc(struct sock *sk, sctp_assoc_t id); 3251da177e4SLinus Torvalds 3260343c554SBenjamin Poirier int sctp_do_peeloff(struct sock *sk, sctp_assoc_t id, struct socket **sockp); 3271da177e4SLinus Torvalds 3281da177e4SLinus Torvalds /* A macro to walk a list of skbs. */ 3291da177e4SLinus Torvalds #define sctp_skb_for_each(pos, head, tmp) \ 3303d09274cSDavid S. Miller skb_queue_walk_safe(head, pos, tmp) 3311da177e4SLinus Torvalds 3321da177e4SLinus Torvalds /* A helper to append an entire skb list (list) to another (head). */ 3331da177e4SLinus Torvalds static inline void sctp_skb_list_tail(struct sk_buff_head *list, 3341da177e4SLinus Torvalds struct sk_buff_head *head) 3351da177e4SLinus Torvalds { 3361da177e4SLinus Torvalds unsigned long flags; 3371da177e4SLinus Torvalds 338940287eeSwangweidong spin_lock_irqsave(&head->lock, flags); 3393c8e43baSwangweidong spin_lock(&list->lock); 3401da177e4SLinus Torvalds 3413d09274cSDavid S. Miller skb_queue_splice_tail_init(list, head); 3421da177e4SLinus Torvalds 3433c8e43baSwangweidong spin_unlock(&list->lock); 344940287eeSwangweidong spin_unlock_irqrestore(&head->lock, flags); 3451da177e4SLinus Torvalds } 3461da177e4SLinus Torvalds 3471da177e4SLinus Torvalds /** 3481da177e4SLinus Torvalds * sctp_list_dequeue - remove from the head of the queue 3491da177e4SLinus Torvalds * @list: list to dequeue from 3501da177e4SLinus Torvalds * 3511da177e4SLinus Torvalds * Remove the head of the list. The head item is 3521da177e4SLinus Torvalds * returned or %NULL if the list is empty. 3531da177e4SLinus Torvalds */ 3541da177e4SLinus Torvalds 3551da177e4SLinus Torvalds static inline struct list_head *sctp_list_dequeue(struct list_head *list) 3561da177e4SLinus Torvalds { 3571da177e4SLinus Torvalds struct list_head *result = NULL; 3581da177e4SLinus Torvalds 3591da177e4SLinus Torvalds if (list->next != list) { 3601da177e4SLinus Torvalds result = list->next; 3611da177e4SLinus Torvalds list->next = result->next; 3621da177e4SLinus Torvalds list->next->prev = list; 3631da177e4SLinus Torvalds INIT_LIST_HEAD(result); 3641da177e4SLinus Torvalds } 3651da177e4SLinus Torvalds return result; 3661da177e4SLinus Torvalds } 3671da177e4SLinus Torvalds 368331c4ee7SVlad Yasevich /* SCTP version of skb_set_owner_r. We need this one because 369331c4ee7SVlad Yasevich * of the way we have to do receive buffer accounting on bundled 370331c4ee7SVlad Yasevich * chunks. 371331c4ee7SVlad Yasevich */ 372331c4ee7SVlad Yasevich static inline void sctp_skb_set_owner_r(struct sk_buff *skb, struct sock *sk) 373331c4ee7SVlad Yasevich { 374331c4ee7SVlad Yasevich struct sctp_ulpevent *event = sctp_skb2event(skb); 375331c4ee7SVlad Yasevich 376d55d87fdSHerbert Xu skb_orphan(skb); 377331c4ee7SVlad Yasevich skb->sk = sk; 378331c4ee7SVlad Yasevich skb->destructor = sctp_sock_rfree; 379331c4ee7SVlad Yasevich atomic_add(event->rmem_len, &sk->sk_rmem_alloc); 3804d93df0aSNeil Horman /* 3813ab224beSHideo Aoki * This mimics the behavior of skb_set_owner_r 3824d93df0aSNeil Horman */ 3834d93df0aSNeil Horman sk->sk_forward_alloc -= event->rmem_len; 384331c4ee7SVlad Yasevich } 385331c4ee7SVlad Yasevich 3861da177e4SLinus Torvalds /* Tests if the list has one and only one entry. */ 3871da177e4SLinus Torvalds static inline int sctp_list_single_entry(struct list_head *head) 3881da177e4SLinus Torvalds { 389a02cec21SEric Dumazet return (head->next != head) && (head->next == head->prev); 3901da177e4SLinus Torvalds } 3911da177e4SLinus Torvalds 3921da177e4SLinus Torvalds /* Break down data chunks at this point. */ 393f68b2e05SVlad Yasevich static inline int sctp_frag_point(const struct sctp_association *asoc, int pmtu) 3941da177e4SLinus Torvalds { 395f68b2e05SVlad Yasevich struct sctp_sock *sp = sctp_sk(asoc->base.sk); 3961da177e4SLinus Torvalds int frag = pmtu; 3971da177e4SLinus Torvalds 3981da177e4SLinus Torvalds frag -= sp->pf->af->net_header_len; 3991da177e4SLinus Torvalds frag -= sizeof(struct sctphdr) + sizeof(struct sctp_data_chunk); 4001da177e4SLinus Torvalds 401f68b2e05SVlad Yasevich if (asoc->user_frag) 402f68b2e05SVlad Yasevich frag = min_t(int, frag, asoc->user_frag); 4031da177e4SLinus Torvalds 4041da177e4SLinus Torvalds frag = min_t(int, frag, SCTP_MAX_CHUNK_LEN); 4051da177e4SLinus Torvalds 4061da177e4SLinus Torvalds return frag; 4071da177e4SLinus Torvalds } 4081da177e4SLinus Torvalds 40902f3d4ceSDavid S. Miller static inline void sctp_assoc_pending_pmtu(struct sock *sk, struct sctp_association *asoc) 4108a479491SVlad Yasevich { 4118a479491SVlad Yasevich 41202f3d4ceSDavid S. Miller sctp_assoc_sync_pmtu(sk, asoc); 4138a479491SVlad Yasevich asoc->pmtu_pending = 0; 4148a479491SVlad Yasevich } 4158a479491SVlad Yasevich 4161da177e4SLinus Torvalds /* Walk through a list of TLV parameters. Don't trust the 4171da177e4SLinus Torvalds * individual parameter lengths and instead depend on 4181da177e4SLinus Torvalds * the chunk length to indicate when to stop. Make sure 4191da177e4SLinus Torvalds * there is room for a param header too. 4201da177e4SLinus Torvalds */ 4211da177e4SLinus Torvalds #define sctp_walk_params(pos, chunk, member)\ 422dd2d1c6fSVladislav Yasevich _sctp_walk_params((pos), (chunk), ntohs((chunk)->chunk_hdr.length), member) 4231da177e4SLinus Torvalds 4241da177e4SLinus Torvalds #define _sctp_walk_params(pos, chunk, end, member)\ 4251da177e4SLinus Torvalds for (pos.v = chunk->member;\ 426dd2d1c6fSVladislav Yasevich pos.v <= (void *)chunk + end - ntohs(pos.p->length) &&\ 4271da177e4SLinus Torvalds ntohs(pos.p->length) >= sizeof(sctp_paramhdr_t);\ 4281da177e4SLinus Torvalds pos.v += WORD_ROUND(ntohs(pos.p->length))) 4291da177e4SLinus Torvalds 4301da177e4SLinus Torvalds #define sctp_walk_errors(err, chunk_hdr)\ 4311da177e4SLinus Torvalds _sctp_walk_errors((err), (chunk_hdr), ntohs((chunk_hdr)->length)) 4321da177e4SLinus Torvalds 4331da177e4SLinus Torvalds #define _sctp_walk_errors(err, chunk_hdr, end)\ 4341da177e4SLinus Torvalds for (err = (sctp_errhdr_t *)((void *)chunk_hdr + \ 4351da177e4SLinus Torvalds sizeof(sctp_chunkhdr_t));\ 436dd2d1c6fSVladislav Yasevich (void *)err <= (void *)chunk_hdr + end - ntohs(err->length) &&\ 4371da177e4SLinus Torvalds ntohs(err->length) >= sizeof(sctp_errhdr_t); \ 4381da177e4SLinus Torvalds err = (sctp_errhdr_t *)((void *)err + WORD_ROUND(ntohs(err->length)))) 4391da177e4SLinus Torvalds 4401da177e4SLinus Torvalds #define sctp_walk_fwdtsn(pos, chunk)\ 4411da177e4SLinus Torvalds _sctp_walk_fwdtsn((pos), (chunk), ntohs((chunk)->chunk_hdr->length) - sizeof(struct sctp_fwdtsn_chunk)) 4421da177e4SLinus Torvalds 4431da177e4SLinus Torvalds #define _sctp_walk_fwdtsn(pos, chunk, end)\ 4441da177e4SLinus Torvalds for (pos = chunk->subh.fwdtsn_hdr->skip;\ 4451da177e4SLinus Torvalds (void *)pos <= (void *)chunk->subh.fwdtsn_hdr->skip + end - sizeof(struct sctp_fwdtsn_skip);\ 4461da177e4SLinus Torvalds pos++) 4471da177e4SLinus Torvalds 4481da177e4SLinus Torvalds /* Round an int up to the next multiple of 4. */ 4491da177e4SLinus Torvalds #define WORD_ROUND(s) (((s)+3)&~3) 4501da177e4SLinus Torvalds 4511da177e4SLinus Torvalds /* External references. */ 4521da177e4SLinus Torvalds 4531da177e4SLinus Torvalds extern struct proto sctp_prot; 4541da177e4SLinus Torvalds extern struct proto sctpv6_prot; 4551da177e4SLinus Torvalds void sctp_put_port(struct sock *sk); 4561da177e4SLinus Torvalds 4571da177e4SLinus Torvalds extern struct idr sctp_assocs_id; 4581da177e4SLinus Torvalds extern spinlock_t sctp_assocs_id_lock; 4591da177e4SLinus Torvalds 4601da177e4SLinus Torvalds /* Static inline functions. */ 4611da177e4SLinus Torvalds 4621da177e4SLinus Torvalds /* Convert from an IP version number to an Address Family symbol. */ 4631da177e4SLinus Torvalds static inline int ipver2af(__u8 ipver) 4641da177e4SLinus Torvalds { 4651da177e4SLinus Torvalds switch (ipver) { 4661da177e4SLinus Torvalds case 4: 4671da177e4SLinus Torvalds return AF_INET; 4681da177e4SLinus Torvalds case 6: 4691da177e4SLinus Torvalds return AF_INET6; 4701da177e4SLinus Torvalds default: 4711da177e4SLinus Torvalds return 0; 472e3cc055cSJoe Perches } 4731da177e4SLinus Torvalds } 4741da177e4SLinus Torvalds 4751da177e4SLinus Torvalds /* Convert from an address parameter type to an address family. */ 476dbc16db1SAl Viro static inline int param_type2af(__be16 type) 4771da177e4SLinus Torvalds { 4781da177e4SLinus Torvalds switch (type) { 4791da177e4SLinus Torvalds case SCTP_PARAM_IPV4_ADDRESS: 4801da177e4SLinus Torvalds return AF_INET; 4811da177e4SLinus Torvalds case SCTP_PARAM_IPV6_ADDRESS: 4821da177e4SLinus Torvalds return AF_INET6; 4831da177e4SLinus Torvalds default: 4841da177e4SLinus Torvalds return 0; 485e3cc055cSJoe Perches } 4861da177e4SLinus Torvalds } 4871da177e4SLinus Torvalds 4881da177e4SLinus Torvalds /* Warning: The following hash functions assume a power of two 'size'. */ 4891da177e4SLinus Torvalds /* This is the hash function for the SCTP port hash table. */ 490f1f43763SEric W. Biederman static inline int sctp_phashfn(struct net *net, __u16 lport) 4911da177e4SLinus Torvalds { 492f1f43763SEric W. Biederman return (net_hash_mix(net) + lport) & (sctp_port_hashsize - 1); 4931da177e4SLinus Torvalds } 4941da177e4SLinus Torvalds 4951da177e4SLinus Torvalds /* This is the hash function for the endpoint hash table. */ 4964cdadcbcSEric W. Biederman static inline int sctp_ep_hashfn(struct net *net, __u16 lport) 4971da177e4SLinus Torvalds { 4984cdadcbcSEric W. Biederman return (net_hash_mix(net) + lport) & (sctp_ep_hashsize - 1); 4991da177e4SLinus Torvalds } 5001da177e4SLinus Torvalds 5011da177e4SLinus Torvalds /* This is the hash function for the association hash table. */ 5024110cc25SEric W. Biederman static inline int sctp_assoc_hashfn(struct net *net, __u16 lport, __u16 rport) 5031da177e4SLinus Torvalds { 5044110cc25SEric W. Biederman int h = (lport << 16) + rport + net_hash_mix(net); 5051da177e4SLinus Torvalds h ^= h>>8; 506a02cec21SEric Dumazet return h & (sctp_assoc_hashsize - 1); 5071da177e4SLinus Torvalds } 5081da177e4SLinus Torvalds 5091da177e4SLinus Torvalds /* This is the hash function for the association hash table. This is 5101da177e4SLinus Torvalds * not used yet, but could be used as a better hash function when 5111da177e4SLinus Torvalds * we have a vtag. 5121da177e4SLinus Torvalds */ 5131da177e4SLinus Torvalds static inline int sctp_vtag_hashfn(__u16 lport, __u16 rport, __u32 vtag) 5141da177e4SLinus Torvalds { 5151da177e4SLinus Torvalds int h = (lport << 16) + rport; 5161da177e4SLinus Torvalds h ^= vtag; 517a02cec21SEric Dumazet return h & (sctp_assoc_hashsize - 1); 5181da177e4SLinus Torvalds } 5191da177e4SLinus Torvalds 520b67bfe0dSSasha Levin #define sctp_for_each_hentry(epb, head) \ 521b67bfe0dSSasha Levin hlist_for_each_entry(epb, head, node) 522d970dbf8SVlad Yasevich 5231da177e4SLinus Torvalds /* Is a socket of this style? */ 5241da177e4SLinus Torvalds #define sctp_style(sk, style) __sctp_style((sk), (SCTP_SOCKET_##style)) 5251da177e4SLinus Torvalds static inline int __sctp_style(const struct sock *sk, sctp_socket_type_t style) 5261da177e4SLinus Torvalds { 5271da177e4SLinus Torvalds return sctp_sk(sk)->type == style; 5281da177e4SLinus Torvalds } 5291da177e4SLinus Torvalds 5301da177e4SLinus Torvalds /* Is the association in this state? */ 5311da177e4SLinus Torvalds #define sctp_state(asoc, state) __sctp_state((asoc), (SCTP_STATE_##state)) 5321da177e4SLinus Torvalds static inline int __sctp_state(const struct sctp_association *asoc, 5331da177e4SLinus Torvalds sctp_state_t state) 5341da177e4SLinus Torvalds { 5351da177e4SLinus Torvalds return asoc->state == state; 5361da177e4SLinus Torvalds } 5371da177e4SLinus Torvalds 5381da177e4SLinus Torvalds /* Is the socket in this state? */ 5391da177e4SLinus Torvalds #define sctp_sstate(sk, state) __sctp_sstate((sk), (SCTP_SS_##state)) 5401da177e4SLinus Torvalds static inline int __sctp_sstate(const struct sock *sk, sctp_sock_state_t state) 5411da177e4SLinus Torvalds { 5421da177e4SLinus Torvalds return sk->sk_state == state; 5431da177e4SLinus Torvalds } 5441da177e4SLinus Torvalds 5451da177e4SLinus Torvalds /* Map v4-mapped v6 address back to v4 address */ 5461da177e4SLinus Torvalds static inline void sctp_v6_map_v4(union sctp_addr *addr) 5471da177e4SLinus Torvalds { 5481da177e4SLinus Torvalds addr->v4.sin_family = AF_INET; 5491da177e4SLinus Torvalds addr->v4.sin_port = addr->v6.sin6_port; 5501da177e4SLinus Torvalds addr->v4.sin_addr.s_addr = addr->v6.sin6_addr.s6_addr32[3]; 5511da177e4SLinus Torvalds } 5521da177e4SLinus Torvalds 5531da177e4SLinus Torvalds /* Map v4 address to v4-mapped v6 address */ 5541da177e4SLinus Torvalds static inline void sctp_v4_map_v6(union sctp_addr *addr) 5551da177e4SLinus Torvalds { 5561da177e4SLinus Torvalds addr->v6.sin6_family = AF_INET6; 5571da177e4SLinus Torvalds addr->v6.sin6_port = addr->v4.sin_port; 5581da177e4SLinus Torvalds addr->v6.sin6_addr.s6_addr32[3] = addr->v4.sin_addr.s_addr; 5591da177e4SLinus Torvalds addr->v6.sin6_addr.s6_addr32[0] = 0; 5601da177e4SLinus Torvalds addr->v6.sin6_addr.s6_addr32[1] = 0; 5611da177e4SLinus Torvalds addr->v6.sin6_addr.s6_addr32[2] = htonl(0x0000ffff); 5621da177e4SLinus Torvalds } 5631da177e4SLinus Torvalds 564e0268868SNicolas Dichtel /* The cookie is always 0 since this is how it's used in the 565e0268868SNicolas Dichtel * pmtu code. 566e0268868SNicolas Dichtel */ 567e0268868SNicolas Dichtel static inline struct dst_entry *sctp_transport_dst_check(struct sctp_transport *t) 568e0268868SNicolas Dichtel { 569d27fc782Sfan.du if (t->dst && !dst_check(t->dst, t->dst_cookie)) { 570e0268868SNicolas Dichtel dst_release(t->dst); 571e0268868SNicolas Dichtel t->dst = NULL; 572e0268868SNicolas Dichtel } 573e0268868SNicolas Dichtel 574e0268868SNicolas Dichtel return t->dst; 575e0268868SNicolas Dichtel } 576e0268868SNicolas Dichtel 5771da177e4SLinus Torvalds #endif /* __net_sctp_h__ */ 578