11da177e4SLinus Torvalds /* SCTP kernel reference 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 * 71da177e4SLinus Torvalds * This file is part of the SCTP kernel reference Implementation 81da177e4SLinus Torvalds * 91da177e4SLinus Torvalds * The base lksctp header. 101da177e4SLinus Torvalds * 111da177e4SLinus Torvalds * The SCTP reference 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 * 171da177e4SLinus Torvalds * The SCTP reference 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 241da177e4SLinus Torvalds * along with GNU CC; see the file COPYING. If not, write to 251da177e4SLinus Torvalds * the Free Software Foundation, 59 Temple Place - Suite 330, 261da177e4SLinus Torvalds * Boston, MA 02111-1307, USA. 271da177e4SLinus Torvalds * 281da177e4SLinus Torvalds * Please send any bug reports or fixes you make to the 291da177e4SLinus Torvalds * email address(es): 301da177e4SLinus Torvalds * lksctp developers <lksctp-developers@lists.sourceforge.net> 311da177e4SLinus Torvalds * 321da177e4SLinus Torvalds * Or submit a bug report through the following website: 331da177e4SLinus Torvalds * http://www.sf.net/projects/lksctp 341da177e4SLinus Torvalds * 351da177e4SLinus Torvalds * Written or modified by: 361da177e4SLinus Torvalds * La Monte H.P. Yarroll <piggy@acm.org> 371da177e4SLinus Torvalds * Xingang Guo <xingang.guo@intel.com> 381da177e4SLinus Torvalds * Jon Grimm <jgrimm@us.ibm.com> 391da177e4SLinus Torvalds * Daisy Chang <daisyc@us.ibm.com> 401da177e4SLinus Torvalds * Sridhar Samudrala <sri@us.ibm.com> 411da177e4SLinus Torvalds * Ardelle Fan <ardelle.fan@intel.com> 421da177e4SLinus Torvalds * Ryan Layer <rmlayer@us.ibm.com> 431da177e4SLinus Torvalds * Kevin Gao <kevin.gao@intel.com> 441da177e4SLinus Torvalds * 451da177e4SLinus Torvalds * Any bugs reported given to us we will try to fix... any fixes shared will 461da177e4SLinus Torvalds * be incorporated into the next SCTP release. 471da177e4SLinus Torvalds */ 481da177e4SLinus Torvalds 491da177e4SLinus Torvalds #ifndef __net_sctp_h__ 501da177e4SLinus Torvalds #define __net_sctp_h__ 511da177e4SLinus Torvalds 521da177e4SLinus Torvalds /* Header Strategy. 531da177e4SLinus Torvalds * Start getting some control over the header file depencies: 541da177e4SLinus Torvalds * includes 551da177e4SLinus Torvalds * constants 561da177e4SLinus Torvalds * structs 571da177e4SLinus Torvalds * prototypes 581da177e4SLinus Torvalds * macros, externs, and inlines 591da177e4SLinus Torvalds * 601da177e4SLinus Torvalds * Move test_frame specific items out of the kernel headers 611da177e4SLinus Torvalds * and into the test frame headers. This is not perfect in any sense 621da177e4SLinus Torvalds * and will continue to evolve. 631da177e4SLinus Torvalds */ 641da177e4SLinus Torvalds 651da177e4SLinus Torvalds 661da177e4SLinus Torvalds #include <linux/config.h> 671da177e4SLinus Torvalds 681da177e4SLinus Torvalds #ifdef TEST_FRAME 691da177e4SLinus Torvalds #undef CONFIG_PROC_FS 701da177e4SLinus Torvalds #undef CONFIG_SCTP_DBG_OBJCNT 711da177e4SLinus Torvalds #undef CONFIG_SYSCTL 721da177e4SLinus Torvalds #endif /* TEST_FRAME */ 731da177e4SLinus Torvalds 741da177e4SLinus Torvalds #include <linux/types.h> 751da177e4SLinus Torvalds #include <linux/slab.h> 761da177e4SLinus Torvalds #include <linux/in.h> 771da177e4SLinus Torvalds #include <linux/tty.h> 781da177e4SLinus Torvalds #include <linux/proc_fs.h> 791da177e4SLinus Torvalds #include <linux/spinlock.h> 801da177e4SLinus Torvalds #include <linux/jiffies.h> 811da177e4SLinus Torvalds #include <linux/idr.h> 821da177e4SLinus Torvalds 831da177e4SLinus Torvalds #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 841da177e4SLinus Torvalds #include <net/ipv6.h> 851da177e4SLinus Torvalds #include <net/ip6_route.h> 861da177e4SLinus Torvalds #endif 871da177e4SLinus Torvalds 881da177e4SLinus Torvalds #include <asm/uaccess.h> 891da177e4SLinus Torvalds #include <asm/page.h> 901da177e4SLinus Torvalds #include <net/sock.h> 911da177e4SLinus Torvalds #include <net/snmp.h> 921da177e4SLinus Torvalds #include <net/sctp/structs.h> 931da177e4SLinus Torvalds #include <net/sctp/constants.h> 941da177e4SLinus Torvalds 951da177e4SLinus Torvalds 961da177e4SLinus Torvalds /* Set SCTP_DEBUG flag via config if not already set. */ 971da177e4SLinus Torvalds #ifndef SCTP_DEBUG 981da177e4SLinus Torvalds #ifdef CONFIG_SCTP_DBG_MSG 991da177e4SLinus Torvalds #define SCTP_DEBUG 1 1001da177e4SLinus Torvalds #else 1011da177e4SLinus Torvalds #define SCTP_DEBUG 0 1021da177e4SLinus Torvalds #endif /* CONFIG_SCTP_DBG */ 1031da177e4SLinus Torvalds #endif /* SCTP_DEBUG */ 1041da177e4SLinus Torvalds 1051da177e4SLinus Torvalds #ifdef CONFIG_IP_SCTP_MODULE 1061da177e4SLinus Torvalds #define SCTP_PROTOSW_FLAG 0 1071da177e4SLinus Torvalds #else /* static! */ 1081da177e4SLinus Torvalds #define SCTP_PROTOSW_FLAG INET_PROTOSW_PERMANENT 1091da177e4SLinus Torvalds #endif 1101da177e4SLinus Torvalds 1111da177e4SLinus Torvalds 1121da177e4SLinus Torvalds /* Certain internal static functions need to be exported when 1131da177e4SLinus Torvalds * compiled into the test frame. 1141da177e4SLinus Torvalds */ 1151da177e4SLinus Torvalds #ifndef SCTP_STATIC 1161da177e4SLinus Torvalds #define SCTP_STATIC static 1171da177e4SLinus Torvalds #endif 1181da177e4SLinus Torvalds 1191da177e4SLinus Torvalds /* 1201da177e4SLinus Torvalds * Function declarations. 1211da177e4SLinus Torvalds */ 1221da177e4SLinus Torvalds 1231da177e4SLinus Torvalds /* 1241da177e4SLinus Torvalds * sctp/protocol.c 1251da177e4SLinus Torvalds */ 1261da177e4SLinus Torvalds extern struct sock *sctp_get_ctl_sock(void); 1271da177e4SLinus Torvalds extern int sctp_copy_local_addr_list(struct sctp_bind_addr *, 128dd0fc66fSAl Viro sctp_scope_t, gfp_t gfp, 1293182cd84SAlexey Dobriyan int flags); 1301da177e4SLinus Torvalds extern struct sctp_pf *sctp_get_pf_specific(sa_family_t family); 1311da177e4SLinus Torvalds extern int sctp_register_pf(struct sctp_pf *, sa_family_t); 1321da177e4SLinus Torvalds 1331da177e4SLinus Torvalds /* 1341da177e4SLinus Torvalds * sctp/socket.c 1351da177e4SLinus Torvalds */ 1361da177e4SLinus Torvalds int sctp_backlog_rcv(struct sock *sk, struct sk_buff *skb); 1371da177e4SLinus Torvalds int sctp_inet_listen(struct socket *sock, int backlog); 1381da177e4SLinus Torvalds void sctp_write_space(struct sock *sk); 1391da177e4SLinus Torvalds unsigned int sctp_poll(struct file *file, struct socket *sock, 1401da177e4SLinus Torvalds poll_table *wait); 1411da177e4SLinus Torvalds 1421da177e4SLinus Torvalds /* 1431da177e4SLinus Torvalds * sctp/primitive.c 1441da177e4SLinus Torvalds */ 1451da177e4SLinus Torvalds int sctp_primitive_ASSOCIATE(struct sctp_association *, void *arg); 1461da177e4SLinus Torvalds int sctp_primitive_SHUTDOWN(struct sctp_association *, void *arg); 1471da177e4SLinus Torvalds int sctp_primitive_ABORT(struct sctp_association *, void *arg); 1481da177e4SLinus Torvalds int sctp_primitive_SEND(struct sctp_association *, void *arg); 1491da177e4SLinus Torvalds int sctp_primitive_REQUESTHEARTBEAT(struct sctp_association *, void *arg); 1501da177e4SLinus Torvalds int sctp_primitive_ASCONF(struct sctp_association *, void *arg); 1511da177e4SLinus Torvalds 1521da177e4SLinus Torvalds /* 1531da177e4SLinus Torvalds * sctp/crc32c.c 1541da177e4SLinus Torvalds */ 1551da177e4SLinus Torvalds __u32 sctp_start_cksum(__u8 *ptr, __u16 count); 1561da177e4SLinus Torvalds __u32 sctp_update_cksum(__u8 *ptr, __u16 count, __u32 cksum); 1571da177e4SLinus Torvalds __u32 sctp_end_cksum(__u32 cksum); 1581da177e4SLinus Torvalds __u32 sctp_update_copy_cksum(__u8 *, __u8 *, __u16 count, __u32 cksum); 1591da177e4SLinus Torvalds 1601da177e4SLinus Torvalds /* 1611da177e4SLinus Torvalds * sctp/input.c 1621da177e4SLinus Torvalds */ 1631da177e4SLinus Torvalds int sctp_rcv(struct sk_buff *skb); 1641da177e4SLinus Torvalds void sctp_v4_err(struct sk_buff *skb, u32 info); 1651da177e4SLinus Torvalds void sctp_hash_established(struct sctp_association *); 1661da177e4SLinus Torvalds void sctp_unhash_established(struct sctp_association *); 1671da177e4SLinus Torvalds void sctp_hash_endpoint(struct sctp_endpoint *); 1681da177e4SLinus Torvalds void sctp_unhash_endpoint(struct sctp_endpoint *); 1691da177e4SLinus Torvalds struct sock *sctp_err_lookup(int family, struct sk_buff *, 170d1ad1ff2SSridhar Samudrala struct sctphdr *, struct sctp_association **, 1711da177e4SLinus Torvalds struct sctp_transport **); 172d1ad1ff2SSridhar Samudrala void sctp_err_finish(struct sock *, struct sctp_association *); 1731da177e4SLinus Torvalds void sctp_icmp_frag_needed(struct sock *, struct sctp_association *, 1741da177e4SLinus Torvalds struct sctp_transport *t, __u32 pmtu); 1751da177e4SLinus Torvalds void sctp_icmp_proto_unreachable(struct sock *sk, 1761da177e4SLinus Torvalds struct sctp_association *asoc, 1771da177e4SLinus Torvalds struct sctp_transport *t); 178c4d2444eSSridhar Samudrala void sctp_backlog_migrate(struct sctp_association *assoc, 179c4d2444eSSridhar Samudrala struct sock *oldsk, struct sock *newsk); 1801da177e4SLinus Torvalds 1811da177e4SLinus Torvalds /* 1821da177e4SLinus Torvalds * Section: Macros, externs, and inlines 1831da177e4SLinus Torvalds */ 1841da177e4SLinus Torvalds 1851da177e4SLinus Torvalds 1861da177e4SLinus Torvalds #ifdef TEST_FRAME 1871da177e4SLinus Torvalds #include <test_frame.h> 1881da177e4SLinus Torvalds #else 1891da177e4SLinus Torvalds 1901da177e4SLinus Torvalds /* spin lock wrappers. */ 1911da177e4SLinus Torvalds #define sctp_spin_lock_irqsave(lock, flags) spin_lock_irqsave(lock, flags) 1921da177e4SLinus Torvalds #define sctp_spin_unlock_irqrestore(lock, flags) \ 1931da177e4SLinus Torvalds spin_unlock_irqrestore(lock, flags) 1941da177e4SLinus Torvalds #define sctp_local_bh_disable() local_bh_disable() 1951da177e4SLinus Torvalds #define sctp_local_bh_enable() local_bh_enable() 1961da177e4SLinus Torvalds #define sctp_spin_lock(lock) spin_lock(lock) 1971da177e4SLinus Torvalds #define sctp_spin_unlock(lock) spin_unlock(lock) 1981da177e4SLinus Torvalds #define sctp_write_lock(lock) write_lock(lock) 1991da177e4SLinus Torvalds #define sctp_write_unlock(lock) write_unlock(lock) 2001da177e4SLinus Torvalds #define sctp_read_lock(lock) read_lock(lock) 2011da177e4SLinus Torvalds #define sctp_read_unlock(lock) read_unlock(lock) 2021da177e4SLinus Torvalds 2031da177e4SLinus Torvalds /* sock lock wrappers. */ 2041da177e4SLinus Torvalds #define sctp_lock_sock(sk) lock_sock(sk) 2051da177e4SLinus Torvalds #define sctp_release_sock(sk) release_sock(sk) 2061da177e4SLinus Torvalds #define sctp_bh_lock_sock(sk) bh_lock_sock(sk) 2071da177e4SLinus Torvalds #define sctp_bh_unlock_sock(sk) bh_unlock_sock(sk) 2081da177e4SLinus Torvalds #define SCTP_SOCK_SLEEP_PRE(sk) SOCK_SLEEP_PRE(sk) 2091da177e4SLinus Torvalds #define SCTP_SOCK_SLEEP_POST(sk) SOCK_SLEEP_POST(sk) 2101da177e4SLinus Torvalds 2111da177e4SLinus Torvalds /* SCTP SNMP MIB stats handlers */ 2121da177e4SLinus Torvalds DECLARE_SNMP_STAT(struct sctp_mib, sctp_statistics); 2131da177e4SLinus Torvalds #define SCTP_INC_STATS(field) SNMP_INC_STATS(sctp_statistics, field) 2141da177e4SLinus Torvalds #define SCTP_INC_STATS_BH(field) SNMP_INC_STATS_BH(sctp_statistics, field) 2151da177e4SLinus Torvalds #define SCTP_INC_STATS_USER(field) SNMP_INC_STATS_USER(sctp_statistics, field) 2161da177e4SLinus Torvalds #define SCTP_DEC_STATS(field) SNMP_DEC_STATS(sctp_statistics, field) 2171da177e4SLinus Torvalds 2181da177e4SLinus Torvalds #endif /* !TEST_FRAME */ 2191da177e4SLinus Torvalds 2201da177e4SLinus Torvalds 2211da177e4SLinus Torvalds /* Print debugging messages. */ 2221da177e4SLinus Torvalds #if SCTP_DEBUG 2231da177e4SLinus Torvalds extern int sctp_debug_flag; 2241da177e4SLinus Torvalds #define SCTP_DEBUG_PRINTK(whatever...) \ 2251da177e4SLinus Torvalds ((void) (sctp_debug_flag && printk(KERN_DEBUG whatever))) 2263f7a87d2SFrank Filz #define SCTP_DEBUG_PRINTK_IPADDR(lead, trail, leadparm, saddr, otherparms...) \ 2273f7a87d2SFrank Filz if (sctp_debug_flag) { \ 2283f7a87d2SFrank Filz if (saddr->sa.sa_family == AF_INET6) { \ 2293f7a87d2SFrank Filz printk(KERN_DEBUG \ 23046b86a2dSJoe Perches lead NIP6_FMT trail, \ 2313f7a87d2SFrank Filz leadparm, \ 2323f7a87d2SFrank Filz NIP6(saddr->v6.sin6_addr), \ 2333f7a87d2SFrank Filz otherparms); \ 2343f7a87d2SFrank Filz } else { \ 2353f7a87d2SFrank Filz printk(KERN_DEBUG \ 23646b86a2dSJoe Perches lead NIPQUAD_FMT trail, \ 2373f7a87d2SFrank Filz leadparm, \ 2383f7a87d2SFrank Filz NIPQUAD(saddr->v4.sin_addr.s_addr), \ 2393f7a87d2SFrank Filz otherparms); \ 2403f7a87d2SFrank Filz } \ 2413f7a87d2SFrank Filz } 2421da177e4SLinus Torvalds #define SCTP_ENABLE_DEBUG { sctp_debug_flag = 1; } 2431da177e4SLinus Torvalds #define SCTP_DISABLE_DEBUG { sctp_debug_flag = 0; } 2441da177e4SLinus Torvalds 2451da177e4SLinus Torvalds #define SCTP_ASSERT(expr, str, func) \ 2461da177e4SLinus Torvalds if (!(expr)) { \ 2471da177e4SLinus Torvalds SCTP_DEBUG_PRINTK("Assertion Failed: %s(%s) at %s:%s:%d\n", \ 2481da177e4SLinus Torvalds str, (#expr), __FILE__, __FUNCTION__, __LINE__); \ 2491da177e4SLinus Torvalds func; \ 2501da177e4SLinus Torvalds } 2511da177e4SLinus Torvalds 2521da177e4SLinus Torvalds #else /* SCTP_DEBUG */ 2531da177e4SLinus Torvalds 2541da177e4SLinus Torvalds #define SCTP_DEBUG_PRINTK(whatever...) 2553f7a87d2SFrank Filz #define SCTP_DEBUG_PRINTK_IPADDR(whatever...) 2561da177e4SLinus Torvalds #define SCTP_ENABLE_DEBUG 2571da177e4SLinus Torvalds #define SCTP_DISABLE_DEBUG 25865fd28f7SDavid S. Miller #define SCTP_ASSERT(expr, str, func) 2591da177e4SLinus Torvalds 2601da177e4SLinus Torvalds #endif /* SCTP_DEBUG */ 2611da177e4SLinus Torvalds 2621da177e4SLinus Torvalds 2631da177e4SLinus Torvalds /* 2641da177e4SLinus Torvalds * Macros for keeping a global reference of object allocations. 2651da177e4SLinus Torvalds */ 2661da177e4SLinus Torvalds #ifdef CONFIG_SCTP_DBG_OBJCNT 2671da177e4SLinus Torvalds 2681da177e4SLinus Torvalds extern atomic_t sctp_dbg_objcnt_sock; 2691da177e4SLinus Torvalds extern atomic_t sctp_dbg_objcnt_ep; 2701da177e4SLinus Torvalds extern atomic_t sctp_dbg_objcnt_assoc; 2711da177e4SLinus Torvalds extern atomic_t sctp_dbg_objcnt_transport; 2721da177e4SLinus Torvalds extern atomic_t sctp_dbg_objcnt_chunk; 2731da177e4SLinus Torvalds extern atomic_t sctp_dbg_objcnt_bind_addr; 2741da177e4SLinus Torvalds extern atomic_t sctp_dbg_objcnt_bind_bucket; 2751da177e4SLinus Torvalds extern atomic_t sctp_dbg_objcnt_addr; 2761da177e4SLinus Torvalds extern atomic_t sctp_dbg_objcnt_ssnmap; 2771da177e4SLinus Torvalds extern atomic_t sctp_dbg_objcnt_datamsg; 2781da177e4SLinus Torvalds 2791da177e4SLinus Torvalds /* Macros to atomically increment/decrement objcnt counters. */ 2801da177e4SLinus Torvalds #define SCTP_DBG_OBJCNT_INC(name) \ 2811da177e4SLinus Torvalds atomic_inc(&sctp_dbg_objcnt_## name) 2821da177e4SLinus Torvalds #define SCTP_DBG_OBJCNT_DEC(name) \ 2831da177e4SLinus Torvalds atomic_dec(&sctp_dbg_objcnt_## name) 2841da177e4SLinus Torvalds #define SCTP_DBG_OBJCNT(name) \ 2851da177e4SLinus Torvalds atomic_t sctp_dbg_objcnt_## name = ATOMIC_INIT(0) 2861da177e4SLinus Torvalds 2871da177e4SLinus Torvalds /* Macro to help create new entries in in the global array of 2881da177e4SLinus Torvalds * objcnt counters. 2891da177e4SLinus Torvalds */ 2901da177e4SLinus Torvalds #define SCTP_DBG_OBJCNT_ENTRY(name) \ 2911da177e4SLinus Torvalds {.label= #name, .counter= &sctp_dbg_objcnt_## name} 2921da177e4SLinus Torvalds 2931da177e4SLinus Torvalds void sctp_dbg_objcnt_init(void); 2941da177e4SLinus Torvalds void sctp_dbg_objcnt_exit(void); 2951da177e4SLinus Torvalds 2961da177e4SLinus Torvalds #else 2971da177e4SLinus Torvalds 2981da177e4SLinus Torvalds #define SCTP_DBG_OBJCNT_INC(name) 2991da177e4SLinus Torvalds #define SCTP_DBG_OBJCNT_DEC(name) 3001da177e4SLinus Torvalds 3011da177e4SLinus Torvalds static inline void sctp_dbg_objcnt_init(void) { return; } 3021da177e4SLinus Torvalds static inline void sctp_dbg_objcnt_exit(void) { return; } 3031da177e4SLinus Torvalds 3041da177e4SLinus Torvalds #endif /* CONFIG_SCTP_DBG_OBJCOUNT */ 3051da177e4SLinus Torvalds 3061da177e4SLinus Torvalds #if defined CONFIG_SYSCTL 3071da177e4SLinus Torvalds void sctp_sysctl_register(void); 3081da177e4SLinus Torvalds void sctp_sysctl_unregister(void); 3091da177e4SLinus Torvalds #else 3101da177e4SLinus Torvalds static inline void sctp_sysctl_register(void) { return; } 3111da177e4SLinus Torvalds static inline void sctp_sysctl_unregister(void) { return; } 3121da177e4SLinus Torvalds static inline int sctp_sysctl_jiffies_ms(ctl_table *table, int __user *name, int nlen, 3131da177e4SLinus Torvalds void __user *oldval, size_t __user *oldlenp, 3141da177e4SLinus Torvalds void __user *newval, size_t newlen, void **context) { 3151da177e4SLinus Torvalds return -ENOSYS; 3161da177e4SLinus Torvalds } 3171da177e4SLinus Torvalds #endif 3181da177e4SLinus Torvalds 3191da177e4SLinus Torvalds /* Size of Supported Address Parameter for 'x' address types. */ 3201da177e4SLinus Torvalds #define SCTP_SAT_LEN(x) (sizeof(struct sctp_paramhdr) + (x) * sizeof(__u16)) 3211da177e4SLinus Torvalds 3221da177e4SLinus Torvalds #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 3231da177e4SLinus Torvalds 3241da177e4SLinus Torvalds int sctp_v6_init(void); 3251da177e4SLinus Torvalds void sctp_v6_exit(void); 3261da177e4SLinus Torvalds 3271da177e4SLinus Torvalds #else /* #ifdef defined(CONFIG_IPV6) */ 3281da177e4SLinus Torvalds 3291da177e4SLinus Torvalds static inline int sctp_v6_init(void) { return 0; } 3301da177e4SLinus Torvalds static inline void sctp_v6_exit(void) { return; } 3311da177e4SLinus Torvalds 3321da177e4SLinus Torvalds #endif /* #if defined(CONFIG_IPV6) */ 3331da177e4SLinus Torvalds 3341da177e4SLinus Torvalds /* Some wrappers, in case crypto not available. */ 3351da177e4SLinus Torvalds #if defined (CONFIG_CRYPTO_HMAC) 3361da177e4SLinus Torvalds #define sctp_crypto_alloc_tfm crypto_alloc_tfm 3371da177e4SLinus Torvalds #define sctp_crypto_free_tfm crypto_free_tfm 3381da177e4SLinus Torvalds #define sctp_crypto_hmac crypto_hmac 3391da177e4SLinus Torvalds #else 3401da177e4SLinus Torvalds #define sctp_crypto_alloc_tfm(x...) NULL 3411da177e4SLinus Torvalds #define sctp_crypto_free_tfm(x...) 3421da177e4SLinus Torvalds #define sctp_crypto_hmac(x...) 3431da177e4SLinus Torvalds #endif 3441da177e4SLinus Torvalds 3451da177e4SLinus Torvalds 3461da177e4SLinus Torvalds /* Map an association to an assoc_id. */ 3471da177e4SLinus Torvalds static inline sctp_assoc_t sctp_assoc2id(const struct sctp_association *asoc) 3481da177e4SLinus Torvalds { 3491da177e4SLinus Torvalds return (asoc?asoc->assoc_id:0); 3501da177e4SLinus Torvalds } 3511da177e4SLinus Torvalds 3521da177e4SLinus Torvalds /* Look up the association by its id. */ 3531da177e4SLinus Torvalds struct sctp_association *sctp_id2assoc(struct sock *sk, sctp_assoc_t id); 3541da177e4SLinus Torvalds 3551da177e4SLinus Torvalds 3561da177e4SLinus Torvalds /* A macro to walk a list of skbs. */ 3571da177e4SLinus Torvalds #define sctp_skb_for_each(pos, head, tmp) \ 3581da177e4SLinus Torvalds for (pos = (head)->next;\ 3591da177e4SLinus Torvalds tmp = (pos)->next, pos != ((struct sk_buff *)(head));\ 3601da177e4SLinus Torvalds pos = tmp) 3611da177e4SLinus Torvalds 3621da177e4SLinus Torvalds 3631da177e4SLinus Torvalds /* A helper to append an entire skb list (list) to another (head). */ 3641da177e4SLinus Torvalds static inline void sctp_skb_list_tail(struct sk_buff_head *list, 3651da177e4SLinus Torvalds struct sk_buff_head *head) 3661da177e4SLinus Torvalds { 3671da177e4SLinus Torvalds unsigned long flags; 3681da177e4SLinus Torvalds 3691da177e4SLinus Torvalds sctp_spin_lock_irqsave(&head->lock, flags); 3701da177e4SLinus Torvalds sctp_spin_lock(&list->lock); 3711da177e4SLinus Torvalds 3721da177e4SLinus Torvalds list_splice((struct list_head *)list, (struct list_head *)head->prev); 3731da177e4SLinus Torvalds 3741da177e4SLinus Torvalds head->qlen += list->qlen; 3751da177e4SLinus Torvalds list->qlen = 0; 3761da177e4SLinus Torvalds 3771da177e4SLinus Torvalds sctp_spin_unlock(&list->lock); 3781da177e4SLinus Torvalds sctp_spin_unlock_irqrestore(&head->lock, flags); 3791da177e4SLinus Torvalds } 3801da177e4SLinus Torvalds 3811da177e4SLinus Torvalds /** 3821da177e4SLinus Torvalds * sctp_list_dequeue - remove from the head of the queue 3831da177e4SLinus Torvalds * @list: list to dequeue from 3841da177e4SLinus Torvalds * 3851da177e4SLinus Torvalds * Remove the head of the list. The head item is 3861da177e4SLinus Torvalds * returned or %NULL if the list is empty. 3871da177e4SLinus Torvalds */ 3881da177e4SLinus Torvalds 3891da177e4SLinus Torvalds static inline struct list_head *sctp_list_dequeue(struct list_head *list) 3901da177e4SLinus Torvalds { 3911da177e4SLinus Torvalds struct list_head *result = NULL; 3921da177e4SLinus Torvalds 3931da177e4SLinus Torvalds if (list->next != list) { 3941da177e4SLinus Torvalds result = list->next; 3951da177e4SLinus Torvalds list->next = result->next; 3961da177e4SLinus Torvalds list->next->prev = list; 3971da177e4SLinus Torvalds INIT_LIST_HEAD(result); 3981da177e4SLinus Torvalds } 3991da177e4SLinus Torvalds return result; 4001da177e4SLinus Torvalds } 4011da177e4SLinus Torvalds 4021da177e4SLinus Torvalds /* Tests if the list has one and only one entry. */ 4031da177e4SLinus Torvalds static inline int sctp_list_single_entry(struct list_head *head) 4041da177e4SLinus Torvalds { 4051da177e4SLinus Torvalds return ((head->next != head) && (head->next == head->prev)); 4061da177e4SLinus Torvalds } 4071da177e4SLinus Torvalds 4081da177e4SLinus Torvalds /* Calculate the size (in bytes) occupied by the data of an iovec. */ 4091da177e4SLinus Torvalds static inline size_t get_user_iov_size(struct iovec *iov, int iovlen) 4101da177e4SLinus Torvalds { 4111da177e4SLinus Torvalds size_t retval = 0; 4121da177e4SLinus Torvalds 4131da177e4SLinus Torvalds for (; iovlen > 0; --iovlen) { 4141da177e4SLinus Torvalds retval += iov->iov_len; 4151da177e4SLinus Torvalds iov++; 4161da177e4SLinus Torvalds } 4171da177e4SLinus Torvalds 4181da177e4SLinus Torvalds return retval; 4191da177e4SLinus Torvalds } 4201da177e4SLinus Torvalds 4211da177e4SLinus Torvalds /* Generate a random jitter in the range of -50% ~ +50% of input RTO. */ 4221da177e4SLinus Torvalds static inline __s32 sctp_jitter(__u32 rto) 4231da177e4SLinus Torvalds { 4241da177e4SLinus Torvalds static __u32 sctp_rand; 4251da177e4SLinus Torvalds __s32 ret; 4261da177e4SLinus Torvalds 4271da177e4SLinus Torvalds /* Avoid divide by zero. */ 4281da177e4SLinus Torvalds if (!rto) 4291da177e4SLinus Torvalds rto = 1; 4301da177e4SLinus Torvalds 4311da177e4SLinus Torvalds sctp_rand += jiffies; 4321da177e4SLinus Torvalds sctp_rand ^= (sctp_rand << 12); 4331da177e4SLinus Torvalds sctp_rand ^= (sctp_rand >> 20); 4341da177e4SLinus Torvalds 4351da177e4SLinus Torvalds /* Choose random number from 0 to rto, then move to -50% ~ +50% 4361da177e4SLinus Torvalds * of rto. 4371da177e4SLinus Torvalds */ 4381da177e4SLinus Torvalds ret = sctp_rand % rto - (rto >> 1); 4391da177e4SLinus Torvalds return ret; 4401da177e4SLinus Torvalds } 4411da177e4SLinus Torvalds 4421da177e4SLinus Torvalds /* Break down data chunks at this point. */ 4431da177e4SLinus Torvalds static inline int sctp_frag_point(const struct sctp_sock *sp, int pmtu) 4441da177e4SLinus Torvalds { 4451da177e4SLinus Torvalds int frag = pmtu; 4461da177e4SLinus Torvalds 4471da177e4SLinus Torvalds frag -= sp->pf->af->net_header_len; 4481da177e4SLinus Torvalds frag -= sizeof(struct sctphdr) + sizeof(struct sctp_data_chunk); 4491da177e4SLinus Torvalds 4501da177e4SLinus Torvalds if (sp->user_frag) 4511da177e4SLinus Torvalds frag = min_t(int, frag, sp->user_frag); 4521da177e4SLinus Torvalds 4531da177e4SLinus Torvalds frag = min_t(int, frag, SCTP_MAX_CHUNK_LEN); 4541da177e4SLinus Torvalds 4551da177e4SLinus Torvalds return frag; 4561da177e4SLinus Torvalds } 4571da177e4SLinus Torvalds 4581da177e4SLinus Torvalds /* Walk through a list of TLV parameters. Don't trust the 4591da177e4SLinus Torvalds * individual parameter lengths and instead depend on 4601da177e4SLinus Torvalds * the chunk length to indicate when to stop. Make sure 4611da177e4SLinus Torvalds * there is room for a param header too. 4621da177e4SLinus Torvalds */ 4631da177e4SLinus Torvalds #define sctp_walk_params(pos, chunk, member)\ 464dd2d1c6fSVladislav Yasevich _sctp_walk_params((pos), (chunk), ntohs((chunk)->chunk_hdr.length), member) 4651da177e4SLinus Torvalds 4661da177e4SLinus Torvalds #define _sctp_walk_params(pos, chunk, end, member)\ 4671da177e4SLinus Torvalds for (pos.v = chunk->member;\ 4681da177e4SLinus Torvalds pos.v <= (void *)chunk + end - sizeof(sctp_paramhdr_t) &&\ 469dd2d1c6fSVladislav Yasevich pos.v <= (void *)chunk + end - ntohs(pos.p->length) &&\ 4701da177e4SLinus Torvalds ntohs(pos.p->length) >= sizeof(sctp_paramhdr_t);\ 4711da177e4SLinus Torvalds pos.v += WORD_ROUND(ntohs(pos.p->length))) 4721da177e4SLinus Torvalds 4731da177e4SLinus Torvalds #define sctp_walk_errors(err, chunk_hdr)\ 4741da177e4SLinus Torvalds _sctp_walk_errors((err), (chunk_hdr), ntohs((chunk_hdr)->length)) 4751da177e4SLinus Torvalds 4761da177e4SLinus Torvalds #define _sctp_walk_errors(err, chunk_hdr, end)\ 4771da177e4SLinus Torvalds for (err = (sctp_errhdr_t *)((void *)chunk_hdr + \ 4781da177e4SLinus Torvalds sizeof(sctp_chunkhdr_t));\ 4791da177e4SLinus Torvalds (void *)err <= (void *)chunk_hdr + end - sizeof(sctp_errhdr_t) &&\ 480dd2d1c6fSVladislav Yasevich (void *)err <= (void *)chunk_hdr + end - ntohs(err->length) &&\ 4811da177e4SLinus Torvalds ntohs(err->length) >= sizeof(sctp_errhdr_t); \ 4821da177e4SLinus Torvalds err = (sctp_errhdr_t *)((void *)err + WORD_ROUND(ntohs(err->length)))) 4831da177e4SLinus Torvalds 4841da177e4SLinus Torvalds #define sctp_walk_fwdtsn(pos, chunk)\ 4851da177e4SLinus Torvalds _sctp_walk_fwdtsn((pos), (chunk), ntohs((chunk)->chunk_hdr->length) - sizeof(struct sctp_fwdtsn_chunk)) 4861da177e4SLinus Torvalds 4871da177e4SLinus Torvalds #define _sctp_walk_fwdtsn(pos, chunk, end)\ 4881da177e4SLinus Torvalds for (pos = chunk->subh.fwdtsn_hdr->skip;\ 4891da177e4SLinus Torvalds (void *)pos <= (void *)chunk->subh.fwdtsn_hdr->skip + end - sizeof(struct sctp_fwdtsn_skip);\ 4901da177e4SLinus Torvalds pos++) 4911da177e4SLinus Torvalds 4921da177e4SLinus Torvalds /* Round an int up to the next multiple of 4. */ 4931da177e4SLinus Torvalds #define WORD_ROUND(s) (((s)+3)&~3) 4941da177e4SLinus Torvalds 4951da177e4SLinus Torvalds /* Make a new instance of type. */ 4961da177e4SLinus Torvalds #define t_new(type, flags) (type *)kmalloc(sizeof(type), flags) 4971da177e4SLinus Torvalds 4981da177e4SLinus Torvalds /* Compare two timevals. */ 4991da177e4SLinus Torvalds #define tv_lt(s, t) \ 5001da177e4SLinus Torvalds (s.tv_sec < t.tv_sec || (s.tv_sec == t.tv_sec && s.tv_usec < t.tv_usec)) 5011da177e4SLinus Torvalds 5021da177e4SLinus Torvalds /* Add tv1 to tv2. */ 5031da177e4SLinus Torvalds #define TIMEVAL_ADD(tv1, tv2) \ 5041da177e4SLinus Torvalds ({ \ 5051da177e4SLinus Torvalds suseconds_t usecs = (tv2).tv_usec + (tv1).tv_usec; \ 5061da177e4SLinus Torvalds time_t secs = (tv2).tv_sec + (tv1).tv_sec; \ 5071da177e4SLinus Torvalds \ 5081da177e4SLinus Torvalds if (usecs >= 1000000) { \ 5091da177e4SLinus Torvalds usecs -= 1000000; \ 5101da177e4SLinus Torvalds secs++; \ 5111da177e4SLinus Torvalds } \ 5121da177e4SLinus Torvalds (tv2).tv_sec = secs; \ 5131da177e4SLinus Torvalds (tv2).tv_usec = usecs; \ 5141da177e4SLinus Torvalds }) 5151da177e4SLinus Torvalds 5161da177e4SLinus Torvalds /* External references. */ 5171da177e4SLinus Torvalds 5181da177e4SLinus Torvalds extern struct proto sctp_prot; 5191da177e4SLinus Torvalds extern struct proto sctpv6_prot; 5201da177e4SLinus Torvalds extern struct proc_dir_entry *proc_net_sctp; 5211da177e4SLinus Torvalds void sctp_put_port(struct sock *sk); 5221da177e4SLinus Torvalds 5231da177e4SLinus Torvalds extern struct idr sctp_assocs_id; 5241da177e4SLinus Torvalds extern spinlock_t sctp_assocs_id_lock; 5251da177e4SLinus Torvalds 5261da177e4SLinus Torvalds /* Static inline functions. */ 5271da177e4SLinus Torvalds 5281da177e4SLinus Torvalds /* Convert from an IP version number to an Address Family symbol. */ 5291da177e4SLinus Torvalds static inline int ipver2af(__u8 ipver) 5301da177e4SLinus Torvalds { 5311da177e4SLinus Torvalds switch (ipver) { 5321da177e4SLinus Torvalds case 4: 5331da177e4SLinus Torvalds return AF_INET; 5341da177e4SLinus Torvalds case 6: 5351da177e4SLinus Torvalds return AF_INET6; 5361da177e4SLinus Torvalds default: 5371da177e4SLinus Torvalds return 0; 5381da177e4SLinus Torvalds }; 5391da177e4SLinus Torvalds } 5401da177e4SLinus Torvalds 5411da177e4SLinus Torvalds /* Convert from an address parameter type to an address family. */ 5421da177e4SLinus Torvalds static inline int param_type2af(__u16 type) 5431da177e4SLinus Torvalds { 5441da177e4SLinus Torvalds switch (type) { 5451da177e4SLinus Torvalds case SCTP_PARAM_IPV4_ADDRESS: 5461da177e4SLinus Torvalds return AF_INET; 5471da177e4SLinus Torvalds case SCTP_PARAM_IPV6_ADDRESS: 5481da177e4SLinus Torvalds return AF_INET6; 5491da177e4SLinus Torvalds default: 5501da177e4SLinus Torvalds return 0; 5511da177e4SLinus Torvalds }; 5521da177e4SLinus Torvalds } 5531da177e4SLinus Torvalds 5541da177e4SLinus Torvalds /* Perform some sanity checks. */ 5551da177e4SLinus Torvalds static inline int sctp_sanity_check(void) 5561da177e4SLinus Torvalds { 5571da177e4SLinus Torvalds SCTP_ASSERT(sizeof(struct sctp_ulpevent) <= 5581da177e4SLinus Torvalds sizeof(((struct sk_buff *)0)->cb), 5591da177e4SLinus Torvalds "SCTP: ulpevent does not fit in skb!\n", return 0); 5601da177e4SLinus Torvalds 5611da177e4SLinus Torvalds return 1; 5621da177e4SLinus Torvalds } 5631da177e4SLinus Torvalds 5641da177e4SLinus Torvalds /* Warning: The following hash functions assume a power of two 'size'. */ 5651da177e4SLinus Torvalds /* This is the hash function for the SCTP port hash table. */ 5661da177e4SLinus Torvalds static inline int sctp_phashfn(__u16 lport) 5671da177e4SLinus Torvalds { 5681da177e4SLinus Torvalds return (lport & (sctp_port_hashsize - 1)); 5691da177e4SLinus Torvalds } 5701da177e4SLinus Torvalds 5711da177e4SLinus Torvalds /* This is the hash function for the endpoint hash table. */ 5721da177e4SLinus Torvalds static inline int sctp_ep_hashfn(__u16 lport) 5731da177e4SLinus Torvalds { 5741da177e4SLinus Torvalds return (lport & (sctp_ep_hashsize - 1)); 5751da177e4SLinus Torvalds } 5761da177e4SLinus Torvalds 5771da177e4SLinus Torvalds /* This is the hash function for the association hash table. */ 5781da177e4SLinus Torvalds static inline int sctp_assoc_hashfn(__u16 lport, __u16 rport) 5791da177e4SLinus Torvalds { 5801da177e4SLinus Torvalds int h = (lport << 16) + rport; 5811da177e4SLinus Torvalds h ^= h>>8; 5821da177e4SLinus Torvalds return (h & (sctp_assoc_hashsize - 1)); 5831da177e4SLinus Torvalds } 5841da177e4SLinus Torvalds 5851da177e4SLinus Torvalds /* This is the hash function for the association hash table. This is 5861da177e4SLinus Torvalds * not used yet, but could be used as a better hash function when 5871da177e4SLinus Torvalds * we have a vtag. 5881da177e4SLinus Torvalds */ 5891da177e4SLinus Torvalds static inline int sctp_vtag_hashfn(__u16 lport, __u16 rport, __u32 vtag) 5901da177e4SLinus Torvalds { 5911da177e4SLinus Torvalds int h = (lport << 16) + rport; 5921da177e4SLinus Torvalds h ^= vtag; 5931da177e4SLinus Torvalds return (h & (sctp_assoc_hashsize-1)); 5941da177e4SLinus Torvalds } 5951da177e4SLinus Torvalds 5961da177e4SLinus Torvalds /* Is a socket of this style? */ 5971da177e4SLinus Torvalds #define sctp_style(sk, style) __sctp_style((sk), (SCTP_SOCKET_##style)) 5981da177e4SLinus Torvalds static inline int __sctp_style(const struct sock *sk, sctp_socket_type_t style) 5991da177e4SLinus Torvalds { 6001da177e4SLinus Torvalds return sctp_sk(sk)->type == style; 6011da177e4SLinus Torvalds } 6021da177e4SLinus Torvalds 6031da177e4SLinus Torvalds /* Is the association in this state? */ 6041da177e4SLinus Torvalds #define sctp_state(asoc, state) __sctp_state((asoc), (SCTP_STATE_##state)) 6051da177e4SLinus Torvalds static inline int __sctp_state(const struct sctp_association *asoc, 6061da177e4SLinus Torvalds sctp_state_t state) 6071da177e4SLinus Torvalds { 6081da177e4SLinus Torvalds return asoc->state == state; 6091da177e4SLinus Torvalds } 6101da177e4SLinus Torvalds 6111da177e4SLinus Torvalds /* Is the socket in this state? */ 6121da177e4SLinus Torvalds #define sctp_sstate(sk, state) __sctp_sstate((sk), (SCTP_SS_##state)) 6131da177e4SLinus Torvalds static inline int __sctp_sstate(const struct sock *sk, sctp_sock_state_t state) 6141da177e4SLinus Torvalds { 6151da177e4SLinus Torvalds return sk->sk_state == state; 6161da177e4SLinus Torvalds } 6171da177e4SLinus Torvalds 6181da177e4SLinus Torvalds /* Map v4-mapped v6 address back to v4 address */ 6191da177e4SLinus Torvalds static inline void sctp_v6_map_v4(union sctp_addr *addr) 6201da177e4SLinus Torvalds { 6211da177e4SLinus Torvalds addr->v4.sin_family = AF_INET; 6221da177e4SLinus Torvalds addr->v4.sin_port = addr->v6.sin6_port; 6231da177e4SLinus Torvalds addr->v4.sin_addr.s_addr = addr->v6.sin6_addr.s6_addr32[3]; 6241da177e4SLinus Torvalds } 6251da177e4SLinus Torvalds 6261da177e4SLinus Torvalds /* Map v4 address to v4-mapped v6 address */ 6271da177e4SLinus Torvalds static inline void sctp_v4_map_v6(union sctp_addr *addr) 6281da177e4SLinus Torvalds { 6291da177e4SLinus Torvalds addr->v6.sin6_family = AF_INET6; 6301da177e4SLinus Torvalds addr->v6.sin6_port = addr->v4.sin_port; 6311da177e4SLinus Torvalds addr->v6.sin6_addr.s6_addr32[3] = addr->v4.sin_addr.s_addr; 6321da177e4SLinus Torvalds addr->v6.sin6_addr.s6_addr32[0] = 0; 6331da177e4SLinus Torvalds addr->v6.sin6_addr.s6_addr32[1] = 0; 6341da177e4SLinus Torvalds addr->v6.sin6_addr.s6_addr32[2] = htonl(0x0000ffff); 6351da177e4SLinus Torvalds } 6361da177e4SLinus Torvalds 6371da177e4SLinus Torvalds #endif /* __net_sctp_h__ */ 638