michael@0: /*- michael@0: * Copyright (c) 2006-2007, by Cisco Systems, Inc. All rights reserved. michael@0: * Copyright (c) 2008-2011, by Randall Stewart. All rights reserved. michael@0: * Copyright (c) 2008-2011, by Michael Tuexen. All rights reserved. michael@0: * Copyright (c) 2008-2011, by Brad Penoff. All rights reserved. michael@0: * michael@0: * Redistribution and use in source and binary forms, with or without michael@0: * modification, are permitted provided that the following conditions are met: michael@0: * michael@0: * a) Redistributions of source code must retain the above copyright notice, michael@0: * this list of conditions and the following disclaimer. michael@0: * michael@0: * b) Redistributions in binary form must reproduce the above copyright michael@0: * notice, this list of conditions and the following disclaimer in michael@0: * the documentation and/or other materials provided with the distribution. michael@0: * michael@0: * c) Neither the name of Cisco Systems, Inc. nor the names of its michael@0: * contributors may be used to endorse or promote products derived michael@0: * from this software without specific prior written permission. michael@0: * michael@0: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS michael@0: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, michael@0: * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE michael@0: * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE michael@0: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR michael@0: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF michael@0: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS michael@0: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN michael@0: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) michael@0: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF michael@0: * THE POSSIBILITY OF SUCH DAMAGE. michael@0: */ michael@0: michael@0: #ifndef __sctp_os_userspace_h__ michael@0: #define __sctp_os_userspace_h__ michael@0: /* michael@0: * Userspace includes michael@0: * All the opt_xxx.h files are placed in the kernel build directory. michael@0: * We will place them in userspace stack build directory. michael@0: */ michael@0: michael@0: #include michael@0: michael@0: #if defined(__Userspace_os_Windows) michael@0: #include michael@0: #include michael@0: #include michael@0: #include michael@0: #include michael@0: #include "user_environment.h" michael@0: typedef CRITICAL_SECTION userland_mutex_t; michael@0: #if WINVER < 0x0600 michael@0: enum { michael@0: C_SIGNAL = 0, michael@0: C_BROADCAST = 1, michael@0: C_MAX_EVENTS = 2 michael@0: }; michael@0: typedef struct michael@0: { michael@0: u_int waiters_count; michael@0: CRITICAL_SECTION waiters_count_lock; michael@0: HANDLE events_[C_MAX_EVENTS]; michael@0: } userland_cond_t; michael@0: void InitializeXPConditionVariable(userland_cond_t *); michael@0: void DeleteXPConditionVariable(userland_cond_t *); michael@0: int SleepXPConditionVariable(userland_cond_t *, userland_mutex_t *); michael@0: void WakeAllXPConditionVariable(userland_cond_t *); michael@0: #define InitializeConditionVariable(cond) InitializeXPConditionVariable(cond) michael@0: #define DeleteConditionVariable(cond) DeleteXPConditionVariable(cond) michael@0: #define SleepConditionVariableCS(cond, mtx, time) SleepXPConditionVariable(cond, mtx) michael@0: #define WakeAllConditionVariable(cond) WakeAllXPConditionVariable(cond) michael@0: #else michael@0: #define DeleteConditionVariable(cond) michael@0: typedef CONDITION_VARIABLE userland_cond_t; michael@0: #endif michael@0: typedef HANDLE userland_thread_t; michael@0: #define ADDRESS_FAMILY unsigned __int8 michael@0: #define IPVERSION 4 michael@0: #define MAXTTL 255 michael@0: /* VS2010 comes with stdint.h */ michael@0: #if _MSC_VER >= 1600 michael@0: #include michael@0: #else michael@0: #define uint64_t unsigned __int64 michael@0: #define uint32_t unsigned __int32 michael@0: #define int32_t __int32 michael@0: #define uint16_t unsigned __int16 michael@0: #define int16_t __int16 michael@0: #define uint8_t unsigned __int8 michael@0: #define int8_t __int8 michael@0: #endif michael@0: #ifndef _SIZE_T_DEFINED michael@0: #define size_t __int32 michael@0: #endif michael@0: #define u_long unsigned __int64 michael@0: #define u_int unsigned __int32 michael@0: #define u_int32_t unsigned __int32 michael@0: #define u_int16_t unsigned __int16 michael@0: #define u_int8_t unsigned __int8 michael@0: #define u_char unsigned char michael@0: #define n_short unsigned __int16 michael@0: #define u_short unsigned __int16 michael@0: #define n_time unsigned __int32 michael@0: #define sa_family_t unsigned __int8 michael@0: #define ssize_t __int64 michael@0: #define IFNAMSIZ 64 michael@0: #define __func__ __FUNCTION__ michael@0: michael@0: #ifndef EWOULDBLOCK michael@0: #define EWOULDBLOCK WSAEWOULDBLOCK michael@0: #endif michael@0: #ifndef EINPROGRESS michael@0: #define EINPROGRESS WSAEINPROGRESS michael@0: #endif michael@0: #ifndef EALREADY michael@0: #define EALREADY WSAEALREADY michael@0: #endif michael@0: #ifndef ENOTSOCK michael@0: #define ENOTSOCK WSAENOTSOCK michael@0: #endif michael@0: #ifndef EDESTADDRREQ michael@0: #define EDESTADDRREQ WSAEDESTADDRREQ michael@0: #endif michael@0: #ifndef EMSGSIZE michael@0: #define EMSGSIZE WSAEMSGSIZE michael@0: #endif michael@0: #ifndef EPROTOTYPE michael@0: #define EPROTOTYPE WSAEPROTOTYPE michael@0: #endif michael@0: #ifndef ENOPROTOOPT michael@0: #define ENOPROTOOPT WSAENOPROTOOPT michael@0: #endif michael@0: #ifndef EPROTONOSUPPORT michael@0: #define EPROTONOSUPPORT WSAEPROTONOSUPPORT michael@0: #endif michael@0: #ifndef ESOCKTNOSUPPORT michael@0: #define ESOCKTNOSUPPORT WSAESOCKTNOSUPPORT michael@0: #endif michael@0: #ifndef EOPNOTSUPP michael@0: #define EOPNOTSUPP WSAEOPNOTSUPP michael@0: #endif michael@0: #ifndef ENOTSUP michael@0: #define ENOTSUP WSAEOPNOTSUPP michael@0: #endif michael@0: #ifndef EPFNOSUPPORT michael@0: #define EPFNOSUPPORT WSAEPFNOSUPPORT michael@0: #endif michael@0: #ifndef EAFNOSUPPORT michael@0: #define EAFNOSUPPORT WSAEAFNOSUPPORT michael@0: #endif michael@0: #ifndef EADDRINUSE michael@0: #define EADDRINUSE WSAEADDRINUSE michael@0: #endif michael@0: #ifndef EADDRNOTAVAIL michael@0: #define EADDRNOTAVAIL WSAEADDRNOTAVAIL michael@0: #endif michael@0: #ifndef ENETDOWN michael@0: #define ENETDOWN WSAENETDOWN michael@0: #endif michael@0: #ifndef ENETUNREACH michael@0: #define ENETUNREACH WSAENETUNREACH michael@0: #endif michael@0: #ifndef ENETRESET michael@0: #define ENETRESET WSAENETRESET michael@0: #endif michael@0: #ifndef ECONNABORTED michael@0: #define ECONNABORTED WSAECONNABORTED michael@0: #endif michael@0: #ifndef ECONNRESET michael@0: #define ECONNRESET WSAECONNRESET michael@0: #endif michael@0: #ifndef ENOBUFS michael@0: #define ENOBUFS WSAENOBUFS michael@0: #endif michael@0: #ifndef EISCONN michael@0: #define EISCONN WSAEISCONN michael@0: #endif michael@0: #ifndef ENOTCONN michael@0: #define ENOTCONN WSAENOTCONN michael@0: #endif michael@0: #ifndef ESHUTDOWN michael@0: #define ESHUTDOWN WSAESHUTDOWN michael@0: #endif michael@0: #ifndef ETOOMANYREFS michael@0: #define ETOOMANYREFS WSAETOOMANYREFS michael@0: #endif michael@0: #ifndef ETIMEDOUT michael@0: #define ETIMEDOUT WSAETIMEDOUT michael@0: #endif michael@0: #ifndef ECONNREFUSED michael@0: #define ECONNREFUSED WSAECONNREFUSED michael@0: #endif michael@0: #ifndef ELOOP michael@0: #define ELOOP WSAELOOP michael@0: #endif michael@0: #ifndef EHOSTDOWN michael@0: #define EHOSTDOWN WSAEHOSTDOWN michael@0: #endif michael@0: #ifndef EHOSTUNREACH michael@0: #define EHOSTUNREACH WSAEHOSTUNREACH michael@0: #endif michael@0: #ifndef EPROCLIM michael@0: #define EPROCLIM WSAEPROCLIM michael@0: #endif michael@0: #ifndef EUSERS michael@0: #define EUSERS WSAEUSERS michael@0: #endif michael@0: #ifndef EDQUOT michael@0: #define EDQUOT WSAEDQUOT michael@0: #endif michael@0: #ifndef ESTALE michael@0: #define ESTALE WSAESTALE michael@0: #endif michael@0: #ifndef EREMOTE michael@0: #define EREMOTE WSAEREMOTE michael@0: #endif michael@0: michael@0: typedef char* caddr_t; michael@0: michael@0: int Win_getifaddrs(struct ifaddrs**); michael@0: #define getifaddrs(interfaces) (int)Win_getifaddrs(interfaces) michael@0: int win_if_nametoindex(const char *); michael@0: #define if_nametoindex(x) win_if_nametoindex(x) michael@0: michael@0: #define bzero(buf, len) memset(buf, 0, len) michael@0: #define bcopy(srcKey, dstKey, len) memcpy(dstKey, srcKey, len) michael@0: #define snprintf(data, size, format, name) _snprintf_s(data, size, _TRUNCATE, format, name) michael@0: #define inline __inline michael@0: #define __inline__ __inline michael@0: #define random() rand() michael@0: #define srandom(s) srand(s) michael@0: #define MSG_EOR 0x8 /* data completes record */ michael@0: #define MSG_DONTWAIT 0x80 /* this message should be nonblocking */ michael@0: michael@0: #ifdef CMSG_DATA michael@0: #undef CMSG_DATA michael@0: #endif michael@0: /* michael@0: * The following definitions should apply iff WINVER < 0x0600 michael@0: * but that check doesn't work in all cases. So be more pedantic... michael@0: */ michael@0: #define CMSG_DATA(x) WSA_CMSG_DATA(x) michael@0: #define CMSG_ALIGN(x) WSA_CMSGDATA_ALIGN(x) michael@0: #ifndef CMSG_FIRSTHDR michael@0: #define CMSG_FIRSTHDR(x) WSA_CMSG_FIRSTHDR(x) michael@0: #endif michael@0: #ifndef CMSG_NXTHDR michael@0: #define CMSG_NXTHDR(x, y) WSA_CMSG_NXTHDR(x, y) michael@0: #endif michael@0: #ifndef CMSG_SPACE michael@0: #define CMSG_SPACE(x) WSA_CMSG_SPACE(x) michael@0: #endif michael@0: #ifndef CMSG_LEN michael@0: #define CMSG_LEN(x) WSA_CMSG_LEN(x) michael@0: #endif michael@0: michael@0: /**** from sctp_os_windows.h ***************/ michael@0: #define SCTP_IFN_IS_IFT_LOOP(ifn) ((ifn)->ifn_type == IFT_LOOP) michael@0: #define SCTP_ROUTE_IS_REAL_LOOP(ro) ((ro)->ro_rt && (ro)->ro_rt->rt_ifa && (ro)->ro_rt->rt_ifa->ifa_ifp && (ro)->ro_rt->rt_ifa->ifa_ifp->if_type == IFT_LOOP) michael@0: michael@0: /* michael@0: * Access to IFN's to help with src-addr-selection michael@0: */ michael@0: /* This could return VOID if the index works but for BSD we provide both. */ michael@0: #define SCTP_GET_IFN_VOID_FROM_ROUTE(ro) \ michael@0: ((ro)->ro_rt != NULL ? (ro)->ro_rt->rt_ifp : NULL) michael@0: #define SCTP_ROUTE_HAS_VALID_IFN(ro) \ michael@0: ((ro)->ro_rt && (ro)->ro_rt->rt_ifp) michael@0: /******************************************/ michael@0: michael@0: #define SCTP_GET_IF_INDEX_FROM_ROUTE(ro) 1 /* compiles... TODO use routing socket to determine */ michael@0: michael@0: #define timeradd(tvp, uvp, vvp) \ michael@0: do { \ michael@0: (vvp)->tv_sec = (tvp)->tv_sec + (uvp)->tv_sec; \ michael@0: (vvp)->tv_usec = (tvp)->tv_usec + (uvp)->tv_usec; \ michael@0: if ((vvp)->tv_usec >= 1000000) { \ michael@0: (vvp)->tv_sec++; \ michael@0: (vvp)->tv_usec -= 1000000; \ michael@0: } \ michael@0: } while (0) michael@0: michael@0: #define timersub(tvp, uvp, vvp) \ michael@0: do { \ michael@0: (vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec; \ michael@0: (vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec; \ michael@0: if ((vvp)->tv_usec < 0) { \ michael@0: (vvp)->tv_sec--; \ michael@0: (vvp)->tv_usec += 1000000; \ michael@0: } \ michael@0: } while (0) michael@0: michael@0: #define BIG_ENDIAN 1 michael@0: #define LITTLE_ENDIAN 0 michael@0: #ifdef WORDS_BIGENDIAN michael@0: #define BYTE_ORDER BIG_ENDIAN michael@0: #else michael@0: #define BYTE_ORDER LITTLE_ENDIAN michael@0: #endif michael@0: michael@0: struct iovec { michael@0: ULONG len; michael@0: CHAR FAR *buf; michael@0: }; michael@0: michael@0: #define iov_base buf michael@0: #define iov_len len michael@0: michael@0: struct ifa_msghdr { michael@0: unsigned __int16 ifam_msglen; michael@0: unsigned char ifam_version; michael@0: unsigned char ifam_type; michael@0: __int32 ifam_addrs; michael@0: __int32 ifam_flags; michael@0: unsigned __int16 ifam_index; michael@0: __int32 ifam_metric; michael@0: }; michael@0: michael@0: struct ifdevmtu { michael@0: int ifdm_current; michael@0: int ifdm_min; michael@0: int ifdm_max; michael@0: }; michael@0: michael@0: struct ifkpi { michael@0: unsigned int ifk_module_id; michael@0: unsigned int ifk_type; michael@0: union { michael@0: void *ifk_ptr; michael@0: int ifk_value; michael@0: } ifk_data; michael@0: }; michael@0: michael@0: struct ifreq { michael@0: char ifr_name[16]; michael@0: union { michael@0: struct sockaddr ifru_addr; michael@0: struct sockaddr ifru_dstaddr; michael@0: struct sockaddr ifru_broadaddr; michael@0: short ifru_flags; michael@0: int ifru_metric; michael@0: int ifru_mtu; michael@0: int ifru_phys; michael@0: int ifru_media; michael@0: int ifru_intval; michael@0: char* ifru_data; michael@0: struct ifdevmtu ifru_devmtu; michael@0: struct ifkpi ifru_kpi; michael@0: unsigned __int32 ifru_wake_flags; michael@0: } ifr_ifru; michael@0: #define ifr_addr ifr_ifru.ifru_addr michael@0: #define ifr_dstaddr ifr_ifru.ifru_dstaddr michael@0: #define ifr_broadaddr ifr_ifru.ifru_broadaddr michael@0: #define ifr_flags ifr_ifru.ifru_flags[0] michael@0: #define ifr_prevflags ifr_ifru.ifru_flags[1] michael@0: #define ifr_metric ifr_ifru.ifru_metric michael@0: #define ifr_mtu ifr_ifru.ifru_mtu michael@0: #define ifr_phys ifr_ifru.ifru_phys michael@0: #define ifr_media ifr_ifru.ifru_media michael@0: #define ifr_data ifr_ifru.ifru_data michael@0: #define ifr_devmtu ifr_ifru.ifru_devmtu michael@0: #define ifr_intval ifr_ifru.ifru_intval michael@0: #define ifr_kpi ifr_ifru.ifru_kpi michael@0: #define ifr_wake_flags ifr_ifru.ifru_wake_flags michael@0: }; michael@0: michael@0: /*#include michael@0: #pragma pack(push, 1)*/ michael@0: struct ip { michael@0: u_char ip_hl:4, ip_v:4; michael@0: u_char ip_tos; michael@0: u_short ip_len; michael@0: u_short ip_id; michael@0: u_short ip_off; michael@0: #define IP_RP 0x8000 michael@0: #define IP_DF 0x4000 michael@0: #define IP_MF 0x2000 michael@0: #define IP_OFFMASK 0x1fff michael@0: u_char ip_ttl; michael@0: u_char ip_p; michael@0: u_short ip_sum; michael@0: struct in_addr ip_src, ip_dst; michael@0: }; michael@0: michael@0: struct ifaddrs { michael@0: struct ifaddrs *ifa_next; michael@0: char *ifa_name; michael@0: unsigned int ifa_flags; michael@0: struct sockaddr *ifa_addr; michael@0: struct sockaddr *ifa_netmask; michael@0: struct sockaddr *ifa_dstaddr; michael@0: void *ifa_data; michael@0: }; michael@0: michael@0: struct udphdr { michael@0: unsigned __int16 uh_sport; michael@0: unsigned __int16 uh_dport; michael@0: unsigned __int16 uh_ulen; michael@0: unsigned __int16 uh_sum; michael@0: }; michael@0: michael@0: #else /* !defined(Userspace_os_Windows) */ michael@0: #include /* needed? added from old __FreeBSD__ */ michael@0: #include michael@0: #if defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD) || defined(__Userspace_os_Linux) || defined(__Userspace_os_NetBSD) || defined(__Userspace_os_OpenBSD) || defined(ANDROID) michael@0: #include michael@0: #endif michael@0: typedef pthread_mutex_t userland_mutex_t; michael@0: typedef pthread_cond_t userland_cond_t; michael@0: typedef pthread_t userland_thread_t; michael@0: #endif michael@0: michael@0: #define mtx_lock(arg1) michael@0: #define mtx_unlock(arg1) michael@0: #define mtx_assert(arg1,arg2) michael@0: #define MA_OWNED 7 /* sys/mutex.h typically on FreeBSD */ michael@0: #if !defined(__Userspace_os_FreeBSD) michael@0: struct mtx {int dummy;}; michael@0: #if !defined(__Userspace_os_NetBSD) michael@0: struct selinfo {int dummy;}; michael@0: #endif michael@0: struct sx {int dummy;}; michael@0: #endif michael@0: michael@0: #include michael@0: #include michael@0: /* #include in FreeBSD defines MSIZE */ michael@0: /* #include */ michael@0: /* #include */ michael@0: #if defined(__Userspace_os_Windows) michael@0: #include michael@0: #else michael@0: #include michael@0: #endif michael@0: #include michael@0: /* #include */ michael@0: /* #include */ michael@0: /* #include */ michael@0: /* on FreeBSD, this results in a redefintion of SOCK(BUF)_(UN)LOCK and michael@0: * uknown type of struct mtx for sb_mtx in struct sockbuf */ michael@0: #include "user_socketvar.h" /* MALLOC_DECLARE's M_PCB. Replacement for sys/socketvar.h */ michael@0: /* #include */ michael@0: /* #include */ michael@0: #include michael@0: #include michael@0: #include michael@0: /* #include */ michael@0: /* #include */ michael@0: #if defined(__FreeBSD__) && __FreeBSD_version > 602000 michael@0: #include michael@0: #endif michael@0: /* #include */ michael@0: #if defined(__FreeBSD__) && __FreeBSD_version > 602000 michael@0: #include michael@0: #endif michael@0: /* #include */ michael@0: /* #include */ michael@0: /* #include */ michael@0: michael@0: #if defined(__Userspace_os_Darwin) michael@0: /* was a 0 byte file. needed for structs if_data(64) and net_event_data */ michael@0: #include michael@0: #endif michael@0: #if defined(__Userspace_os_FreeBSD) michael@0: #include michael@0: /* #include was a 0 byte file. causes struct mtx redefinition */ michael@0: #endif michael@0: /* OOTB only - dummy route used at the moment. should we port route to michael@0: * userspace as well? */ michael@0: /* on FreeBSD, this results in a redefintion of struct route */ michael@0: /* #include */ michael@0: #if !defined(__Userspace_os_Windows) michael@0: #include michael@0: #include michael@0: #include michael@0: #include michael@0: #include michael@0: #else michael@0: #include michael@0: #endif michael@0: /* #include ported to userspace */ michael@0: #include michael@0: michael@0: /* for getifaddrs */ michael@0: #include michael@0: #if !defined(__Userspace_os_Windows) michael@0: #if !defined(ANDROID) && (defined(INET) || defined(INET6)) michael@0: #include michael@0: #endif michael@0: michael@0: /* for ioctl */ michael@0: #include michael@0: michael@0: /* for close, etc. */ michael@0: #include michael@0: #endif michael@0: michael@0: /* lots of errno's used and needed in userspace */ michael@0: michael@0: /* for offsetof */ michael@0: #include michael@0: michael@0: #if defined(SCTP_PROCESS_LEVEL_LOCKS) && !defined(__Userspace_os_Windows) michael@0: /* for pthread_mutex_lock, pthread_mutex_unlock, etc. */ michael@0: #include michael@0: #endif michael@0: michael@0: #ifdef IPSEC michael@0: #include michael@0: #include michael@0: #endif /* IPSEC */ michael@0: michael@0: #ifdef INET6 michael@0: #if defined(__Userspace_os_FreeBSD) michael@0: #include michael@0: #endif michael@0: #ifdef IPSEC michael@0: #include michael@0: #endif michael@0: #if !defined(__Userspace_os_Windows) michael@0: #include michael@0: #include michael@0: #endif michael@0: #if defined(__Userspace_os_Darwin) || defined(__Userspace_os_FreeBSD) || defined(__Userspace_os_Linux) || defined(__Userspace_os_NetBSD) || defined(__Userspace_os_OpenBSD) || defined(__Userspace_os_Windows) michael@0: #include "user_ip6_var.h" michael@0: #else michael@0: #include michael@0: #endif michael@0: #if defined(__Userspace_os_FreeBSD) michael@0: #include michael@0: #include michael@0: /* #include was a 0 byte file */ michael@0: #include michael@0: #endif michael@0: #endif /* INET6 */ michael@0: michael@0: #if defined(HAVE_SCTP_PEELOFF_SOCKOPT) michael@0: #include michael@0: #include michael@0: #endif michael@0: michael@0: #include "netinet/sctp_sha1.h" michael@0: michael@0: #if __FreeBSD_version >= 700000 michael@0: #include michael@0: #endif michael@0: michael@0: #define SCTP_PRINTF(...) \ michael@0: if (SCTP_BASE_VAR(debug_printf)) { \ michael@0: SCTP_BASE_VAR(debug_printf)(__VA_ARGS__); \ michael@0: } michael@0: michael@0: #if defined(__FreeBSD__) michael@0: #ifndef in6pcb michael@0: #define in6pcb inpcb michael@0: #endif michael@0: #endif michael@0: /* Declare all the malloc names for all the various mallocs */ michael@0: MALLOC_DECLARE(SCTP_M_MAP); michael@0: MALLOC_DECLARE(SCTP_M_STRMI); michael@0: MALLOC_DECLARE(SCTP_M_STRMO); michael@0: MALLOC_DECLARE(SCTP_M_ASC_ADDR); michael@0: MALLOC_DECLARE(SCTP_M_ASC_IT); michael@0: MALLOC_DECLARE(SCTP_M_AUTH_CL); michael@0: MALLOC_DECLARE(SCTP_M_AUTH_KY); michael@0: MALLOC_DECLARE(SCTP_M_AUTH_HL); michael@0: MALLOC_DECLARE(SCTP_M_AUTH_IF); michael@0: MALLOC_DECLARE(SCTP_M_STRESET); michael@0: MALLOC_DECLARE(SCTP_M_CMSG); michael@0: MALLOC_DECLARE(SCTP_M_COPYAL); michael@0: MALLOC_DECLARE(SCTP_M_VRF); michael@0: MALLOC_DECLARE(SCTP_M_IFA); michael@0: MALLOC_DECLARE(SCTP_M_IFN); michael@0: MALLOC_DECLARE(SCTP_M_TIMW); michael@0: MALLOC_DECLARE(SCTP_M_MVRF); michael@0: MALLOC_DECLARE(SCTP_M_ITER); michael@0: MALLOC_DECLARE(SCTP_M_SOCKOPT); michael@0: michael@0: #if defined(SCTP_LOCAL_TRACE_BUF) michael@0: michael@0: #define SCTP_GET_CYCLECOUNT get_cyclecount() michael@0: #define SCTP_CTR6 sctp_log_trace michael@0: michael@0: #else michael@0: #define SCTP_CTR6 CTR6 michael@0: #endif michael@0: michael@0: /* Empty ktr statement for _Userspace__ (similar to what is done for mac) */ michael@0: #define CTR6(m, d, p1, p2, p3, p4, p5, p6) michael@0: michael@0: michael@0: michael@0: #define SCTP_BASE_INFO(__m) system_base_info.sctppcbinfo.__m michael@0: #define SCTP_BASE_STATS system_base_info.sctpstat michael@0: #define SCTP_BASE_STAT(__m) system_base_info.sctpstat.__m michael@0: #define SCTP_BASE_SYSCTL(__m) system_base_info.sctpsysctl.__m michael@0: #define SCTP_BASE_VAR(__m) system_base_info.__m michael@0: michael@0: /* michael@0: * michael@0: */ michael@0: #if !defined(__Userspace_os_Darwin) michael@0: #define USER_ADDR_NULL (NULL) /* FIX ME: temp */ michael@0: #endif michael@0: michael@0: #if defined(SCTP_DEBUG) michael@0: #include michael@0: #define SCTPDBG(level, ...) \ michael@0: { \ michael@0: do { \ michael@0: if (SCTP_BASE_SYSCTL(sctp_debug_on) & level) { \ michael@0: SCTP_PRINTF(__VA_ARGS__); \ michael@0: } \ michael@0: } while (0); \ michael@0: } michael@0: #define SCTPDBG_ADDR(level, addr) \ michael@0: { \ michael@0: do { \ michael@0: if (SCTP_BASE_SYSCTL(sctp_debug_on) & level ) { \ michael@0: sctp_print_address(addr); \ michael@0: } \ michael@0: } while (0); \ michael@0: } michael@0: #else michael@0: #define SCTPDBG(level, ...) michael@0: #define SCTPDBG_ADDR(level, addr) michael@0: #endif michael@0: michael@0: #ifdef SCTP_LTRACE_CHUNKS michael@0: #define SCTP_LTRACE_CHK(a, b, c, d) if(sctp_logging_level & SCTP_LTRACE_CHUNK_ENABLE) CTR6(KTR_SUBSYS, "SCTP:%d[%d]:%x-%x-%x-%x", SCTP_LOG_CHUNK_PROC, 0, a, b, c, d) michael@0: #else michael@0: #define SCTP_LTRACE_CHK(a, b, c, d) michael@0: #endif michael@0: michael@0: #ifdef SCTP_LTRACE_ERRORS michael@0: #define SCTP_LTRACE_ERR_RET_PKT(m, inp, stcb, net, file, err) \ michael@0: if (sctp_logging_level & SCTP_LTRACE_ERROR_ENABLE) \ michael@0: SCTP_PRINTF("mbuf:%p inp:%p stcb:%p net:%p file:%x line:%d error:%d\n", \ michael@0: (void *)m, (void *)inp, (void *)stcb, (void *)net, file, __LINE__, err); michael@0: #define SCTP_LTRACE_ERR_RET(inp, stcb, net, file, err) \ michael@0: if (sctp_logging_level & SCTP_LTRACE_ERROR_ENABLE) \ michael@0: SCTP_PRINTF("inp:%p stcb:%p net:%p file:%x line:%d error:%d\n", \ michael@0: (void *)inp, (void *)stcb, (void *)net, file, __LINE__, err); michael@0: #else michael@0: #define SCTP_LTRACE_ERR_RET_PKT(m, inp, stcb, net, file, err) michael@0: #define SCTP_LTRACE_ERR_RET(inp, stcb, net, file, err) michael@0: #endif michael@0: michael@0: michael@0: /* michael@0: * Local address and interface list handling michael@0: */ michael@0: #define SCTP_MAX_VRF_ID 0 michael@0: #define SCTP_SIZE_OF_VRF_HASH 3 michael@0: #define SCTP_IFNAMSIZ IFNAMSIZ michael@0: #define SCTP_DEFAULT_VRFID 0 michael@0: #define SCTP_VRF_ADDR_HASH_SIZE 16 michael@0: #define SCTP_VRF_IFN_HASH_SIZE 3 michael@0: #define SCTP_INIT_VRF_TABLEID(vrf) michael@0: michael@0: #if !defined(__Userspace_os_Windows) michael@0: #define SCTP_IFN_IS_IFT_LOOP(ifn) (strncmp((ifn)->ifn_name, "lo", 2) == 0) michael@0: /* BSD definition */ michael@0: /* #define SCTP_ROUTE_IS_REAL_LOOP(ro) ((ro)->ro_rt && (ro)->ro_rt->rt_ifa && (ro)->ro_rt->rt_ifa->ifa_ifp && (ro)->ro_rt->rt_ifa->ifa_ifp->if_type == IFT_LOOP) */ michael@0: /* only used in IPv6 scenario, which isn't supported yet */ michael@0: #define SCTP_ROUTE_IS_REAL_LOOP(ro) 0 michael@0: michael@0: /* michael@0: * Access to IFN's to help with src-addr-selection michael@0: */ michael@0: /* This could return VOID if the index works but for BSD we provide both. */ michael@0: #define SCTP_GET_IFN_VOID_FROM_ROUTE(ro) (void *)ro->ro_rt->rt_ifp michael@0: #define SCTP_GET_IF_INDEX_FROM_ROUTE(ro) 1 /* compiles... TODO use routing socket to determine */ michael@0: #define SCTP_ROUTE_HAS_VALID_IFN(ro) ((ro)->ro_rt && (ro)->ro_rt->rt_ifp) michael@0: #endif michael@0: michael@0: /* michael@0: * general memory allocation michael@0: */ michael@0: #define SCTP_MALLOC(var, type, size, name) \ michael@0: do { \ michael@0: MALLOC(var, type, size, name, M_NOWAIT); \ michael@0: } while (0) michael@0: michael@0: #define SCTP_FREE(var, type) FREE(var, type) michael@0: michael@0: #define SCTP_MALLOC_SONAME(var, type, size) \ michael@0: do { \ michael@0: MALLOC(var, type, size, M_SONAME, (M_WAITOK | M_ZERO)); \ michael@0: } while (0) michael@0: michael@0: #define SCTP_FREE_SONAME(var) FREE(var, M_SONAME) michael@0: michael@0: #define SCTP_PROCESS_STRUCT struct proc * michael@0: michael@0: /* michael@0: * zone allocation functions michael@0: */ michael@0: michael@0: michael@0: #if defined(SCTP_SIMPLE_ALLOCATOR) michael@0: /*typedef size_t sctp_zone_t;*/ michael@0: #define SCTP_ZONE_INIT(zone, name, size, number) { \ michael@0: zone = size; \ michael@0: } michael@0: michael@0: /* __Userspace__ SCTP_ZONE_GET: allocate element from the zone */ michael@0: #define SCTP_ZONE_GET(zone, type) \ michael@0: (type *)malloc(zone); michael@0: michael@0: michael@0: /* __Userspace__ SCTP_ZONE_FREE: free element from the zone */ michael@0: #define SCTP_ZONE_FREE(zone, element) { \ michael@0: free(element); \ michael@0: } michael@0: michael@0: #define SCTP_ZONE_DESTROY(zone) michael@0: #else michael@0: /*__Userspace__ michael@0: Compiling & linking notes: Needs libumem, which has been placed in ./user_lib michael@0: All userspace header files are in ./user_include. Makefile will need the michael@0: following. michael@0: CFLAGS = -I./ -Wall michael@0: LDFLAGS = -L./user_lib -R./user_lib -lumem michael@0: */ michael@0: #include "user_include/umem.h" michael@0: michael@0: /* __Userspace__ SCTP_ZONE_INIT: initialize the zone */ michael@0: /* michael@0: __Userspace__ michael@0: No equivalent function to uma_zone_set_max added yet. (See SCTP_ZONE_INIT in sctp_os_bsd.h michael@0: for reference). It may not be required as mentioned in michael@0: http://nixdoc.net/man-pages/FreeBSD/uma_zalloc.9.html that michael@0: max limits may not enforced on systems with more than one CPU. michael@0: */ michael@0: #define SCTP_ZONE_INIT(zone, name, size, number) { \ michael@0: zone = umem_cache_create(name, size, 0, NULL, NULL, NULL, NULL, NULL, 0); \ michael@0: } michael@0: michael@0: /* __Userspace__ SCTP_ZONE_GET: allocate element from the zone */ michael@0: #define SCTP_ZONE_GET(zone, type) \ michael@0: (type *)umem_cache_alloc(zone, UMEM_DEFAULT); michael@0: michael@0: michael@0: /* __Userspace__ SCTP_ZONE_FREE: free element from the zone */ michael@0: #define SCTP_ZONE_FREE(zone, element) \ michael@0: umem_cache_free(zone, element); michael@0: michael@0: michael@0: /* __Userspace__ SCTP_ZONE_DESTROY: destroy the zone */ michael@0: #define SCTP_ZONE_DESTROY(zone) \ michael@0: umem_cache_destroy(zone); michael@0: #endif michael@0: michael@0: /* global struct ifaddrs used in sctp_init_ifns_for_vrf getifaddrs call michael@0: * but references to fields are needed to persist as the vrf is queried. michael@0: * getifaddrs allocates memory that needs to be freed with a freeifaddrs michael@0: * call; this global is used to call freeifaddrs upon in sctp_pcb_finish michael@0: */ michael@0: extern struct ifaddrs *g_interfaces; michael@0: michael@0: michael@0: /* michael@0: * __Userspace__ Defining sctp_hashinit_flags() and sctp_hashdestroy() for userland. michael@0: */ michael@0: void *sctp_hashinit_flags(int elements, struct malloc_type *type, michael@0: u_long *hashmask, int flags); michael@0: void michael@0: sctp_hashdestroy(void *vhashtbl, struct malloc_type *type, u_long hashmask); michael@0: michael@0: void michael@0: sctp_hashfreedestroy(void *vhashtbl, struct malloc_type *type, u_long hashmask); michael@0: michael@0: michael@0: #define HASH_NOWAIT 0x00000001 michael@0: #define HASH_WAITOK 0x00000002 michael@0: michael@0: /* M_PCB is MALLOC_DECLARE'd in sys/socketvar.h */ michael@0: #define SCTP_HASH_INIT(size, hashmark) sctp_hashinit_flags(size, M_PCB, hashmark, HASH_NOWAIT) michael@0: michael@0: #define SCTP_HASH_FREE(table, hashmark) sctp_hashdestroy(table, M_PCB, hashmark) michael@0: michael@0: #define SCTP_HASH_FREE_DESTROY(table, hashmark) sctp_hashfreedestroy(table, M_PCB, hashmark) michael@0: #define SCTP_M_COPYM m_copym michael@0: michael@0: /* michael@0: * timers michael@0: */ michael@0: /* __Userspace__ michael@0: * user_sctp_callout.h has typedef struct sctp_callout sctp_os_timer_t; michael@0: * which is used in the timer related functions such as michael@0: * SCTP_OS_TIMER_INIT etc. michael@0: */ michael@0: #include michael@0: michael@0: /* __Userspace__ Creating a receive thread */ michael@0: #include michael@0: michael@0: /*__Userspace__ defining KTR_SUBSYS 1 as done in sctp_os_macosx.h */ michael@0: #define KTR_SUBSYS 1 michael@0: michael@0: #define sctp_get_tick_count() (ticks) michael@0: michael@0: /* The packed define for 64 bit platforms */ michael@0: #if !defined(__Userspace_os_Windows) michael@0: #define SCTP_PACKED __attribute__((packed)) michael@0: #define SCTP_UNUSED __attribute__((unused)) michael@0: #else michael@0: #define SCTP_PACKED michael@0: #define SCTP_UNUSED michael@0: #endif michael@0: michael@0: /* michael@0: * Functions michael@0: */ michael@0: /* Mbuf manipulation and access macros */ michael@0: #define SCTP_BUF_LEN(m) (m->m_len) michael@0: #define SCTP_BUF_NEXT(m) (m->m_next) michael@0: #define SCTP_BUF_NEXT_PKT(m) (m->m_nextpkt) michael@0: #define SCTP_BUF_RESV_UF(m, size) m->m_data += size michael@0: #define SCTP_BUF_AT(m, size) m->m_data + size michael@0: #define SCTP_BUF_IS_EXTENDED(m) (m->m_flags & M_EXT) michael@0: #define SCTP_BUF_EXTEND_SIZE(m) (m->m_ext.ext_size) michael@0: #define SCTP_BUF_TYPE(m) (m->m_type) michael@0: #define SCTP_BUF_RECVIF(m) (m->m_pkthdr.rcvif) michael@0: #define SCTP_BUF_PREPEND M_PREPEND michael@0: michael@0: #define SCTP_ALIGN_TO_END(m, len) if(m->m_flags & M_PKTHDR) { \ michael@0: MH_ALIGN(m, len); \ michael@0: } else if ((m->m_flags & M_EXT) == 0) { \ michael@0: M_ALIGN(m, len); \ michael@0: } michael@0: michael@0: /* We make it so if you have up to 4 threads michael@0: * writting based on the default size of michael@0: * the packet log 65 k, that would be michael@0: * 4 16k packets before we would hit michael@0: * a problem. michael@0: */ michael@0: #define SCTP_PKTLOG_WRITERS_NEED_LOCK 3 michael@0: michael@0: michael@0: /* michael@0: * routes, output, etc. michael@0: */ michael@0: michael@0: typedef struct sctp_route sctp_route_t; michael@0: typedef struct sctp_rtentry sctp_rtentry_t; michael@0: michael@0: static inline void sctp_userspace_rtalloc(sctp_route_t *ro) michael@0: { michael@0: if (ro->ro_rt != NULL) { michael@0: ro->ro_rt->rt_refcnt++; michael@0: return; michael@0: } michael@0: michael@0: ro->ro_rt = (sctp_rtentry_t *) malloc(sizeof(sctp_rtentry_t)); michael@0: if (ro->ro_rt == NULL) michael@0: return; michael@0: michael@0: /* initialize */ michael@0: memset(ro->ro_rt, 0, sizeof(sctp_rtentry_t)); michael@0: ro->ro_rt->rt_refcnt = 1; michael@0: michael@0: /* set MTU */ michael@0: /* TODO set this based on the ro->ro_dst, looking up MTU with routing socket */ michael@0: #if 0 michael@0: if (userspace_rawroute == -1) { michael@0: userspace_rawroute = socket(AF_ROUTE, SOCK_RAW, 0); michael@0: if (userspace_rawroute == -1) michael@0: return; michael@0: } michael@0: #endif michael@0: ro->ro_rt->rt_rmx.rmx_mtu = 1500; /* FIXME temporary solution */ michael@0: michael@0: /* TODO enable the ability to obtain interface index of route for michael@0: * SCTP_GET_IF_INDEX_FROM_ROUTE macro. michael@0: */ michael@0: } michael@0: #define SCTP_RTALLOC(ro, vrf_id) sctp_userspace_rtalloc((sctp_route_t *)ro) michael@0: michael@0: /* dummy rtfree needed once user_route.h is included */ michael@0: static inline void sctp_userspace_rtfree(sctp_rtentry_t *rt) michael@0: { michael@0: if(rt == NULL) { michael@0: return; michael@0: } michael@0: if(--rt->rt_refcnt > 0) { michael@0: return; michael@0: } michael@0: free(rt); michael@0: rt = NULL; michael@0: } michael@0: #define rtfree(arg1) sctp_userspace_rtfree(arg1) michael@0: michael@0: michael@0: /*************************/ michael@0: /* MTU */ michael@0: /*************************/ michael@0: int sctp_userspace_get_mtu_from_ifn(uint32_t if_index, int af); michael@0: michael@0: #define SCTP_GATHER_MTU_FROM_IFN_INFO(ifn, ifn_index, af) sctp_userspace_get_mtu_from_ifn(ifn_index, af) michael@0: michael@0: #define SCTP_GATHER_MTU_FROM_ROUTE(sctp_ifa, sa, rt) ((rt != NULL) ? rt->rt_rmx.rmx_mtu : 0) michael@0: michael@0: #define SCTP_GATHER_MTU_FROM_INTFC(sctp_ifn) sctp_userspace_get_mtu_from_ifn(if_nametoindex(((struct ifaddrs *) (sctp_ifn))->ifa_name), AF_INET) michael@0: michael@0: #define SCTP_SET_MTU_OF_ROUTE(sa, rt, mtu) do { \ michael@0: if (rt != NULL) \ michael@0: rt->rt_rmx.rmx_mtu = mtu; \ michael@0: } while(0) michael@0: michael@0: /* (de-)register interface event notifications */ michael@0: #define SCTP_REGISTER_INTERFACE(ifhandle, af) michael@0: #define SCTP_DEREGISTER_INTERFACE(ifhandle, af) michael@0: michael@0: michael@0: /*************************/ michael@0: /* These are for logging */ michael@0: /*************************/ michael@0: /* return the base ext data pointer */ michael@0: #define SCTP_BUF_EXTEND_BASE(m) (m->m_ext.ext_buf) michael@0: /* return the refcnt of the data pointer */ michael@0: #define SCTP_BUF_EXTEND_REFCNT(m) (*m->m_ext.ref_cnt) michael@0: /* return any buffer related flags, this is michael@0: * used beyond logging for apple only. michael@0: */ michael@0: #define SCTP_BUF_GET_FLAGS(m) (m->m_flags) michael@0: michael@0: /* For BSD this just accesses the M_PKTHDR length michael@0: * so it operates on an mbuf with hdr flag. Other michael@0: * O/S's may have seperate packet header and mbuf michael@0: * chain pointers.. thus the macro. michael@0: */ michael@0: #define SCTP_HEADER_TO_CHAIN(m) (m) michael@0: #define SCTP_DETACH_HEADER_FROM_CHAIN(m) michael@0: #define SCTP_HEADER_LEN(m) ((m)->m_pkthdr.len) michael@0: #define SCTP_GET_HEADER_FOR_OUTPUT(o_pak) 0 michael@0: #define SCTP_RELEASE_HEADER(m) michael@0: #define SCTP_RELEASE_PKT(m) sctp_m_freem(m) michael@0: /* UDP __Userspace__ - dummy definition */ michael@0: #define SCTP_ENABLE_UDP_CSUM(m) m=m michael@0: /* BSD definition */ michael@0: /* #define SCTP_ENABLE_UDP_CSUM(m) do { \ */ michael@0: /* m->m_pkthdr.csum_flags = CSUM_UDP; \ */ michael@0: /* m->m_pkthdr.csum_data = offsetof(struct udphdr, uh_sum); \ */ michael@0: /* } while (0) */ michael@0: michael@0: #define SCTP_GET_PKT_VRFID(m, vrf_id) ((vrf_id = SCTP_DEFAULT_VRFID) != SCTP_DEFAULT_VRFID) michael@0: michael@0: michael@0: michael@0: /* Attach the chain of data into the sendable packet. */ michael@0: #define SCTP_ATTACH_CHAIN(pak, m, packet_length) do { \ michael@0: pak = m; \ michael@0: pak->m_pkthdr.len = packet_length; \ michael@0: } while(0) michael@0: michael@0: /* Other m_pkthdr type things */ michael@0: /* FIXME need real definitions */ michael@0: #define SCTP_IS_IT_BROADCAST(dst, m) 0 michael@0: /* OOTB only #define SCTP_IS_IT_BROADCAST(dst, m) ((m->m_flags & M_PKTHDR) ? in_broadcast(dst, m->m_pkthdr.rcvif) : 0) BSD def */ michael@0: #define SCTP_IS_IT_LOOPBACK(m) 0 michael@0: /* OOTB ONLY #define SCTP_IS_IT_LOOPBACK(m) ((m->m_flags & M_PKTHDR) && ((m->m_pkthdr.rcvif == NULL) || (m->m_pkthdr.rcvif->if_type == IFT_LOOP))) BSD def */ michael@0: michael@0: michael@0: /* This converts any input packet header michael@0: * into the chain of data holders, for BSD michael@0: * its a NOP. michael@0: */ michael@0: michael@0: /* get the v6 hop limit */ michael@0: #define SCTP_GET_HLIM(inp, ro) 128 /* As done for __Windows__ */ michael@0: #define IPv6_HOP_LIMIT 128 michael@0: michael@0: /* is the endpoint v6only? */ michael@0: #define SCTP_IPV6_V6ONLY(inp) (((struct inpcb *)inp)->inp_flags & IN6P_IPV6_V6ONLY) michael@0: /* is the socket non-blocking? */ michael@0: #define SCTP_SO_IS_NBIO(so) ((so)->so_state & SS_NBIO) michael@0: #define SCTP_SET_SO_NBIO(so) ((so)->so_state |= SS_NBIO) michael@0: #define SCTP_CLEAR_SO_NBIO(so) ((so)->so_state &= ~SS_NBIO) michael@0: /* get the socket type */ michael@0: #define SCTP_SO_TYPE(so) ((so)->so_type) michael@0: michael@0: /* reserve sb space for a socket */ michael@0: #define SCTP_SORESERVE(so, send, recv) soreserve(so, send, recv) michael@0: michael@0: /* wakeup a socket */ michael@0: #define SCTP_SOWAKEUP(so) wakeup(&(so)->so_timeo, so) michael@0: /* clear the socket buffer state */ michael@0: #define SCTP_SB_CLEAR(sb) \ michael@0: (sb).sb_cc = 0; \ michael@0: (sb).sb_mb = NULL; \ michael@0: (sb).sb_mbcnt = 0; michael@0: michael@0: #define SCTP_SB_LIMIT_RCV(so) so->so_rcv.sb_hiwat michael@0: #define SCTP_SB_LIMIT_SND(so) so->so_snd.sb_hiwat michael@0: michael@0: /* Future zero copy wakeup/send function */ michael@0: #define SCTP_ZERO_COPY_EVENT(inp, so) michael@0: /* This is re-pulse ourselves for sendbuf */ michael@0: #define SCTP_ZERO_COPY_SENDQ_EVENT(inp, so) michael@0: michael@0: #define SCTP_READ_RANDOM(buf, len) read_random(buf, len) michael@0: michael@0: #define SCTP_SHA1_CTX struct sctp_sha1_context michael@0: #define SCTP_SHA1_INIT sctp_sha1_init michael@0: #define SCTP_SHA1_UPDATE sctp_sha1_update michael@0: #define SCTP_SHA1_FINAL(x,y) sctp_sha1_final((unsigned char *)x, y) michael@0: michael@0: /* start OOTB only stuff */ michael@0: /* TODO IFT_LOOP is in net/if_types.h on Linux */ michael@0: #define IFT_LOOP 0x18 michael@0: michael@0: /* sctp_pcb.h */ michael@0: michael@0: #if defined(__Userspace_os_Windows) michael@0: #define SHUT_RD 1 michael@0: #define SHUT_WR 2 michael@0: #define SHUT_RDWR 3 michael@0: #endif michael@0: #define PRU_FLUSH_RD SHUT_RD michael@0: #define PRU_FLUSH_WR SHUT_WR michael@0: #define PRU_FLUSH_RDWR SHUT_RDWR michael@0: michael@0: /* netinet/ip_var.h defintions are behind an if defined for _KERNEL on FreeBSD */ michael@0: #define IP_RAWOUTPUT 0x2 michael@0: michael@0: michael@0: /* end OOTB only stuff */ michael@0: michael@0: #define AF_CONN 123 michael@0: struct sockaddr_conn { michael@0: #ifdef HAVE_SCONN_LEN michael@0: uint8_t sconn_len; michael@0: #endif michael@0: uint8_t sconn_family; michael@0: uint16_t sconn_port; michael@0: void *sconn_addr; michael@0: }; michael@0: michael@0: /* michael@0: * SCTP protocol specific mbuf flags. michael@0: */ michael@0: #define M_NOTIFICATION M_PROTO5 /* SCTP notification */ michael@0: michael@0: /* michael@0: * IP output routines michael@0: */ michael@0: michael@0: /* Defining SCTP_IP_ID macro. michael@0: In netinet/ip_output.c, we have u_short ip_id; michael@0: In netinet/ip_var.h, we have extern u_short ip_id; (enclosed within _KERNEL_) michael@0: See static __inline uint16_t ip_newid(void) in netinet/ip_var.h michael@0: */ michael@0: #define SCTP_IP_ID(inp) (ip_id) michael@0: michael@0: /* need sctphdr to get port in SCTP_IP_OUTPUT. sctphdr defined in sctp.h */ michael@0: #include michael@0: extern void sctp_userspace_ip_output(int *result, struct mbuf *o_pak, michael@0: sctp_route_t *ro, void *stcb, michael@0: uint32_t vrf_id); michael@0: michael@0: #define SCTP_IP_OUTPUT(result, o_pak, ro, stcb, vrf_id) sctp_userspace_ip_output(&result, o_pak, ro, stcb, vrf_id); michael@0: michael@0: #if defined(INET6) michael@0: extern void sctp_userspace_ip6_output(int *result, struct mbuf *o_pak, michael@0: struct route_in6 *ro, void *stcb, michael@0: uint32_t vrf_id); michael@0: #define SCTP_IP6_OUTPUT(result, o_pak, ro, ifp, stcb, vrf_id) sctp_userspace_ip6_output(&result, o_pak, ro, stcb, vrf_id); michael@0: #endif michael@0: michael@0: michael@0: michael@0: #if 0 michael@0: #define SCTP_IP6_OUTPUT(result, o_pak, ro, ifp, stcb, vrf_id) \ michael@0: { \ michael@0: if (stcb && stcb->sctp_ep) \ michael@0: result = ip6_output(o_pak, \ michael@0: ((struct in6pcb *)(stcb->sctp_ep))->in6p_outputopts, \ michael@0: (ro), 0, 0, ifp, NULL); \ michael@0: else \ michael@0: result = ip6_output(o_pak, NULL, (ro), 0, 0, ifp, NULL); \ michael@0: } michael@0: #endif michael@0: michael@0: struct mbuf * michael@0: sctp_get_mbuf_for_msg(unsigned int space_needed, int want_header, int how, int allonebuf, int type); michael@0: michael@0: michael@0: /* with the current included files, this is defined in Linux but michael@0: * in FreeBSD, it is behind a _KERNEL in sys/socket.h ... michael@0: */ michael@0: #if defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD) || defined(__Userspace_os_OpenBSD) michael@0: /* stolen from /usr/include/sys/socket.h */ michael@0: #define CMSG_ALIGN(n) _ALIGN(n) michael@0: #elif defined(__Userspace_os_NetBSD) michael@0: #define CMSG_ALIGN(n) (((n) + __ALIGNBYTES) & ~__ALIGNBYTES) michael@0: #elif defined(__Userspace_os_Darwin) michael@0: #if !defined(__DARWIN_ALIGNBYTES) michael@0: #define __DARWIN_ALIGNBYTES (sizeof(__darwin_size_t) - 1) michael@0: #endif michael@0: michael@0: #if !defined(__DARWIN_ALIGN) michael@0: #define __DARWIN_ALIGN(p) ((__darwin_size_t)((char *)(uintptr_t)(p) + __DARWIN_ALIGNBYTES) &~ __DARWIN_ALIGNBYTES) michael@0: #endif michael@0: michael@0: #if !defined(__DARWIN_ALIGNBYTES32) michael@0: #define __DARWIN_ALIGNBYTES32 (sizeof(__uint32_t) - 1) michael@0: #endif michael@0: michael@0: #if !defined(__DARWIN_ALIGN32) michael@0: #define __DARWIN_ALIGN32(p) ((__darwin_size_t)((char *)(uintptr_t)(p) + __DARWIN_ALIGNBYTES32) &~ __DARWIN_ALIGNBYTES32) michael@0: #endif michael@0: #define CMSG_ALIGN(n) __DARWIN_ALIGN32(n) michael@0: #endif michael@0: #define I_AM_HERE \ michael@0: do { \ michael@0: SCTP_PRINTF("%s:%d at %s\n", __FILE__, __LINE__ , __FUNCTION__); \ michael@0: } while (0) michael@0: michael@0: #ifndef timevalsub michael@0: #define timevalsub(tp1, tp2) \ michael@0: do { \ michael@0: (tp1)->tv_sec -= (tp2)->tv_sec; \ michael@0: (tp1)->tv_usec -= (tp2)->tv_usec; \ michael@0: if ((tp1)->tv_usec < 0) { \ michael@0: (tp1)->tv_sec--; \ michael@0: (tp1)->tv_usec += 1000000; \ michael@0: } \ michael@0: } while (0) michael@0: #endif michael@0: michael@0: #if defined(__Userspace_os_Linux) michael@0: #if !defined(TAILQ_FOREACH_SAFE) michael@0: #define TAILQ_FOREACH_SAFE(var, head, field, tvar) \ michael@0: for ((var) = ((head)->tqh_first); \ michael@0: (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \ michael@0: (var) = (tvar)) michael@0: #endif michael@0: #if !defined(LIST_FOREACH_SAFE) michael@0: #define LIST_FOREACH_SAFE(var, head, field, tvar) \ michael@0: for ((var) = ((head)->lh_first); \ michael@0: (var) && ((tvar) = LIST_NEXT((var), field), 1); \ michael@0: (var) = (tvar)) michael@0: #endif michael@0: #endif michael@0: #if defined(__Userspace_os_DragonFly) michael@0: #define TAILQ_FOREACH_SAFE TAILQ_FOREACH_MUTABLE michael@0: #define LIST_FOREACH_SAFE LIST_FOREACH_MUTABLE michael@0: #endif michael@0: #endif