diff --git a/CMakeLists.txt b/CMakeLists.txt index 0f71833..1ebfcb3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt
@@ -29,102 +29,62 @@ # SUCH DAMAGE. # -cmake_minimum_required(VERSION 2.6) project(usrsctplib) +cmake_minimum_required(VERSION 3.0) # Debug build type as default if (NOT CMAKE_BUILD_TYPE) - message(STATUS "No build type selected, using DEBUG") - set(CMAKE_BUILD_TYPE "DEBUG") + message(STATUS "No build type selected, using DEBUG") + set(CMAKE_BUILD_TYPE "DEBUG") endif () include(CheckStructHasMember) include(CheckIncludeFile) include(CheckIncludeFiles) - +include(CheckCCompilerFlag) ################################################# # CHECK OPTIONS ################################################# -option(INVARIANTS "Add runtime checks" 0) -if (INVARIANTS) - add_definitions(-DINVARIANTS) +option(sctp_invariants "Add runtime checks" 0) +if (sctp_invariants) + add_definitions(-DINVARIANTS) endif () -option(SCTP_DEBUG "Provide debug information" 1) -if (SCTP_DEBUG) - add_definitions(-DSCTP_DEBUG) +option(sctp_debug "Provide debug information" 1) +if (sctp_debug) + add_definitions(-DSCTP_DEBUG) endif () -option(INET "Support IPv4" 1) -if (INET) - add_definitions(-DINET) +option(sctp_inet "Support IPv4" 1) +if (sctp_inet) + add_definitions(-DINET) endif () -option(INET6 "Support IPv6" 1) -if (INET6) - add_definitions(-DINET6) +option(sctp_inet6 "Support IPv6" 1) +if (sctp_inet6) + add_definitions(-DINET6) endif () -option(SCTP_SIMPLE_ALLOCATOR " " 1) -if (SCTP_SIMPLE_ALLOCATOR) - add_definitions(-DSCTP_SIMPLE_ALLOCATOR) +option(sctp_werror "Thread warning as error" 1) + +option(sctp_link_programs_static "Link example programs static" 0) + +option(sctp_build_programs "Build example programs" 1) + +option(sctp_sanitizer_address "Compile with address sanitizer" 0) + +option(sctp_sanitizer_memory "Compile with memory sanitizer" 0) + +if (sctp_sanitizer_address AND sctp_sanitizer_memory) + message(FATAL_ERROR "Can not compile with both sanitizer options") endif () -option(SCTP_PROCESS_LEVEL_LOCKS " " 1) -if (SCTP_PROCESS_LEVEL_LOCKS) - add_definitions(-DSCTP_PROCESS_LEVEL_LOCKS) -endif () - -option(SCTP_WITH_NO_CSUM "Disable SCTP checksum" 0) -if (SCTP_WITH_NO_CSUM) - add_definitions(-DSCTP_WITH_NO_CSUM) -endif () - -option(SCTP_MBUF_LOGGING " " 0) -if (SCTP_MBUF_LOGGING) - add_definitions(-DSCTP_MBUF_LOGGING) -endif () - -option(SCTP_PACKET_LOGGING " " 0) -if (SCTP_PACKET_LOGGING) - add_definitions(-DSCTP_PACKET_LOGGING) -endif () - -option(SCTP_SO_LOCK_TESTING " " 0) -if (SCTP_SO_LOCK_TESTING) - add_definitions(-DSCTP_SO_LOCK_TESTING) -endif () - -option(SCTP_EMBEDDED_V6_SCOPE " " 0) -if (SCTP_EMBEDDED_V6_SCOPE) - add_definitions(-DSCTP_EMBEDDED_V6_SCOPE) -endif () - -option(SCTP_KAME " " 0) -if (SCTP_KAME) - add_definitions(-DSCTP_KAME) -endif () - -option(WERROR "Warning as error" 1) - -option(LINK_PROGRAMS_STATIC "Link example programs static" 0) - -option(BUILD_PROGRAMS "Build example programs" 1) - -option(SANITIZER_ADDRESS "Compile with address sanitizer" 0) - -option(SANITIZER_MEMORY "Compile with memory sanitizer" 0) - -if (SANITIZER_ADDRESS AND SANITIZER_MEMORY) - message(FATAL_ERROR "Can not compile with both sanitizer options") -endif () - -if (LINK_PROGRAMS_STATIC OR WIN32) - set(PROGRAMS_LINK_LIBRARY "usrsctp-static") +if (sctp_link_programs_static OR WIN32) + set(programs_link_library "usrsctp-static") else () - set(PROGRAMS_LINK_LIBRARY "usrsctp") + set(programs_link_library "usrsctp") endif () @@ -132,29 +92,29 @@ # CHECK FOR TYPES AND FUNCTIONS ################################################# -check_include_files("sys/queue.h" HAVE_SYS_QUEUE_H) -if (HAVE_SYS_QUEUE_H) - add_definitions(-DHAVE_SYS_QUEUE_H) +check_include_files("sys/queue.h" have_sys_queue_h) +if (have_sys_queue_h) + add_definitions(-DHAVE_SYS_QUEUE_H) endif () -check_include_files("sys/socket.h;linux/if_addr.h" HAVE_LINUX_IF_ADDR_H) -if (HAVE_LINUX_IF_ADDR_H) - add_definitions(-DHAVE_LINUX_IF_ADDR_H) +check_include_files("sys/socket.h;linux/if_addr.h" have_linux_if_addr_h) +if (have_linux_if_addr_h) + add_definitions(-DHAVE_LINUX_IF_ADDR_H) endif () -check_include_files("sys/socket.h;linux/rtnetlink.h" HAVE_LINUX_RTNETLINK_H) -if (HAVE_LINUX_RTNETLINK_H) - add_definitions(-DHAVE_LINUX_RTNETLINK_H) +check_include_files("sys/socket.h;linux/rtnetlink.h" have_linux_rtnetlink_h) +if (have_linux_rtnetlink_h) + add_definitions(-DHAVE_LINUX_RTNETLINK_H) endif () -check_include_files("sys/types.h;netinet/in.h;netinet/ip.h;netinet/ip_icmp.h" HAVE_NETINET_IP_ICMP_H) -if (HAVE_NETINET_IP_ICMP_H) - add_definitions(-DHAVE_NETINET_IP_ICMP_H) +check_include_files("sys/types.h;netinet/in.h;netinet/ip.h;netinet/ip_icmp.h" have_netinet_ip_icmp_h) +if (have_netinet_ip_icmp_h) + add_definitions(-DHAVE_NETINET_IP_ICMP_H) endif () -check_include_files("stdatomic.h" HAVE_STDATOMIC_H) -if (HAVE_STDATOMIC_H) - add_definitions(-DHAVE_STDATOMIC_H) +check_include_files("stdatomic.h" have_stdatomic_h) +if (have_stdatomic_h) + add_definitions(-DHAVE_STDATOMIC_H) endif () @@ -162,34 +122,35 @@ # CHECK STRUCT MEMBERS ################################################# -set (CMAKE_REQUIRED_INCLUDES "${CMAKE_SOURCE_DIR}/usrsctplib") -check_include_file(usrsctp.h HAVE_USRSCTP_H) -if (NOT HAVE_USRSCTP_H) - message(FATAL_ERROR "usrsctp.h not found") +set(CMAKE_REQUIRED_INCLUDES "${CMAKE_SOURCE_DIR}/usrsctplib") + +check_include_file(usrsctp.h have_usrsctp_h) +if (NOT have_usrsctp_h) + message(FATAL_ERROR "usrsctp.h not found") endif () -check_struct_has_member("struct sockaddr" "sa_len" "sys/types.h;sys/socket.h" HAVE_SA_LEN) -if (HAVE_SA_LEN) - message(STATUS "HAVE_SA_LEN") - add_definitions(-DHAVE_SA_LEN) +check_struct_has_member("struct sockaddr" "sa_len" "sys/types.h;sys/socket.h" have_sa_len) +if (have_sa_len) + message(STATUS "have_sa_len") + add_definitions(-DHAVE_SA_LEN) endif () -check_struct_has_member("struct sockaddr_in" "sin_len" "sys/types.h;netinet/in.h" HAVE_SIN_LEN) -if (HAVE_SIN_LEN) - message(STATUS "HAVE_SIN_LEN") - add_definitions(-DHAVE_SIN_LEN) +check_struct_has_member("struct sockaddr_in" "sin_len" "sys/types.h;netinet/in.h" have_sin_len) +if (have_sin_len) + message(STATUS "have_sin_len") + add_definitions(-DHAVE_SIN_LEN) endif () -check_struct_has_member("struct sockaddr_in6" "sin6_len" "sys/types.h;netinet/in.h" HAVE_SIN6_LEN) -if (HAVE_SIN6_LEN) - message(STATUS "HAVE_SIN6_LEN") - add_definitions(-DHAVE_SIN6_LEN) +check_struct_has_member("struct sockaddr_in6" "sin6_len" "sys/types.h;netinet/in.h" have_sin6_len) +if (have_sin6_len) + message(STATUS "have_sin6_len") + add_definitions(-DHAVE_SIN6_LEN) endif () -check_struct_has_member("struct sockaddr_conn" "sconn_len" "usrsctp.h" HAVE_SCONN_LEN) -if (HAVE_SCONN_LEN) - message(STATUS "HAVE_SCONN_LEN") - add_definitions(-DHAVE_SCONN_LEN) +check_struct_has_member("struct sockaddr_conn" "sconn_len" "usrsctp.h" have_sconn_len) +if (have_sconn_len) + message(STATUS "HAVE_SCONN_LEN") + add_definitions(-DHAVE_SCONN_LEN) endif () @@ -198,38 +159,85 @@ ################################################# # SETTINGS FOR UNIX COMPILER -if ("x${CMAKE_C_COMPILER_ID}" STREQUAL "xClang" OR "x${CMAKE_C_COMPILER_ID}" STREQUAL "xGNU") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -pedantic -Wall -Wextra -Wfloat-equal -Wshadow -Wpointer-arith -Winit-self -Wno-unused-function -Wno-unused-parameter") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c99 -pedantic -Wall -Wextra -Wfloat-equal -Wshadow -Wpointer-arith -Winit-self -Wno-unused-function -Wno-unused-parameter") +if ("${CMAKE_C_COMPILER_ID}" MATCHES "Clang" OR "${CMAKE_C_COMPILER_ID}" MATCHES "AppleClang" OR "${CMAKE_C_COMPILER_ID}" MATCHES "GNU") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -pedantic -Wall -Wextra") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c99 -pedantic -Wall -Wextra") - if (WERROR) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror") - endif () + check_c_compiler_flag(-Wfloat-equal has_wfloat_equal) + if (has_wfloat_equal) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wfloat-equal") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wfloat-equal") + endif () - if (SANITIZER_ADDRESS) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -O1 -fno-omit-frame-pointer -g -Wno-address-of-packed-member") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -O1 -fno-omit-frame-pointer -g -Wno-address-of-packed-member") - endif () + check_c_compiler_flag(-Wshadow has_wshadow) + if (has_wshadow) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wshadow") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wshadow") + endif () - if (SANITIZER_MEMORY) - # maybe add "-fPIE -pie" here - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=memory -fno-omit-frame-pointer -g -Wno-address-of-packed-member -fsanitize-memory-track-origins") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=memory -fno-omit-frame-pointer -g -Wno-address-of-packed-member -fsanitize-memory-track-origins") - endif () + check_c_compiler_flag(-Wpointer-arith has_wpointer_aritih) + if (has_wpointer_aritih) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wpointer-arith") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wpointer-arith") + endif () + + check_c_compiler_flag(-Wunreachable-code has_wunreachable_code) + if (has_wunreachable_code) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wunreachable-code") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wunreachable-code") + endif () + + check_c_compiler_flag(-Winit-self has_winit_self) + if (has_winit_self) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Winit-self") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Winit-self") + endif () + + check_c_compiler_flag(-Wno-unused-function has_wno_unused_function) + if (has_wno_unused_function) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-function") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-function") + endif () + + check_c_compiler_flag(-Wno-unused-parameter has_wno_unused_parameter) + if (has_wno_unused_parameter) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-parameter") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-parameter") + endif () + + check_c_compiler_flag(-Wno-unreachable-code has_wno_unreachable_code) + if (has_wno_unreachable_code) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unreachable-code") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unreachable-code") + endif () + + if (sctp_werror) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror") + endif () + + if (sctp_sanitizer_address) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fno-omit-frame-pointer -g") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fno-omit-frame-pointer -g") + endif () + + if (sctp_sanitizer_memory) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=memory -fno-omit-frame-pointer -g -fsanitize-memory-track-origins") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=memory -fno-omit-frame-pointer -g -fsanitize-memory-track-origins") + endif () endif () # SETTINGS FOR VISUAL STUDIO COMPILER if ("x${CMAKE_C_COMPILER_ID}" STREQUAL "xMSVC") - if (CMAKE_C_FLAGS MATCHES "/W[0-4]") - string(REGEX REPLACE "/W[0-4]" "/W3" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") - else () - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W3") - endif () + if (CMAKE_C_FLAGS MATCHES "/W[0-4]") + string(REGEX REPLACE "/W[0-4]" "/W3" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") + else () + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W3") + endif () - if (WERROR) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /WX") - endif () + if (WERROR) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /WX") + endif () endif () @@ -239,6 +247,6 @@ add_subdirectory(usrsctplib) -if (BUILD_PROGRAMS) - add_subdirectory(programs) +if (sctp_build_programs) + add_subdirectory(programs) endif ()
diff --git a/README.md b/README.md index 6fc164c..0f0f8b1 100644 --- a/README.md +++ b/README.md
@@ -1,4 +1,5 @@ # usrsctp +[![Coverity Scan Build Status](https://scan.coverity.com/projects/13430/badge.svg)](https://scan.coverity.com/projects/usrsctp) This is a userland SCTP stack supporting FreeBSD, Linux, Mac OS X and Windows.
diff --git a/configure.ac b/configure.ac index 2339ea7..a6bfbd9 100644 --- a/configure.ac +++ b/configure.ac
@@ -45,7 +45,7 @@ case $host_os in darwin*) - CFLAGS="$CFLAGS -std=c99 -Wno-deprecated-declarations -Wno-address-of-packed-member -D__APPLE_USE_RFC_2292" + CFLAGS="$CFLAGS -std=c99 -Wno-deprecated-declarations -D__APPLE_USE_RFC_2292" LIBCFLAGS="$LIBCFLAGS -U__APPLE__ -D__Userspace_os_Darwin" ;; dragonfly*) @@ -55,7 +55,7 @@ freebsd*) CFLAGS="$CFLAGS -std=c99 -pthread" if $CC --version | grep -q clang; then - CFLAGS="$CFLAGS -Wno-unknown-warning-option -Wno-address-of-packed-member" + CFLAGS="$CFLAGS -Wno-unknown-warning-option" LDFLAGS="$LDFLAGS -Qunused-arguments" fi LIBCFLAGS="$LIBCFLAGS -U__FreeBSD__ -D__Userspace_os_FreeBSD"
diff --git a/programs/CMakeLists.txt b/programs/CMakeLists.txt index 3026ddc..ab4c7fd 100644 --- a/programs/CMakeLists.txt +++ b/programs/CMakeLists.txt
@@ -49,11 +49,11 @@ ################################################# if (${CMAKE_SYSTEM_NAME} MATCHES "Linux") - add_definitions(-D_GNU_SOURCE) + add_definitions(-D_GNU_SOURCE) endif () if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") - add_definitions(-D__APPLE_USE_RFC_2292) + add_definitions(-D__APPLE_USE_RFC_2292) endif () @@ -68,32 +68,32 @@ # PROGRAMS ################################################# -set(CHECK_PROGRAMS - client.c - daytime_server.c - discard_server.c - echo_server.c - ekr_client.c - ekr_loop_offload.c - ekr_loop.c - ekr_peer.c - ekr_server.c - http_client.c - rtcweb.c - test_libmgmt.c - test_timer.c - tsctp.c +set(check_programs + client.c + daytime_server.c + discard_server.c + echo_server.c + ekr_client.c + ekr_loop_offload.c + ekr_loop.c + ekr_peer.c + ekr_server.c + http_client.c + rtcweb.c + test_libmgmt.c + test_timer.c + tsctp.c ) -foreach (SOURCE_FILE ${CHECK_PROGRAMS}) - get_filename_component(SOURCE_FILE_WE ${SOURCE_FILE} NAME_WE) - add_executable( - ${SOURCE_FILE_WE} - ${SOURCE_FILE} - ) +foreach (source_file ${check_programs}) + get_filename_component(source_file_we ${source_file} NAME_WE) + add_executable( + ${source_file_we} + ${source_file} + ) - target_link_libraries(${SOURCE_FILE_WE} - ${PROGRAMS_LINK_LIBRARY} - ${CMAKE_THREAD_LIBS_INIT} - ) + target_link_libraries(${source_file_we} + ${programs_link_library} + ${CMAKE_THREAD_LIBS_INIT} + ) endforeach ()
diff --git a/programs/client.c b/programs/client.c index 8dcad6f..1fe7579 100644 --- a/programs/client.c +++ b/programs/client.c
@@ -32,6 +32,9 @@ * Usage: client remote_addr remote_port [local_port] [local_encaps_port] [remote_encaps_port] */ +#ifdef _WIN32 +#define _CRT_SECURE_NO_WARNINGS +#endif #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -55,6 +58,206 @@ typedef char* caddr_t; #endif +static void +handle_association_change_event(struct sctp_assoc_change *sac) +{ + unsigned int i, n; + + printf("Association change "); + switch (sac->sac_state) { + case SCTP_COMM_UP: + printf("SCTP_COMM_UP"); + break; + case SCTP_COMM_LOST: + printf("SCTP_COMM_LOST"); + break; + case SCTP_RESTART: + printf("SCTP_RESTART"); + break; + case SCTP_SHUTDOWN_COMP: + printf("SCTP_SHUTDOWN_COMP"); + break; + case SCTP_CANT_STR_ASSOC: + printf("SCTP_CANT_STR_ASSOC"); + break; + default: + printf("UNKNOWN"); + break; + } + printf(", streams (in/out) = (%u/%u)", + sac->sac_inbound_streams, sac->sac_outbound_streams); + n = sac->sac_length - sizeof(struct sctp_assoc_change); + if (((sac->sac_state == SCTP_COMM_UP) || + (sac->sac_state == SCTP_RESTART)) && (n > 0)) { + printf(", supports"); + for (i = 0; i < n; i++) { + switch (sac->sac_info[i]) { + case SCTP_ASSOC_SUPPORTS_PR: + printf(" PR"); + break; + case SCTP_ASSOC_SUPPORTS_AUTH: + printf(" AUTH"); + break; + case SCTP_ASSOC_SUPPORTS_ASCONF: + printf(" ASCONF"); + break; + case SCTP_ASSOC_SUPPORTS_MULTIBUF: + printf(" MULTIBUF"); + break; + case SCTP_ASSOC_SUPPORTS_RE_CONFIG: + printf(" RE-CONFIG"); + break; + default: + printf(" UNKNOWN(0x%02x)", sac->sac_info[i]); + break; + } + } + } else if (((sac->sac_state == SCTP_COMM_LOST) || + (sac->sac_state == SCTP_CANT_STR_ASSOC)) && (n > 0)) { + printf(", ABORT ="); + for (i = 0; i < n; i++) { + printf(" 0x%02x", sac->sac_info[i]); + } + } + printf(".\n"); + if ((sac->sac_state == SCTP_CANT_STR_ASSOC) || + (sac->sac_state == SCTP_SHUTDOWN_COMP) || + (sac->sac_state == SCTP_COMM_LOST)) { + exit(0); + } + return; +} + +static void +handle_peer_address_change_event(struct sctp_paddr_change *spc) +{ + char addr_buf[INET6_ADDRSTRLEN]; + const char *addr; + struct sockaddr_in *sin; + struct sockaddr_in6 *sin6; + struct sockaddr_conn *sconn; + + switch (spc->spc_aaddr.ss_family) { + case AF_INET: + sin = (struct sockaddr_in *)&spc->spc_aaddr; + addr = inet_ntop(AF_INET, &sin->sin_addr, addr_buf, INET_ADDRSTRLEN); + break; + case AF_INET6: + sin6 = (struct sockaddr_in6 *)&spc->spc_aaddr; + addr = inet_ntop(AF_INET6, &sin6->sin6_addr, addr_buf, INET6_ADDRSTRLEN); + break; + case AF_CONN: + sconn = (struct sockaddr_conn *)&spc->spc_aaddr; +#ifdef _WIN32 + _snprintf(addr_buf, INET6_ADDRSTRLEN, "%p", sconn->sconn_addr); +#else + snprintf(addr_buf, INET6_ADDRSTRLEN, "%p", sconn->sconn_addr); +#endif + addr = addr_buf; + break; + default: +#ifdef _WIN32 + _snprintf(addr_buf, INET6_ADDRSTRLEN, "Unknown family %d", spc->spc_aaddr.ss_family); +#else + snprintf(addr_buf, INET6_ADDRSTRLEN, "Unknown family %d", spc->spc_aaddr.ss_family); +#endif + addr = addr_buf; + break; + } + printf("Peer address %s is now ", addr); + switch (spc->spc_state) { + case SCTP_ADDR_AVAILABLE: + printf("SCTP_ADDR_AVAILABLE"); + break; + case SCTP_ADDR_UNREACHABLE: + printf("SCTP_ADDR_UNREACHABLE"); + break; + case SCTP_ADDR_REMOVED: + printf("SCTP_ADDR_REMOVED"); + break; + case SCTP_ADDR_ADDED: + printf("SCTP_ADDR_ADDED"); + break; + case SCTP_ADDR_MADE_PRIM: + printf("SCTP_ADDR_MADE_PRIM"); + break; + case SCTP_ADDR_CONFIRMED: + printf("SCTP_ADDR_CONFIRMED"); + break; + default: + printf("UNKNOWN"); + break; + } + printf(" (error = 0x%08x).\n", spc->spc_error); + return; +} + +static void +handle_send_failed_event(struct sctp_send_failed_event *ssfe) +{ + size_t i, n; + + if (ssfe->ssfe_flags & SCTP_DATA_UNSENT) { + printf("Unsent "); + } + if (ssfe->ssfe_flags & SCTP_DATA_SENT) { + printf("Sent "); + } + if (ssfe->ssfe_flags & ~(SCTP_DATA_SENT | SCTP_DATA_UNSENT)) { + printf("(flags = %x) ", ssfe->ssfe_flags); + } + printf("message with PPID = %u, SID = %u, flags: 0x%04x due to error = 0x%08x", + ntohl(ssfe->ssfe_info.snd_ppid), ssfe->ssfe_info.snd_sid, + ssfe->ssfe_info.snd_flags, ssfe->ssfe_error); + n = ssfe->ssfe_length - sizeof(struct sctp_send_failed_event); + for (i = 0; i < n; i++) { + printf(" 0x%02x", ssfe->ssfe_data[i]); + } + printf(".\n"); + return; +} + +static void +handle_notification(union sctp_notification *notif, size_t n) +{ + if (notif->sn_header.sn_length != (uint32_t)n) { + return; + } + switch (notif->sn_header.sn_type) { + case SCTP_ASSOC_CHANGE: + handle_association_change_event(&(notif->sn_assoc_change)); + break; + case SCTP_PEER_ADDR_CHANGE: + handle_peer_address_change_event(&(notif->sn_paddr_change)); + break; + case SCTP_REMOTE_ERROR: + break; + case SCTP_SHUTDOWN_EVENT: + break; + case SCTP_ADAPTATION_INDICATION: + break; + case SCTP_PARTIAL_DELIVERY_EVENT: + break; + case SCTP_AUTHENTICATION_EVENT: + break; + case SCTP_SENDER_DRY_EVENT: + break; + case SCTP_NOTIFICATIONS_STOPPED_EVENT: + break; + case SCTP_SEND_FAILED_EVENT: + handle_send_failed_event(&(notif->sn_send_failed_event)); + break; + case SCTP_STREAM_RESET_EVENT: + break; + case SCTP_ASSOC_RESET_EVENT: + break; + case SCTP_STREAM_CHANGE_EVENT: + break; + default: + break; + } +} + static int receive_cb(struct socket *sock, union sctp_sockstore addr, void *data, size_t datalen, struct sctp_rcvinfo rcv, int flags, void *ulp_info) @@ -63,13 +266,17 @@ done = 1; usrsctp_close(sock); } else { + if (flags & MSG_NOTIFICATION) { + handle_notification((union sctp_notification *)data, datalen); + } else { #ifdef _WIN32 - _write(_fileno(stdout), data, (unsigned int)datalen); + _write(_fileno(stdout), data, (unsigned int)datalen); #else - if (write(fileno(stdout), data, datalen) < 0) { - perror("write"); - } + if (write(fileno(stdout), data, datalen) < 0) { + perror("write"); + } #endif + } free(data); } return (1); @@ -94,8 +301,13 @@ struct sockaddr_in6 addr6; struct sctp_udpencaps encaps; struct sctpstat stat; + struct sctp_event event; + uint16_t event_types[] = {SCTP_ASSOC_CHANGE, + SCTP_PEER_ADDR_CHANGE, + SCTP_SEND_FAILED_EVENT}; char buffer[80]; - int i, n; + unsigned int i; + int n; if (argc < 3) { printf("%s", "Usage: client remote_addr remote_port local_port local_encaps_port remote_encaps_port\n"); @@ -113,6 +325,15 @@ if ((sock = usrsctp_socket(AF_INET6, SOCK_STREAM, IPPROTO_SCTP, receive_cb, NULL, 0, NULL)) == NULL) { perror("usrsctp_socket"); } + memset(&event, 0, sizeof(event)); + event.se_assoc_id = SCTP_ALL_ASSOC; + event.se_on = 1; + for (i = 0; i < sizeof(event_types)/sizeof(uint16_t); i++) { + event.se_type = event_types[i]; + if (usrsctp_setsockopt(sock, IPPROTO_SCTP, SCTP_EVENT, &event, sizeof(event)) < 0) { + perror("setsockopt SCTP_EVENT"); + } + } if (argc > 3) { memset((void *)&addr6, 0, sizeof(struct sockaddr_in6)); #ifdef HAVE_SIN6_LEN @@ -161,7 +382,7 @@ } else { addr = addrs; printf("Local addresses: "); - for (i = 0; i < n; i++) { + for (i = 0; i < (unsigned int)n; i++) { if (i > 0) { printf("%s", ", "); } @@ -209,7 +430,7 @@ } else { addr = addrs; printf("Peer addresses: "); - for (i = 0; i < n; i++) { + for (i = 0; i < (unsigned int)n; i++) { if (i > 0) { printf("%s", ", "); } @@ -262,7 +483,7 @@ } while (!done) { #ifdef _WIN32 - Sleep(1*1000); + Sleep(1 * 1000); #else sleep(1); #endif @@ -272,7 +493,7 @@ stat.sctps_outpackets, stat.sctps_inpackets); while (usrsctp_finish() != 0) { #ifdef _WIN32 - Sleep(1000); + Sleep(1 * 1000); #else sleep(1); #endif
diff --git a/programs/daytime_server.c b/programs/daytime_server.c index 18a0fcb..35cadf5 100644 --- a/programs/daytime_server.c +++ b/programs/daytime_server.c
@@ -30,6 +30,10 @@ /* * Usage: daytime_server [local_encaps_port] [remote_encaps_port] + * + * Example + * Server: $ ./daytime_server 11111 22222 + * Client: $ ./client 127.0.0.1 13 0 22222 11111 */ #ifdef _WIN32 @@ -49,6 +53,10 @@ #endif #include <usrsctp.h> +#define PORT 13 +#define DAYTIME_PPID 40 +#define SLEEP 1 + void debug_printf(const char *format, ...) { @@ -59,7 +67,6 @@ va_end(ap); } -#define DAYTIME_PPID 40 int main(int argc, char *argv[]) { @@ -97,7 +104,7 @@ addr.sin_len = sizeof(struct sockaddr_in); #endif addr.sin_family = AF_INET; - addr.sin_port = htons(13); + addr.sin_port = htons(PORT); addr.sin_addr.s_addr = htonl(INADDR_ANY); if (usrsctp_bind(sock, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0) { perror("usrsctp_bind"); @@ -121,16 +128,18 @@ sndinfo.snd_ppid = htonl(DAYTIME_PPID); sndinfo.snd_context = 0; sndinfo.snd_assoc_id = 0; - usrsctp_sendv(conn_sock, buffer, strlen(buffer), NULL, 0, (void *)&sndinfo, - (socklen_t)sizeof(struct sctp_sndinfo), SCTP_SENDV_SNDINFO, 0); + if (usrsctp_sendv(conn_sock, buffer, strlen(buffer), NULL, 0, (void *)&sndinfo, + (socklen_t)sizeof(struct sctp_sndinfo), SCTP_SENDV_SNDINFO, 0) < 0) { + perror("usrsctp_sendv"); + } usrsctp_close(conn_sock); } usrsctp_close(sock); while (usrsctp_finish() != 0) { #ifdef _WIN32 - Sleep(1000); + Sleep(SLEEP * 1000); #else - sleep(1); + sleep(SLEEP); #endif } return (0);
diff --git a/programs/discard_server.c b/programs/discard_server.c index bc67cd5..39846dd 100644 --- a/programs/discard_server.c +++ b/programs/discard_server.c
@@ -30,6 +30,10 @@ /* * Usage: discard_server [local_encaps_port] [remote_encaps_port] + * + * Example + * Server: $ ./discard_server 11111 22222 + * Client: $ ./client 127.0.0.1 9 0 22222 11111 */ #ifdef _WIN32 @@ -48,7 +52,9 @@ #endif #include <usrsctp.h> +#define PORT 9 #define BUFFER_SIZE 10240 +#define SLEEP 1 const int use_cb = 0; @@ -189,7 +195,7 @@ addr.sin6_len = sizeof(struct sockaddr_in6); #endif addr.sin6_family = AF_INET6; - addr.sin6_port = htons(9); + addr.sin6_port = htons(PORT); addr.sin6_addr = in6addr_any; if (usrsctp_bind(sock, (struct sockaddr *)&addr, sizeof(struct sockaddr_in6)) < 0) { perror("usrsctp_bind"); @@ -200,9 +206,9 @@ while (1) { if (use_cb) { #ifdef _WIN32 - Sleep(1*1000); + Sleep(SLEEP * 1000); #else - sleep(1); + sleep(SLEEP); #endif } else { from_len = (socklen_t)sizeof(struct sockaddr_in6); @@ -239,9 +245,9 @@ usrsctp_close(sock); while (usrsctp_finish() != 0) { #ifdef _WIN32 - Sleep(1000); + Sleep(SLEEP * 1000); #else - sleep(1); + sleep(SLEEP); #endif } return (0);
diff --git a/programs/echo_server.c b/programs/echo_server.c index 1eab193..64f12c5 100644 --- a/programs/echo_server.c +++ b/programs/echo_server.c
@@ -29,7 +29,11 @@ */ /* - * Usage: discard_server [local_encaps_port] [remote_encaps_port] + * Usage: echo_server [local_encaps_port] [remote_encaps_port] + * + * Example + * Server: $ ./echo_server 11111 22222 + * Client: $ ./client 127.0.0.1 7 0 22222 11111 */ #ifdef _WIN32 @@ -48,7 +52,9 @@ #endif #include <usrsctp.h> +#define PORT 7 #define BUFFER_SIZE 10240 +#define SLEEP 1 const int use_cb = 0; @@ -204,7 +210,7 @@ addr.sin6_len = sizeof(struct sockaddr_in6); #endif addr.sin6_family = AF_INET6; - addr.sin6_port = htons(7); + addr.sin6_port = htons(PORT); addr.sin6_addr = in6addr_any; if (usrsctp_bind(sock, (struct sockaddr *)&addr, sizeof(struct sockaddr_in6)) < 0) { perror("usrsctp_bind"); @@ -215,9 +221,9 @@ while (1) { if (use_cb) { #ifdef _WIN32 - Sleep(1*1000); + Sleep(SLEEP * 1000); #else - sleep(1); + sleep(SLEEP); #endif } else { from_len = (socklen_t)sizeof(struct sockaddr_in6); @@ -269,9 +275,9 @@ usrsctp_close(sock); while (usrsctp_finish() != 0) { #ifdef _WIN32 - Sleep(1000); + Sleep(SLEEP * 1000); #else - sleep(1); + sleep(SLEEP); #endif } return (0);
diff --git a/programs/ekr_client.c b/programs/ekr_client.c index 5cef40c..1e5e7e3 100644 --- a/programs/ekr_client.c +++ b/programs/ekr_client.c
@@ -200,10 +200,12 @@ #ifdef _WIN32 if ((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) { printf("socket() failed with error: %d\n", WSAGetLastError()); + exit(EXIT_FAILURE); } #else if ((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { perror("socket"); + exit(EXIT_FAILURE); } #endif memset(&sin, 0, sizeof(struct sockaddr_in)); @@ -214,15 +216,17 @@ sin.sin_port = htons(atoi(argv[2])); if (!inet_pton(AF_INET, argv[1], &sin.sin_addr.s_addr)){ printf("error: invalid address\n"); - exit(1); + exit(EXIT_FAILURE); } #ifdef _WIN32 if (bind(fd, (struct sockaddr *)&sin, sizeof(struct sockaddr_in)) == SOCKET_ERROR) { printf("bind() failed with error: %d\n", WSAGetLastError()); + exit(EXIT_FAILURE); } #else if (bind(fd, (struct sockaddr *)&sin, sizeof(struct sockaddr_in)) < 0) { perror("bind"); + exit(EXIT_FAILURE); } #endif memset(&sin, 0, sizeof(struct sockaddr_in)); @@ -233,15 +237,17 @@ sin.sin_port = htons(atoi(argv[4])); if (!inet_pton(AF_INET, argv[3], &sin.sin_addr.s_addr)){ printf("error: invalid address\n"); - exit(1); + exit(EXIT_FAILURE); } #ifdef _WIN32 if (connect(fd, (struct sockaddr *)&sin, sizeof(struct sockaddr_in)) == SOCKET_ERROR) { printf("connect() failed with error: %d\n", WSAGetLastError()); + exit(EXIT_FAILURE); } #else if (connect(fd, (struct sockaddr *)&sin, sizeof(struct sockaddr_in)) < 0) { perror("connect"); + exit(EXIT_FAILURE); } #endif #ifdef SCTP_DEBUG
diff --git a/programs/ekr_loop.c b/programs/ekr_loop.c index 798e899..77e72c5 100644 --- a/programs/ekr_loop.c +++ b/programs/ekr_loop.c
@@ -383,7 +383,7 @@ }; #endif #ifdef SCTP_DEBUG - usrsctp_sysctl_set_sctp_debug_on(SCTP_DEBUG_ALL); + usrsctp_sysctl_set_sctp_debug_on(SCTP_DEBUG_NONE); #endif usrsctp_sysctl_set_sctp_ecn_enable(0); usrsctp_register_address((void *)&fd_c); @@ -399,7 +399,7 @@ exit(EXIT_FAILURE); } printf("Change send socket buffer size from %d ", cur_buf_size); - snd_buf_size = 1<<20; /* 1 MB */ + snd_buf_size = 1<<22; /* 4 MB */ if (usrsctp_setsockopt(s_c, SOL_SOCKET, SO_SNDBUF, &snd_buf_size, sizeof(int)) < 0) { perror("usrsctp_setsockopt"); exit(EXIT_FAILURE); @@ -489,7 +489,13 @@ sndinfo.snd_ppid = htonl(DISCARD_PPID); sndinfo.snd_context = 0; sndinfo.snd_assoc_id = 0; - /* Send a 1 MB message */ + /* Send a 1 MB ordered message */ + if (usrsctp_sendv(s_c, line, LINE_LENGTH, NULL, 0, (void *)&sndinfo, + (socklen_t)sizeof(struct sctp_sndinfo), SCTP_SENDV_SNDINFO, 0) < 0) { + perror("usrsctp_sendv"); + exit(EXIT_FAILURE); + } + /* Send a 1 MB ordered message */ if (usrsctp_sendv(s_c, line, LINE_LENGTH, NULL, 0, (void *)&sndinfo, (socklen_t)sizeof(struct sctp_sndinfo), SCTP_SENDV_SNDINFO, 0) < 0) { perror("usrsctp_sendv");
diff --git a/programs/ekr_peer.c b/programs/ekr_peer.c index b3cfe62..ca0c64d 100644 --- a/programs/ekr_peer.c +++ b/programs/ekr_peer.c
@@ -387,7 +387,7 @@ #ifdef _WIN32 if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) { printf("WSAStartup failed\n"); - exit (EXIT_FAILURE); + exit(EXIT_FAILURE); } #endif usrsctp_init(0, conn_output, debug_printf); @@ -395,10 +395,12 @@ #ifdef _WIN32 if ((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) { printf("socket() failed with error: %d\n", WSAGetLastError()); + exit(EXIT_FAILURE); } #else if ((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { perror("socket"); + exit(EXIT_FAILURE); } #endif memset(&sin, 0, sizeof(struct sockaddr_in)); @@ -409,15 +411,17 @@ sin.sin_port = htons(atoi(argv[2])); if (!inet_pton(AF_INET, argv[1], &sin.sin_addr.s_addr)){ printf("error: invalid address\n"); - exit(1); + exit(EXIT_FAILURE); } #ifdef _WIN32 if (bind(fd, (struct sockaddr *)&sin, sizeof(struct sockaddr_in)) == SOCKET_ERROR) { printf("bind() failed with error: %d\n", WSAGetLastError()); + exit(EXIT_FAILURE); } #else if (bind(fd, (struct sockaddr *)&sin, sizeof(struct sockaddr_in)) < 0) { perror("bind"); + exit(EXIT_FAILURE); } #endif memset(&sin, 0, sizeof(struct sockaddr_in)); @@ -428,15 +432,17 @@ sin.sin_port = htons(atoi(argv[4])); if (!inet_pton(AF_INET, argv[3], &sin.sin_addr.s_addr)){ printf("error: invalid address\n"); - exit(1); + exit(EXIT_FAILURE); } #ifdef _WIN32 if (connect(fd, (struct sockaddr *)&sin, sizeof(struct sockaddr_in)) == SOCKET_ERROR) { printf("connect() failed with error: %d\n", WSAGetLastError()); + exit(EXIT_FAILURE); } #else if (connect(fd, (struct sockaddr *)&sin, sizeof(struct sockaddr_in)) < 0) { perror("connect"); + exit(EXIT_FAILURE); } #endif #ifdef _WIN32
diff --git a/programs/ekr_server.c b/programs/ekr_server.c index 02f02b1..5545abb 100644 --- a/programs/ekr_server.c +++ b/programs/ekr_server.c
@@ -50,7 +50,9 @@ #endif #include <usrsctp.h> +#define PORT 5001 #define MAX_PACKET_SIZE (1<<16) +#define SLEEP 1 #ifdef _WIN32 static DWORD WINAPI @@ -196,10 +198,12 @@ #ifdef _WIN32 if ((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) { printf("socket() failed with error: %d\n", WSAGetLastError()); + exit(EXIT_FAILURE); } #else if ((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { perror("socket"); + exit(EXIT_FAILURE); } #endif memset(&sin, 0, sizeof(struct sockaddr_in)); @@ -210,15 +214,17 @@ sin.sin_port = htons(atoi(argv[2])); if (!inet_pton(AF_INET, argv[1], &sin.sin_addr.s_addr)){ printf("error: invalid address\n"); - exit(1); + exit(EXIT_FAILURE); } #ifdef _WIN32 if (bind(fd, (struct sockaddr *)&sin, sizeof(struct sockaddr_in)) == SOCKET_ERROR) { printf("bind() failed with error: %d\n", WSAGetLastError()); + exit(EXIT_FAILURE); } #else if (bind(fd, (struct sockaddr *)&sin, sizeof(struct sockaddr_in)) < 0) { perror("bind"); + exit(EXIT_FAILURE); } #endif memset(&sin, 0, sizeof(struct sockaddr_in)); @@ -229,15 +235,17 @@ sin.sin_port = htons(atoi(argv[4])); if (!inet_pton(AF_INET, argv[3], &sin.sin_addr.s_addr)){ printf("error: invalid address\n"); - exit(1); + exit(EXIT_FAILURE); } #ifdef _WIN32 if (connect(fd, (struct sockaddr *)&sin, sizeof(struct sockaddr_in)) == SOCKET_ERROR) { printf("connect() failed with error: %d\n", WSAGetLastError()); + exit(EXIT_FAILURE); } #else if (connect(fd, (struct sockaddr *)&sin, sizeof(struct sockaddr_in)) < 0) { perror("connect"); + exit(EXIT_FAILURE); } #endif #ifdef SCTP_DEBUG @@ -258,7 +266,7 @@ #ifdef HAVE_SCONN_LEN sconn.sconn_len = sizeof(struct sockaddr_conn); #endif - sconn.sconn_port = htons(5001); + sconn.sconn_port = htons(PORT); sconn.sconn_addr = (void *)&fd; if (usrsctp_bind(s, (struct sockaddr *)&sconn, sizeof(struct sockaddr_conn)) < 0) { perror("usrsctp_bind"); @@ -275,9 +283,9 @@ usrsctp_deregister_address((void *)&fd); while (usrsctp_finish() != 0) { #ifdef _WIN32 - Sleep(1000); + Sleep(SLEEP * 1000); #else - sleep(1); + sleep(SLEEP); #endif } #ifdef _WIN32
diff --git a/programs/http_client.c b/programs/http_client.c index 6dfd1ee..607ee26 100644 --- a/programs/http_client.c +++ b/programs/http_client.c
@@ -30,6 +30,9 @@ /* * Usage: http_client remote_addr remote_port [local_port] [local_encaps_port] [remote_encaps_port] [uri] + * + * Example + * Client: $ ./http_client 212.201.121.100 80 0 9899 9899 /cgi-bin/he */ #ifdef _WIN32
diff --git a/programs/rtcweb.c b/programs/rtcweb.c index 1e0b734..5c5908d 100644 --- a/programs/rtcweb.c +++ b/programs/rtcweb.c
@@ -146,11 +146,23 @@ #undef SCTP_PACKED static void +lock_peer_connection(struct peer_connection *); + +static void +unlock_peer_connection(struct peer_connection *); + +static void init_peer_connection(struct peer_connection *pc) { uint32_t i; struct channel *channel; +#ifdef _WIN32 + InitializeCriticalSection(&(pc->mutex)); +#else + pthread_mutex_init(&pc->mutex, NULL); +#endif + lock_peer_connection(pc); for (i = 0; i < NUMBER_OF_CHANNELS; i++) { channel = &(pc->channels[i]); channel->id = i; @@ -169,11 +181,7 @@ } pc->o_stream_buffer_counter = 0; pc->sock = NULL; -#ifdef _WIN32 - InitializeCriticalSection(&(pc->mutex)); -#else - pthread_mutex_init(&pc->mutex, NULL); -#endif + unlock_peer_connection(pc); } static void
diff --git a/programs/test_timer.c b/programs/test_timer.c index ba2cb50..90a93c8 100644 --- a/programs/test_timer.c +++ b/programs/test_timer.c
@@ -39,18 +39,13 @@ int main(void) { - int i; - void *p; + unsigned int i; usrsctp_init(0, NULL, NULL); -#ifdef SCTP_DEBUG - usrsctp_sysctl_set_sctp_debug_on(SCTP_DEBUG_ALL); -#endif printf("Entering the loop\n"); - p = &i; - for (i = 0; i < 100000; i++) { - usrsctp_register_address(p); - usrsctp_deregister_address(p); + for (i = 0; i < 1000000; i++) { + usrsctp_register_address(NULL); + usrsctp_deregister_address(NULL); } printf("Exited the loop\n"); while (usrsctp_finish() != 0) {
diff --git a/programs/tsctp.c b/programs/tsctp.c index 89811c1..c85da22 100644 --- a/programs/tsctp.c +++ b/programs/tsctp.c
@@ -414,7 +414,9 @@ fragpoint = atoi(optarg); break; case 'L': - inet_pton(AF_INET, optarg, &srcAddr); + if (inet_pton(AF_INET, optarg, &srcAddr) != 1) { + printf("Can't parse %s\n", optarg); + } break; case 'R': rcvbufsize = atoi(optarg);
diff --git a/usrsctplib/CMakeLists.txt b/usrsctplib/CMakeLists.txt index 942e01a..c5b7229 100644 --- a/usrsctplib/CMakeLists.txt +++ b/usrsctplib/CMakeLists.txt
@@ -36,15 +36,17 @@ set(VERSION "1.0.0") -set(prefix ${CMAKE_INSTALL_PREFIX}) -set(exec_prefix "\${prefix}") -set(libdir "\${exec_prefix}/lib") -set(includedir "\${prefix}/include/usrsctp") +set(prefix ${CMAKE_INSTALL_PREFIX}) +set(exec_prefix ${prefix}) +set(libdir ${exec_prefix}/lib) +set(includedir ${prefix}/include/usrsctp) set(CMAKE_REQUIRED_INCLUDES ${CMAKE_CURRENT_SOURCE_DIR}) -set(CMAKE_MACOSX_RPATH 1) +set(CMAKE_MACOSX_RPATH 1) add_definitions(-D__Userspace__) add_definitions(-D__Userspace_os_${CMAKE_SYSTEM_NAME}) +add_definitions(-DSCTP_SIMPLE_ALLOCATOR) +add_definitions(-DSCTP_PROCESS_LEVEL_LOCKS) ################################################# @@ -52,34 +54,32 @@ ################################################# if (${CMAKE_SYSTEM_NAME} MATCHES "Linux") - add_definitions(-D_GNU_SOURCE) - #set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-address-of-packed-member") - #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-address-of-packed-member") + add_definitions(-D_GNU_SOURCE) endif () if (${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") - add_definitions(-U__FreeBSD__) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-address-of-packed-member -Wno-unknown-warning-option") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-address-of-packed-member -Wno-unknown-warning-option") + add_definitions(-U__FreeBSD__) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-address-of-packed-member") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-address-of-packed-member") endif () if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") - add_definitions(-U__APPLE__) - add_definitions(-D__APPLE_USE_RFC_2292) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-address-of-packed-member -Wno-deprecated-declarations") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-address-of-packed-member -Wno-deprecated-declarations") + add_definitions(-U__APPLE__) + add_definitions(-D__APPLE_USE_RFC_2292) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-address-of-packed-member -Wno-deprecated-declarations") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-address-of-packed-member -Wno-deprecated-declarations") endif () if (${CMAKE_SYSTEM_NAME} MATCHES "DragonFly") - add_definitions(-U__DragonFly__) + add_definitions(-U__DragonFly__) endif () if (${CMAKE_SYSTEM_NAME} MATCHES "NetBSD") - add_definitions(-U__NetBSD__) + add_definitions(-U__NetBSD__) endif () if (${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD") - add_definitions(-U__OpenBSD__) + add_definitions(-U__OpenBSD__) endif () @@ -89,92 +89,92 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}) -list(APPEND usrsctp_root_HEADERS - user_atomic.h - user_environment.h - user_inpcb.h - user_ip_icmp.h - user_ip6_var.h - user_malloc.h - user_mbuf.h - user_queue.h - user_recv_thread.h - user_route.h - user_socketvar.h - user_uma.h - usrsctp.h +list(APPEND usrsctp_root_headers + user_atomic.h + user_environment.h + user_inpcb.h + user_ip_icmp.h + user_ip6_var.h + user_malloc.h + user_mbuf.h + user_queue.h + user_recv_thread.h + user_route.h + user_socketvar.h + user_uma.h + usrsctp.h ) -list(APPEND usrsctp_netinet_HEADERS - netinet/sctp_asconf.h - netinet/sctp_auth.h - netinet/sctp_bsd_addr.h - netinet/sctp_callout.h - netinet/sctp_constants.h - netinet/sctp_crc32.h - netinet/sctp_header.h - netinet/sctp_indata.h - netinet/sctp_input.h - netinet/sctp_lock_userspace.h - netinet/sctp_os_userspace.h - netinet/sctp_os.h - netinet/sctp_output.h - netinet/sctp_pcb.h - netinet/sctp_peeloff.h - netinet/sctp_process_lock.h - netinet/sctp_sha1.h - netinet/sctp_structs.h - netinet/sctp_sysctl.h - netinet/sctp_timer.h - netinet/sctp_uio.h - netinet/sctp_var.h - netinet/sctputil.h - netinet/sctp.h +list(APPEND usrsctp_netinet_headers + netinet/sctp_asconf.h + netinet/sctp_auth.h + netinet/sctp_bsd_addr.h + netinet/sctp_callout.h + netinet/sctp_constants.h + netinet/sctp_crc32.h + netinet/sctp_header.h + netinet/sctp_indata.h + netinet/sctp_input.h + netinet/sctp_lock_userspace.h + netinet/sctp_os_userspace.h + netinet/sctp_os.h + netinet/sctp_output.h + netinet/sctp_pcb.h + netinet/sctp_peeloff.h + netinet/sctp_process_lock.h + netinet/sctp_sha1.h + netinet/sctp_structs.h + netinet/sctp_sysctl.h + netinet/sctp_timer.h + netinet/sctp_uio.h + netinet/sctp_var.h + netinet/sctputil.h + netinet/sctp.h ) -list(APPEND usrsctp_netinet6_HEADERS - netinet6/sctp6_var.h +list(APPEND usrsctp_netinet6_headers + netinet6/sctp6_var.h ) -list(APPEND usrsctp_HEADERS - ${usrsctp_root_HEADERS} - ${usrsctp_netinet_HEADERS} - ${usrsctp_netinet6_HEADERS} +list(APPEND usrsctp_headers + ${usrsctp_root_headers} + ${usrsctp_netinet_headers} + ${usrsctp_netinet6_headers} ) -list(APPEND usrsctp_SOURCES - netinet/sctp_asconf.c - netinet/sctp_auth.c - netinet/sctp_bsd_addr.c - netinet/sctp_callout.c - netinet/sctp_cc_functions.c - netinet/sctp_crc32.c - netinet/sctp_indata.c - netinet/sctp_input.c - netinet/sctp_output.c - netinet/sctp_pcb.c - netinet/sctp_peeloff.c - netinet/sctp_sha1.c - netinet/sctp_ss_functions.c - netinet/sctp_sysctl.c - netinet/sctp_timer.c - netinet/sctp_userspace.c - netinet/sctp_usrreq.c - netinet/sctputil.c - netinet6/sctp6_usrreq.c - user_environment.c - user_mbuf.c - user_recv_thread.c - user_socket.c +list(APPEND usrsctp_sources + netinet/sctp_asconf.c + netinet/sctp_auth.c + netinet/sctp_bsd_addr.c + netinet/sctp_callout.c + netinet/sctp_cc_functions.c + netinet/sctp_crc32.c + netinet/sctp_indata.c + netinet/sctp_input.c + netinet/sctp_output.c + netinet/sctp_pcb.c + netinet/sctp_peeloff.c + netinet/sctp_sha1.c + netinet/sctp_ss_functions.c + netinet/sctp_sysctl.c + netinet/sctp_timer.c + netinet/sctp_userspace.c + netinet/sctp_usrreq.c + netinet/sctputil.c + netinet6/sctp6_usrreq.c + user_environment.c + user_mbuf.c + user_recv_thread.c + user_socket.c ) -add_library(usrsctp SHARED ${usrsctp_SOURCES} ${usrsctp_HEADERS}) -add_library(usrsctp-static STATIC ${usrsctp_SOURCES} ${usrsctp_HEADERS}) +add_library(usrsctp SHARED ${usrsctp_sources} ${usrsctp_headers}) +add_library(usrsctp-static STATIC ${usrsctp_sources} ${usrsctp_headers}) if (WIN32) - message(STATUS "link library: ws2_32") - target_link_libraries(usrsctp ws2_32) - target_link_libraries(usrsctp-static ws2_32) + message(STATUS "link library: ws2_32") + target_link_libraries(usrsctp ws2_32) + target_link_libraries(usrsctp-static ws2_32) endif () set_target_properties(usrsctp-static PROPERTIES OUTPUT_NAME "usrsctp") @@ -182,7 +182,7 @@ set_target_properties(usrsctp PROPERTIES SOVERSION 1 VERSION 1.0.0) if (NOT DEFINED CMAKE_INSTALL_LIBDIR) - SET(CMAKE_INSTALL_LIBDIR lib) + SET(CMAKE_INSTALL_LIBDIR lib) endif ()
diff --git a/usrsctplib/netinet/sctp.h b/usrsctplib/netinet/sctp.h index 0e38054..f5b1d82 100755 --- a/usrsctplib/netinet/sctp.h +++ b/usrsctplib/netinet/sctp.h
@@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 2001-2008, by Cisco Systems, Inc. All rights reserved. * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved. * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved. @@ -32,7 +34,7 @@ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp.h 297662 2016-04-07 09:10:34Z rrs $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp.h 323657 2017-09-16 21:26:06Z tuexen $"); #endif #ifndef _NETINET_SCTP_H_ @@ -569,7 +571,6 @@ #define SCTP_PCB_FLAGS_INTERLEAVE_STRMS 0x0000000000000010 #define SCTP_PCB_FLAGS_DO_ASCONF 0x0000000000000020 #define SCTP_PCB_FLAGS_AUTO_ASCONF 0x0000000000000040 -#define SCTP_PCB_FLAGS_ZERO_COPY_ACTIVE 0x0000000000000080 /* socket options */ #define SCTP_PCB_FLAGS_NODELAY 0x0000000000000100 #define SCTP_PCB_FLAGS_AUTOCLOSE 0x0000000000000200
diff --git a/usrsctplib/netinet/sctp_asconf.c b/usrsctplib/netinet/sctp_asconf.c index 0234810..704dfde 100755 --- a/usrsctplib/netinet/sctp_asconf.c +++ b/usrsctplib/netinet/sctp_asconf.c
@@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved. * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved. * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved. @@ -32,7 +34,7 @@ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_asconf.c 321204 2017-07-19 14:28:58Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp_asconf.c 324056 2017-09-27 13:05:23Z tuexen $"); #endif #include <netinet/sctp_os.h> @@ -2341,39 +2343,6 @@ return (0); } -void -sctp_set_primary_ip_address(struct sctp_ifa *ifa) -{ - struct sctp_inpcb *inp; - - /* go through all our PCB's */ - LIST_FOREACH(inp, &SCTP_BASE_INFO(listhead), sctp_list) { - struct sctp_tcb *stcb; - - /* process for all associations for this endpoint */ - LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) { - /* queue an ASCONF:SET_PRIM_ADDR to be sent */ - if (!sctp_asconf_queue_add(stcb, ifa, - SCTP_SET_PRIM_ADDR)) { - /* set primary queuing succeeded */ - SCTPDBG(SCTP_DEBUG_ASCONF1, "set_primary_ip_address: queued on stcb=%p, ", - (void *)stcb); - SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, &ifa->address.sa); - if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) || - (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) { -#ifdef SCTP_TIMER_BASED_ASCONF - sctp_timer_start(SCTP_TIMER_TYPE_ASCONF, - stcb->sctp_ep, stcb, - stcb->asoc.primary_destination); -#else - sctp_send_asconf(stcb, NULL, SCTP_ADDR_NOT_LOCKED); -#endif - } - } - } /* for each stcb */ - } /* for each inp */ -} - int sctp_is_addr_pending(struct sctp_tcb *stcb, struct sctp_ifa *sctp_ifa) {
diff --git a/usrsctplib/netinet/sctp_asconf.h b/usrsctplib/netinet/sctp_asconf.h index 69accd2..28130f3 100755 --- a/usrsctplib/netinet/sctp_asconf.h +++ b/usrsctplib/netinet/sctp_asconf.h
@@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved. * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved. * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved. @@ -32,7 +34,7 @@ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_asconf.h 309607 2016-12-06 10:21:25Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp_asconf.h 324056 2017-09-27 13:05:23Z tuexen $"); #endif #ifndef _NETINET_SCTP_ASCONF_H_ @@ -73,9 +75,6 @@ struct sockaddr *); extern void -sctp_set_primary_ip_address(struct sctp_ifa *ifa); - -extern void sctp_check_address_list(struct sctp_tcb *, struct mbuf *, int, int, struct sockaddr *, uint16_t, uint16_t, uint16_t, uint16_t);
diff --git a/usrsctplib/netinet/sctp_auth.c b/usrsctplib/netinet/sctp_auth.c index d03ace5..e1163eb 100755 --- a/usrsctplib/netinet/sctp_auth.c +++ b/usrsctplib/netinet/sctp_auth.c
@@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 2001-2008, by Cisco Systems, Inc. All rights reserved. * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved. * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved. @@ -32,7 +34,7 @@ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_auth.c 321204 2017-07-19 14:28:58Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp_auth.c 324971 2017-10-25 09:12:22Z tuexen $"); #endif #include <netinet/sctp_os.h> @@ -1633,9 +1635,9 @@ /* now use the rest of the mbuf chain */ while ((m_tmp != NULL) && (size > 0)) { data = mtod(m_tmp, uint8_t *) + m_offset; - if (size > (uint32_t) SCTP_BUF_LEN(m_tmp)) { - memset(data, 0, SCTP_BUF_LEN(m_tmp)); - size -= SCTP_BUF_LEN(m_tmp); + if (size > (uint32_t)(SCTP_BUF_LEN(m_tmp) - m_offset)) { + memset(data, 0, SCTP_BUF_LEN(m_tmp) - m_offset); + size -= SCTP_BUF_LEN(m_tmp) - m_offset; } else { memset(data, 0, size); size = 0;
diff --git a/usrsctplib/netinet/sctp_auth.h b/usrsctplib/netinet/sctp_auth.h index b24f514..c1f82d8 100755 --- a/usrsctplib/netinet/sctp_auth.h +++ b/usrsctplib/netinet/sctp_auth.h
@@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 2001-2008, by Cisco Systems, Inc. All rights reserved. * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved. * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
diff --git a/usrsctplib/netinet/sctp_bsd_addr.c b/usrsctplib/netinet/sctp_bsd_addr.c index 805fdb8..e886e6c 100755 --- a/usrsctplib/netinet/sctp_bsd_addr.c +++ b/usrsctplib/netinet/sctp_bsd_addr.c
@@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved. * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved. * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved. @@ -824,10 +826,6 @@ if ((int)space_needed > (((mbuf_threshold - 1) * MLEN) + MHLEN)) { MCLGET(m, how); - if (m == NULL) { - return (NULL); - } - if (SCTP_BUF_IS_EXTENDED(m) == 0) { sctp_m_freem(m); return (NULL);
diff --git a/usrsctplib/netinet/sctp_bsd_addr.h b/usrsctplib/netinet/sctp_bsd_addr.h index e0483a4..a83c0ec 100755 --- a/usrsctplib/netinet/sctp_bsd_addr.h +++ b/usrsctplib/netinet/sctp_bsd_addr.h
@@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved. * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved. * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
diff --git a/usrsctplib/netinet/sctp_callout.c b/usrsctplib/netinet/sctp_callout.c index c55f1b4..30bfa0d 100755 --- a/usrsctplib/netinet/sctp_callout.c +++ b/usrsctplib/netinet/sctp_callout.c
@@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved. * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved. * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
diff --git a/usrsctplib/netinet/sctp_callout.h b/usrsctplib/netinet/sctp_callout.h index 4d764c9..765f966 100755 --- a/usrsctplib/netinet/sctp_callout.h +++ b/usrsctplib/netinet/sctp_callout.h
@@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved. * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved. * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
diff --git a/usrsctplib/netinet/sctp_cc_functions.c b/usrsctplib/netinet/sctp_cc_functions.c index ace7464..e53e4d7 100755 --- a/usrsctplib/netinet/sctp_cc_functions.c +++ b/usrsctplib/netinet/sctp_cc_functions.c
@@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved. * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved. * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
diff --git a/usrsctplib/netinet/sctp_constants.h b/usrsctplib/netinet/sctp_constants.h index 9afc9bd..525c958 100755 --- a/usrsctplib/netinet/sctp_constants.h +++ b/usrsctplib/netinet/sctp_constants.h
@@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 2001-2008, by Cisco Systems, Inc. All rights reserved. * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved. * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved. @@ -32,7 +34,7 @@ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_constants.h 320263 2017-06-23 09:27:31Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp_constants.h 324615 2017-10-14 10:02:59Z tuexen $"); #endif #ifndef _NETINET_SCTP_CONSTANTS_H_ @@ -102,10 +104,6 @@ */ #define SCTP_DEFAULT_VRF_SIZE 4 -/* constants for rto calc */ -#define sctp_align_safe_nocopy 0 -#define sctp_align_unsafe_makecopy 1 - /* JRS - Values defined for the HTCP algorithm */ #define ALPHA_BASE (1<<7) /* 1.0 with shift << 7 */ #define BETA_MIN (1<<6) /* 0.5 with shift << 7 */ @@ -563,11 +561,9 @@ #define SCTP_TIMER_TYPE_INPKILL 15 #define SCTP_TIMER_TYPE_ASOCKILL 16 #define SCTP_TIMER_TYPE_ADDR_WQ 17 -#define SCTP_TIMER_TYPE_ZERO_COPY 18 -#define SCTP_TIMER_TYPE_ZCOPY_SENDQ 19 -#define SCTP_TIMER_TYPE_PRIM_DELETED 20 +#define SCTP_TIMER_TYPE_PRIM_DELETED 18 /* add new timers here - and increment LAST */ -#define SCTP_TIMER_TYPE_LAST 21 +#define SCTP_TIMER_TYPE_LAST 19 #define SCTP_IS_TIMER_TYPE_VALID(t) (((t) > SCTP_TIMER_TYPE_NONE) && \ ((t) < SCTP_TIMER_TYPE_LAST)) @@ -996,9 +992,6 @@ #define SCTP_SO_NOT_LOCKED 0 -#define SCTP_HOLDS_LOCK 1 -#define SCTP_NOT_LOCKED 0 - /*- * For address locks, do we hold the lock? */
diff --git a/usrsctplib/netinet/sctp_crc32.c b/usrsctplib/netinet/sctp_crc32.c index 27536f1..16ce971 100755 --- a/usrsctplib/netinet/sctp_crc32.c +++ b/usrsctplib/netinet/sctp_crc32.c
@@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved. * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved. * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
diff --git a/usrsctplib/netinet/sctp_crc32.h b/usrsctplib/netinet/sctp_crc32.h index 0b1cbbb..ee1161a 100755 --- a/usrsctplib/netinet/sctp_crc32.h +++ b/usrsctplib/netinet/sctp_crc32.h
@@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved. * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved. * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
diff --git a/usrsctplib/netinet/sctp_header.h b/usrsctplib/netinet/sctp_header.h index 20031e9..6035d9c 100755 --- a/usrsctplib/netinet/sctp_header.h +++ b/usrsctplib/netinet/sctp_header.h
@@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved. * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved. * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
diff --git a/usrsctplib/netinet/sctp_indata.c b/usrsctplib/netinet/sctp_indata.c index 211c05a..9a1dfcb 100755 --- a/usrsctplib/netinet/sctp_indata.c +++ b/usrsctplib/netinet/sctp_indata.c
@@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved. * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved. * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved. @@ -32,7 +34,7 @@ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_indata.c 321463 2017-07-25 11:05:53Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp_indata.c 325434 2017-11-05 11:59:33Z tuexen $"); #endif #include <netinet/sctp_os.h> @@ -95,12 +97,14 @@ return (calc); } + KASSERT(asoc->cnt_on_reasm_queue > 0 || asoc->size_on_reasm_queue == 0, + ("size_on_reasm_queue is %u", asoc->size_on_reasm_queue)); + KASSERT(asoc->cnt_on_all_streams > 0 || asoc->size_on_all_streams == 0, + ("size_on_all_streams is %u", asoc->size_on_all_streams)); if (stcb->asoc.sb_cc == 0 && - asoc->size_on_reasm_queue == 0 && - asoc->size_on_all_streams == 0) { + asoc->cnt_on_reasm_queue == 0 && + asoc->cnt_on_all_streams == 0) { /* Full rwnd granted */ - KASSERT(asoc->cnt_on_reasm_queue == 0, ("cnt_on_reasm_queue is %u", asoc->cnt_on_reasm_queue)); - KASSERT(asoc->cnt_on_all_streams == 0, ("cnt_on_all_streams is %u", asoc->cnt_on_all_streams)); calc = max(SCTP_SB_LIMIT_RCV(stcb->sctp_socket), SCTP_MINIMAL_RWND); return (calc); } @@ -1245,6 +1249,19 @@ } done = (control->end_added) && (control->last_frag_seen); if (control->on_read_q == 0) { + if (!done) { + if (asoc->size_on_all_streams >= control->length) { + asoc->size_on_all_streams -= control->length; + } else { +#ifdef INVARIANTS + panic("size_on_all_streams = %u smaller than control length %u", asoc->size_on_all_streams, control->length); +#else + asoc->size_on_all_streams = 0; +#endif + } + strm->pd_api_started = 1; + control->pdapi_started = 1; + } sctp_add_to_readq(stcb->sctp_ep, stcb, control, &stcb->sctp_socket->so_rcv, control->end_added, @@ -1254,10 +1271,6 @@ if (done) { control = nctl; goto deliver_more; - } else { - /* We are now doing PD API */ - strm->pd_api_started = 1; - control->pdapi_started = 1; } } } @@ -1318,15 +1331,10 @@ } else if (control->on_strm_q == SCTP_ON_ORDERED) { /* Ordered */ TAILQ_REMOVE(&strm->inqueue, control, next_instrm); - if (asoc->size_on_all_streams >= control->length) { - asoc->size_on_all_streams -= control->length; - } else { -#ifdef INVARIANTS - panic("size_on_all_streams = %u smaller than control length %u", asoc->size_on_all_streams, control->length); -#else - asoc->size_on_all_streams = 0; -#endif - } + /* + * Don't need to decrement size_on_all_streams, + * since control is on the read queue. + */ sctp_ucount_decr(asoc->cnt_on_all_streams); control->on_strm_q = 0; #ifdef INVARIANTS @@ -1381,10 +1389,10 @@ } if (sctp_place_control_in_stream(strm, asoc, control)) { /* Duplicate SSN? */ - sctp_clean_up_control(stcb, control); sctp_abort_in_reasm(stcb, control, chk, abort_flag, SCTP_FROM_SCTP_INDATA + SCTP_LOC_6); + sctp_clean_up_control(stcb, control); return; } if ((tsn == (asoc->cumulative_tsn + 1) && (asoc->idata_supported == 0))) { @@ -1583,9 +1591,16 @@ next_fsn, control->fsn_included); TAILQ_REMOVE(&control->reasm, at, sctp_next); lenadded = sctp_add_chk_to_control(control, strm, stcb, asoc, at, SCTP_READ_LOCK_NOT_HELD); - asoc->size_on_all_streams += lenadded; if (control->on_read_q) { do_wakeup = 1; + } else { + /* + * We only add to the size-on-all-streams + * if its not on the read q. The read q + * flag will cause a sballoc so its accounted + * for there. + */ + asoc->size_on_all_streams += lenadded; } next_fsn++; if (control->end_added && control->pdapi_started) { @@ -1598,7 +1613,6 @@ control, &stcb->sctp_socket->so_rcv, control->end_added, SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED); - do_wakeup = 1; } break; } @@ -2623,10 +2637,11 @@ struct sctp_association *asoc; int num_chunks = 0; /* number of control chunks processed */ int stop_proc = 0; - int chk_length, break_flag, last_chunk; + int break_flag, last_chunk; int abort_flag = 0, was_a_gap; struct mbuf *m; uint32_t highest_tsn; + uint16_t chk_length; /* set the rwnd */ sctp_set_rwnd(stcb, &stcb->asoc); @@ -2679,7 +2694,8 @@ #endif /* get pointer to the first chunk header */ ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, *offset, - sizeof(struct sctp_chunkhdr), (uint8_t *) & chunk_buf); + sizeof(struct sctp_chunkhdr), + (uint8_t *)&chunk_buf); if (ch == NULL) { return (1); } @@ -2721,7 +2737,7 @@ } if ((ch->chunk_type == SCTP_DATA) || (ch->chunk_type == SCTP_IDATA)) { - int clen; + uint16_t clen; if (ch->chunk_type == SCTP_DATA) { clen = sizeof(struct sctp_data_chunk); @@ -2736,7 +2752,8 @@ struct mbuf *op_err; char msg[SCTP_DIAG_INFO_LEN]; - snprintf(msg, sizeof(msg), "DATA chunk of length %d", + snprintf(msg, sizeof(msg), "%s chunk of length %u", + ch->chunk_type == SCTP_DATA ? "DATA" : "I-DATA", chk_length); op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_20; @@ -2811,7 +2828,25 @@ return (2); } default: - /* unknown chunk type, use bit rules */ + /* + * Unknown chunk type: use bit rules after + * checking length + */ + if (chk_length < sizeof(struct sctp_chunkhdr)) { + /* + * Need to send an abort since we had a + * invalid chunk. + */ + struct mbuf *op_err; + char msg[SCTP_DIAG_INFO_LEN]; + + snprintf(msg, sizeof(msg), "Chunk of length %u", + chk_length); + op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); + stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_20; + sctp_abort_an_association(inp, stcb, op_err, SCTP_SO_NOT_LOCKED); + return (2); + } if (ch->chunk_type & 0x40) { /* Add a error report to the queue */ struct mbuf *op_err; @@ -2847,7 +2882,8 @@ continue; } ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, *offset, - sizeof(struct sctp_chunkhdr), (uint8_t *) & chunk_buf); + sizeof(struct sctp_chunkhdr), + (uint8_t *)&chunk_buf); if (ch == NULL) { *offset = length; stop_proc = 1; @@ -3039,7 +3075,6 @@ &stcb->asoc, tp1->whoTo, &tp1->sent_rcv_time, - sctp_align_safe_nocopy, SCTP_RTT_FROM_DATA); *rto_ok = 0; } @@ -3998,7 +4033,6 @@ sctp_calculate_rto(stcb, asoc, tp1->whoTo, &tp1->sent_rcv_time, - sctp_align_safe_nocopy, SCTP_RTT_FROM_DATA); rto_ok = 0; } @@ -4204,7 +4238,6 @@ again: j = 0; TAILQ_FOREACH(net, &asoc->nets, sctp_next) { - int to_ticks; if (win_probe_recovery && (net->window_probe)) { win_probe_recovered = 1; /* @@ -4220,15 +4253,9 @@ } } } - if (net->RTO == 0) { - to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto); - } else { - to_ticks = MSEC_TO_TICKS(net->RTO); - } if (net->flight_size) { j++; - (void)SCTP_OS_TIMER_START(&net->rxt_timer.timer, to_ticks, - sctp_timeout_handler, &net->rxt_timer); + sctp_timer_start(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, net); if (net->window_probe) { net->window_probe = 0; } @@ -4237,8 +4264,7 @@ /* In window probes we must assure a timer is still running there */ net->window_probe = 0; if (!SCTP_OS_TIMER_PENDING(&net->rxt_timer.timer)) { - SCTP_OS_TIMER_START(&net->rxt_timer.timer, to_ticks, - sctp_timeout_handler, &net->rxt_timer); + sctp_timer_start(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, net); } } else if (SCTP_OS_TIMER_PENDING(&net->rxt_timer.timer)) { sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, @@ -4633,7 +4659,6 @@ sctp_calculate_rto(stcb, asoc, tp1->whoTo, &tp1->sent_rcv_time, - sctp_align_safe_nocopy, SCTP_RTT_FROM_DATA); rto_ok = 0; }
diff --git a/usrsctplib/netinet/sctp_indata.h b/usrsctplib/netinet/sctp_indata.h index 625dd62..bdba114 100755 --- a/usrsctplib/netinet/sctp_indata.h +++ b/usrsctplib/netinet/sctp_indata.h
@@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved. * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved. * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
diff --git a/usrsctplib/netinet/sctp_input.c b/usrsctplib/netinet/sctp_input.c index 0649ec2..d2ceb75 100755 --- a/usrsctplib/netinet/sctp_input.c +++ b/usrsctplib/netinet/sctp_input.c
@@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 2001-2008, by Cisco Systems, Inc. All rights reserved. * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved. * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved. @@ -32,7 +34,7 @@ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_input.c 320653 2017-07-04 18:24:50Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp_input.c 325864 2017-11-15 22:13:10Z tuexen $"); #endif #include <netinet/sctp_os.h> @@ -224,8 +226,7 @@ #if defined(__FreeBSD__) mflowtype, mflowid, #endif - vrf_id, port, - ((stcb == NULL) ? SCTP_HOLDS_LOCK : SCTP_NOT_LOCKED)); + vrf_id, port); } outnow: if (stcb == NULL) { @@ -549,8 +550,8 @@ asoc->primary_destination, SCTP_FROM_SCTP_INPUT + SCTP_LOC_3); /* calculate the RTO */ - net->RTO = sctp_calculate_rto(stcb, asoc, net, &asoc->time_entered, sctp_align_safe_nocopy, - SCTP_RTT_FROM_NON_DATA); + net->RTO = sctp_calculate_rto(stcb, asoc, net, &asoc->time_entered, + SCTP_RTT_FROM_NON_DATA); #if defined(__Userspace__) if (stcb->sctp_ep->recv_callback) { if (stcb->sctp_socket) { @@ -711,14 +712,22 @@ r_net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_4); sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, r_net); } + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { + sctp_misc_ints(SCTP_THRESHOLD_CLEAR, + stcb->asoc.overall_error_count, + 0, + SCTP_FROM_SCTP_INPUT, + __LINE__); + } + stcb->asoc.overall_error_count = 0; old_error_counter = r_net->error_count; r_net->error_count = 0; r_net->hb_responded = 1; tv.tv_sec = cp->heartbeat.hb_info.time_value_1; tv.tv_usec = cp->heartbeat.hb_info.time_value_2; /* Now lets do a RTO with this */ - r_net->RTO = sctp_calculate_rto(stcb, &stcb->asoc, r_net, &tv, sctp_align_safe_nocopy, - SCTP_RTT_FROM_NON_DATA); + r_net->RTO = sctp_calculate_rto(stcb, &stcb->asoc, r_net, &tv, + SCTP_RTT_FROM_NON_DATA); if (!(r_net->dest_state & SCTP_ADDR_REACHABLE)) { r_net->dest_state |= SCTP_ADDR_REACHABLE; sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, @@ -776,6 +785,14 @@ */ struct sctpasochead *head; + if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_WAIT) || + (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_ECHOED)) { + atomic_add_int(&stcb->asoc.refcnt, 1); + SCTP_TCB_UNLOCK(stcb); + SCTP_INP_INFO_WLOCK(); + SCTP_TCB_LOCK(stcb); + atomic_subtract_int(&stcb->asoc.refcnt, 1); + } if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_WAIT) { /* generate a new vtag and send init */ LIST_REMOVE(stcb, sctp_asocs); @@ -784,6 +801,7 @@ /* put it in the bucket in the vtag hash of assoc's for the system */ LIST_INSERT_HEAD(head, stcb, sctp_asocs); sctp_send_initiate(stcb->sctp_ep, stcb, SCTP_SO_NOT_LOCKED); + SCTP_INP_INFO_WUNLOCK(); return (1); } if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_ECHOED) { @@ -803,6 +821,7 @@ /* put it in the bucket in the vtag hash of assoc's for the system */ LIST_INSERT_HEAD(head, stcb, sctp_asocs); sctp_send_initiate(stcb->sctp_ep, stcb, SCTP_SO_NOT_LOCKED); + SCTP_INP_INFO_WUNLOCK(); return (1); } return (0); @@ -824,7 +843,8 @@ } -static void +/* Returns 1 if the stcb was aborted, 0 otherwise */ +static int sctp_handle_abort(struct sctp_abort_chunk *abort, struct sctp_tcb *stcb, struct sctp_nets *net) { @@ -836,29 +856,29 @@ SCTPDBG(SCTP_DEBUG_INPUT2, "sctp_handle_abort: handling ABORT\n"); if (stcb == NULL) - return; + return (0); len = ntohs(abort->ch.chunk_length); - if (len > sizeof (struct sctp_chunkhdr)) { + if (len >= sizeof(struct sctp_chunkhdr) + sizeof(struct sctp_error_cause)) { /* Need to check the cause codes for our * two magic nat aborts which don't kill the assoc * necessarily. */ - struct sctp_gen_error_cause *cause; + struct sctp_error_cause *cause; - cause = (struct sctp_gen_error_cause *)(abort + 1); + cause = (struct sctp_error_cause *)(abort + 1); error = ntohs(cause->code); if (error == SCTP_CAUSE_NAT_COLLIDING_STATE) { SCTPDBG(SCTP_DEBUG_INPUT2, "Received Colliding state abort flags:%x\n", abort->ch.chunk_flags); if (sctp_handle_nat_colliding_state(stcb)) { - return; + return (0); } } else if (error == SCTP_CAUSE_NAT_MISSING_STATE) { SCTPDBG(SCTP_DEBUG_INPUT2, "Received missing state abort flags:%x\n", abort->ch.chunk_flags); if (sctp_handle_nat_missing_state(stcb, net)) { - return; + return (0); } } } else { @@ -893,6 +913,7 @@ SCTP_SOCKET_UNLOCK(so, 1); #endif SCTPDBG(SCTP_DEBUG_INPUT2, "sctp_handle_abort: finished\n"); + return (1); } static void @@ -1148,19 +1169,11 @@ #endif } -/* - * Skip past the param header and then we will find the chunk that caused the - * problem. There are two possibilities ASCONF or FWD-TSN other than that and - * our peer must be broken. - */ static void -sctp_process_unrecog_chunk(struct sctp_tcb *stcb, struct sctp_paramhdr *phdr, +sctp_process_unrecog_chunk(struct sctp_tcb *stcb, uint8_t chunk_type, struct sctp_nets *net) { - struct sctp_chunkhdr *chk; - - chk = (struct sctp_chunkhdr *)((caddr_t)phdr + sizeof(*phdr)); - switch (chk->chunk_type) { + switch (chunk_type) { case SCTP_ASCONF_ACK: case SCTP_ASCONF: sctp_asconf_cleanup(stcb, net); @@ -1171,8 +1184,8 @@ break; default: SCTPDBG(SCTP_DEBUG_INPUT2, - "Peer does not support chunk type %d(%x)??\n", - chk->chunk_type, (uint32_t) chk->chunk_type); + "Peer does not support chunk type %d (0x%x).\n", + chunk_type, chunk_type); break; } } @@ -1184,12 +1197,9 @@ * XXX: Is this the right thing to do? */ static void -sctp_process_unrecog_param(struct sctp_tcb *stcb, struct sctp_paramhdr *phdr) +sctp_process_unrecog_param(struct sctp_tcb *stcb, uint16_t parameter_type) { - struct sctp_paramhdr *pbad; - - pbad = phdr + 1; - switch (ntohs(pbad->param_type)) { + switch (parameter_type) { /* pr-sctp draft */ case SCTP_PRSCTP_SUPPORTED: stcb->asoc.prsctp_supported = 0; @@ -1214,66 +1224,72 @@ break; default: SCTPDBG(SCTP_DEBUG_INPUT2, - "Peer does not support param type %d(%x)??\n", - pbad->param_type, (uint32_t) pbad->param_type); + "Peer does not support param type %d (0x%x)??\n", + parameter_type, parameter_type); break; } } static int sctp_handle_error(struct sctp_chunkhdr *ch, - struct sctp_tcb *stcb, struct sctp_nets *net) + struct sctp_tcb *stcb, struct sctp_nets *net, uint32_t limit) { - int chklen; - struct sctp_paramhdr *phdr; - uint16_t error, error_type; - uint16_t error_len; + struct sctp_error_cause *cause; struct sctp_association *asoc; - int adjust; + uint32_t remaining_length, adjust; + uint16_t code, cause_code, cause_length; #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) struct socket *so; #endif /* parse through all of the errors and process */ asoc = &stcb->asoc; - phdr = (struct sctp_paramhdr *)((caddr_t)ch + + cause = (struct sctp_error_cause *)((caddr_t)ch + sizeof(struct sctp_chunkhdr)); - chklen = ntohs(ch->chunk_length) - sizeof(struct sctp_chunkhdr); - error = 0; - while ((size_t)chklen >= sizeof(struct sctp_paramhdr)) { + remaining_length = ntohs(ch->chunk_length); + if (remaining_length > limit) { + remaining_length = limit; + } + if (remaining_length >= sizeof(struct sctp_chunkhdr)) { + remaining_length -= sizeof(struct sctp_chunkhdr); + } else { + remaining_length = 0; + } + code = 0; + while (remaining_length >= sizeof(struct sctp_error_cause)) { /* Process an Error Cause */ - error_type = ntohs(phdr->param_type); - error_len = ntohs(phdr->param_length); - if ((error_len > chklen) || (error_len == 0)) { - /* invalid param length for this param */ - SCTPDBG(SCTP_DEBUG_INPUT1, "Bogus length in error param- chunk left:%d errorlen:%d\n", - chklen, error_len); + cause_code = ntohs(cause->code); + cause_length = ntohs(cause->length); + if ((cause_length > remaining_length) || (cause_length == 0)) { + /* Invalid cause length, possibly due to truncation. */ + SCTPDBG(SCTP_DEBUG_INPUT1, "Bogus length in cause - bytes left: %u cause length: %u\n", + remaining_length, cause_length); return (0); } - if (error == 0) { + if (code == 0) { /* report the first error cause */ - error = error_type; + code = cause_code; } - switch (error_type) { + switch (cause_code) { case SCTP_CAUSE_INVALID_STREAM: case SCTP_CAUSE_MISSING_PARAM: case SCTP_CAUSE_INVALID_PARAM: case SCTP_CAUSE_NO_USER_DATA: - SCTPDBG(SCTP_DEBUG_INPUT1, "Software error we got a %d back? We have a bug :/ (or do they?)\n", - error_type); + SCTPDBG(SCTP_DEBUG_INPUT1, "Software error we got a %u back? We have a bug :/ (or do they?)\n", + cause_code); break; case SCTP_CAUSE_NAT_COLLIDING_STATE: - SCTPDBG(SCTP_DEBUG_INPUT2, "Received Colliding state abort flags:%x\n", + SCTPDBG(SCTP_DEBUG_INPUT2, "Received Colliding state abort flags: %x\n", ch->chunk_flags); if (sctp_handle_nat_colliding_state(stcb)) { - return (0); + return (0); } break; case SCTP_CAUSE_NAT_MISSING_STATE: - SCTPDBG(SCTP_DEBUG_INPUT2, "Received missing state abort flags:%x\n", + SCTPDBG(SCTP_DEBUG_INPUT2, "Received missing state abort flags: %x\n", ch->chunk_flags); if (sctp_handle_nat_missing_state(stcb, net)) { - return (0); + return (0); } break; case SCTP_CAUSE_STALE_COOKIE: @@ -1281,12 +1297,18 @@ * We only act if we have echoed a cookie and are * waiting. */ - if (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED) { - int *p; + if ((cause_length >= sizeof(struct sctp_error_stale_cookie)) && + (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED)) { + struct sctp_error_stale_cookie *stale_cookie; - p = (int *)((caddr_t)phdr + sizeof(*phdr)); - /* Save the time doubled */ - asoc->cookie_preserve_req = ntohl(*p) << 1; + stale_cookie = (struct sctp_error_stale_cookie *)cause; + asoc->cookie_preserve_req = ntohl(stale_cookie->stale_time); + /* Double it to be more robust on RTX */ + if (asoc->cookie_preserve_req <= UINT32_MAX / 2) { + asoc->cookie_preserve_req *= 2; + } else { + asoc->cookie_preserve_req = UINT32_MAX; + } asoc->stale_cookie_count++; if (asoc->stale_cookie_count > asoc->max_init_times) { @@ -1329,10 +1351,21 @@ */ break; case SCTP_CAUSE_UNRECOG_CHUNK: - sctp_process_unrecog_chunk(stcb, phdr, net); + if (cause_length >= sizeof(struct sctp_error_unrecognized_chunk)) { + struct sctp_error_unrecognized_chunk *unrec_chunk; + + unrec_chunk = (struct sctp_error_unrecognized_chunk *)cause; + sctp_process_unrecog_chunk(stcb, unrec_chunk->ch.chunk_type, net); + } break; case SCTP_CAUSE_UNRECOG_PARAM: - sctp_process_unrecog_param(stcb, phdr); + /* XXX: We only consider the first parameter */ + if (cause_length >= sizeof(struct sctp_error_cause) + sizeof(struct sctp_paramhdr)) { + struct sctp_paramhdr *unrec_parameter; + + unrec_parameter = (struct sctp_paramhdr *)(cause + 1); + sctp_process_unrecog_param(stcb, ntohs(unrec_parameter->param_type)); + } break; case SCTP_CAUSE_COOKIE_IN_SHUTDOWN: /* @@ -1349,8 +1382,8 @@ * We should NOT get these here, but in a * ASCONF-ACK. */ - SCTPDBG(SCTP_DEBUG_INPUT2, "Peer sends ASCONF errors in a Operational Error?<%d>?\n", - error_type); + SCTPDBG(SCTP_DEBUG_INPUT2, "Peer sends ASCONF errors in a error cause with code %u.\n", + cause_code); break; case SCTP_CAUSE_OUT_OF_RESC: /* @@ -1362,15 +1395,19 @@ */ break; default: - SCTPDBG(SCTP_DEBUG_INPUT1, "sctp_handle_error: unknown error type = 0x%xh\n", - error_type); + SCTPDBG(SCTP_DEBUG_INPUT1, "sctp_handle_error: unknown code 0x%x\n", + cause_code); break; } - adjust = SCTP_SIZE32(error_len); - chklen -= adjust; - phdr = (struct sctp_paramhdr *)((caddr_t)phdr + adjust); + adjust = SCTP_SIZE32(cause_length); + if (remaining_length >= adjust) { + remaining_length -= adjust; + } else { + remaining_length = 0; + } + cause = (struct sctp_error_cause *)((caddr_t)cause + adjust); } - sctp_ulp_notify(SCTP_NOTIFY_REMOTE_ERROR, stcb, error, ch, SCTP_SO_NOT_LOCKED); + sctp_ulp_notify(SCTP_NOTIFY_REMOTE_ERROR, stcb, code, ch, SCTP_SO_NOT_LOCKED); return (0); } @@ -1565,6 +1602,7 @@ struct sctp_init_ack_chunk *initack_cp, initack_buf; struct sctp_nets *net; struct mbuf *op_err; + struct timeval old; int init_offset, initack_offset, i; int retval; int spec_flag = 0; @@ -1727,11 +1765,12 @@ * since we did not send a HB make sure we * don't double things */ + old.tv_sec = cookie->time_entered.tv_sec; + old.tv_usec = cookie->time_entered.tv_usec; net->hb_responded = 1; net->RTO = sctp_calculate_rto(stcb, asoc, net, - &cookie->time_entered, - sctp_align_unsafe_makecopy, - SCTP_RTT_FROM_NON_DATA); + &old, + SCTP_RTT_FROM_NON_DATA); if (stcb->asoc.sctp_autoclose_ticks && (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTOCLOSE))) { @@ -2480,10 +2519,13 @@ } (void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered); if ((netp != NULL) && (*netp != NULL)) { + struct timeval old; + /* calculate the RTT and set the encaps port */ + old.tv_sec = cookie->time_entered.tv_sec; + old.tv_usec = cookie->time_entered.tv_usec; (*netp)->RTO = sctp_calculate_rto(stcb, asoc, *netp, - &cookie->time_entered, sctp_align_unsafe_makecopy, - SCTP_RTT_FROM_NON_DATA); + &old, SCTP_RTT_FROM_NON_DATA); } /* respond with a COOKIE-ACK */ sctp_send_cookie_ack(stcb); @@ -2681,9 +2723,6 @@ /* Expire time is in Ticks, so we convert to seconds */ time_expires.tv_sec = cookie->time_entered.tv_sec + TICKS_TO_SEC(cookie->cookie_life); time_expires.tv_usec = cookie->time_entered.tv_usec; - /* TODO sctp_constants.h needs alternative time macros when - * _KERNEL is undefined. - */ #ifndef __FreeBSD__ if (timercmp(&now, &time_expires, >)) #else @@ -2693,9 +2732,11 @@ /* cookie is stale! */ struct mbuf *op_err; struct sctp_error_stale_cookie *cause; - uint32_t tim; + struct timeval diff; + uint32_t staleness; + op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_error_stale_cookie), - 0, M_NOWAIT, 1, MT_DATA); + 0, M_NOWAIT, 1, MT_DATA); if (op_err == NULL) { /* FOOBAR */ return (NULL); @@ -2706,12 +2747,23 @@ cause->cause.code = htons(SCTP_CAUSE_STALE_COOKIE); cause->cause.length = htons((sizeof(struct sctp_paramhdr) + (sizeof(uint32_t)))); - /* seconds to usec */ - tim = (now.tv_sec - time_expires.tv_sec) * 1000000; - /* add in usec */ - if (tim == 0) - tim = now.tv_usec - cookie->time_entered.tv_usec; - cause->stale_time = htonl(tim); +#ifndef __FreeBSD__ + timersub(&now, &time_expires, &diff); +#else + diff = now; + timevalsub(&diff, &time_expires); +#endif + if (diff.tv_sec > UINT32_MAX / 1000000) { + staleness = UINT32_MAX; + } else { + staleness = diff.tv_sec * 1000000; + } + if (UINT32_MAX - staleness >= (uint32_t)diff.tv_usec) { + staleness += diff.tv_usec; + } else { + staleness = UINT32_MAX; + } + cause->stale_time = htonl(staleness); sctp_send_operr_to(src, dst, sh, cookie->peers_vtag, op_err, #if defined(__FreeBSD__) mflowtype, mflowid, l_inp->fibnum, @@ -3092,7 +3144,14 @@ } asoc = &stcb->asoc; - + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { + sctp_misc_ints(SCTP_THRESHOLD_CLEAR, + asoc->overall_error_count, + 0, + SCTP_FROM_SCTP_INPUT, + __LINE__); + } + asoc->overall_error_count = 0; sctp_stop_all_cookie_timers(stcb); /* process according to association state */ if (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED) { @@ -3110,8 +3169,8 @@ SCTP_STAT_INCR_GAUGE32(sctps_currestab); if (asoc->overall_error_count == 0) { net->RTO = sctp_calculate_rto(stcb, asoc, net, - &asoc->time_entered, sctp_align_safe_nocopy, - SCTP_RTT_FROM_NON_DATA); + &asoc->time_entered, + SCTP_RTT_FROM_NON_DATA); } (void)SCTP_GETTIME_TIMEVAL(&asoc->time_entered); sctp_ulp_notify(SCTP_NOTIFY_ASSOC_UP, stcb, 0, NULL, SCTP_SO_NOT_LOCKED); @@ -3316,14 +3375,14 @@ * make sure that we have a covered ECNE in the control chunk part. * If so remove it. */ - struct sctp_tmit_chunk *chk; + struct sctp_tmit_chunk *chk, *nchk; struct sctp_ecne_chunk *ecne; int override; uint32_t cwr_tsn; cwr_tsn = ntohl(cp->tsn); override = cp->ch.chunk_flags & SCTP_CWR_REDUCE_OVERRIDE; - TAILQ_FOREACH(chk, &stcb->asoc.control_send_queue, sctp_next) { + TAILQ_FOREACH_SAFE(chk, &stcb->asoc.control_send_queue, sctp_next, nchk) { if (chk->rec.chunk_id.id != SCTP_ECN_ECHO) { continue; } @@ -4673,7 +4732,7 @@ char msg[SCTP_DIAG_INFO_LEN]; uint32_t vtag_in; int num_chunks = 0; /* number of control chunks processed */ - uint32_t chk_length; + uint32_t chk_length, contiguous; int ret; int abort_no_unlock = 0; int ecne_seen = 0; @@ -4683,7 +4742,6 @@ * until we get into jumbo grams and such.. */ uint8_t chunk_buf[SCTP_CHUNK_BUFFER_SIZE]; - struct sctp_tcb *locked_tcb = stcb; int got_auth = 0; uint32_t auth_offset = 0, auth_len = 0; int auth_skipped = 0; @@ -4695,31 +4753,29 @@ SCTPDBG(SCTP_DEBUG_INPUT1, "sctp_process_control: iphlen=%u, offset=%u, length=%u stcb:%p\n", iphlen, *offset, length, (void *)stcb); + if (stcb) { + SCTP_TCB_LOCK_ASSERT(stcb); + } /* validate chunk header length... */ if (ntohs(ch->chunk_length) < sizeof(*ch)) { SCTPDBG(SCTP_DEBUG_INPUT1, "Invalid header length %d\n", ntohs(ch->chunk_length)); - if (locked_tcb) { - SCTP_TCB_UNLOCK(locked_tcb); - } - return (NULL); + *offset = length; + return (stcb); } /* * validate the verification tag */ vtag_in = ntohl(sh->v_tag); - if (locked_tcb) { - SCTP_TCB_LOCK_ASSERT(locked_tcb); - } if (ch->chunk_type == SCTP_INITIATION) { SCTPDBG(SCTP_DEBUG_INPUT1, "Its an INIT of len:%d vtag:%x\n", ntohs(ch->chunk_length), vtag_in); if (vtag_in != 0) { /* protocol error- silently discard... */ SCTP_STAT_INCR(sctps_badvtag); - if (locked_tcb) { - SCTP_TCB_UNLOCK(locked_tcb); + if (stcb != NULL) { + SCTP_TCB_UNLOCK(stcb); } return (NULL); } @@ -4742,9 +4798,6 @@ if (*offset >= length) { /* no more data left in the mbuf chain */ *offset = length; - if (locked_tcb) { - SCTP_TCB_UNLOCK(locked_tcb); - } return (NULL); } ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, *offset, @@ -4753,10 +4806,7 @@ if (ch == NULL) { /* Help */ *offset = length; - if (locked_tcb) { - SCTP_TCB_UNLOCK(locked_tcb); - } - return (NULL); + return (stcb); } if (ch->chunk_type == SCTP_COOKIE_ECHO) { goto process_control_chunks; @@ -4793,8 +4843,6 @@ * sctp_findassociation_ep_asconf(). */ SCTP_INP_DECR_REF(inp); - } else { - locked_tcb = stcb; } /* now go back and verify any auth chunk to be sure */ @@ -4810,10 +4858,7 @@ auth_offset)) { /* auth HMAC failed so dump it */ *offset = length; - if (locked_tcb) { - SCTP_TCB_UNLOCK(locked_tcb); - } - return (NULL); + return (stcb); } else { /* remaining chunks are HMAC checked */ stcb->asoc.authenticated = 1; @@ -4831,9 +4876,6 @@ #endif vrf_id, port); *offset = length; - if (locked_tcb) { - SCTP_TCB_UNLOCK(locked_tcb); - } return (NULL); } asoc = &stcb->asoc; @@ -4845,13 +4887,14 @@ if ((((ch->chunk_flags & SCTP_HAD_NO_TCB) == 0) && (vtag_in == asoc->my_vtag)) || (((ch->chunk_flags & SCTP_HAD_NO_TCB) == SCTP_HAD_NO_TCB) && + (asoc->peer_vtag != htonl(0)) && (vtag_in == asoc->peer_vtag))) { /* this is valid */ } else { /* drop this packet... */ SCTP_STAT_INCR(sctps_badvtag); - if (locked_tcb) { - SCTP_TCB_UNLOCK(locked_tcb); + if (stcb != NULL) { + SCTP_TCB_UNLOCK(stcb); } return (NULL); } @@ -4864,8 +4907,8 @@ * but it won't complete until the shutdown * is completed */ - if (locked_tcb) { - SCTP_TCB_UNLOCK(locked_tcb); + if (stcb != NULL) { + SCTP_TCB_UNLOCK(stcb); } snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s", __FILE__, __LINE__, __func__); op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), @@ -4886,8 +4929,8 @@ "invalid vtag: %xh, expect %xh\n", vtag_in, asoc->my_vtag); SCTP_STAT_INCR(sctps_badvtag); - if (locked_tcb) { - SCTP_TCB_UNLOCK(locked_tcb); + if (stcb != NULL) { + SCTP_TCB_UNLOCK(stcb); } *offset = length; return (NULL); @@ -4902,14 +4945,6 @@ (ch->chunk_type == SCTP_HEARTBEAT_REQUEST)) && (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_ECHOED)) { /* implied cookie-ack.. we must have lost the ack */ - if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { - sctp_misc_ints(SCTP_THRESHOLD_CLEAR, - stcb->asoc.overall_error_count, - 0, - SCTP_FROM_SCTP_INPUT, - __LINE__); - } - stcb->asoc.overall_error_count = 0; sctp_handle_cookie_ack((struct sctp_cookie_ack_chunk *)ch, stcb, *netp); } @@ -4924,66 +4959,36 @@ if (chk_length < sizeof(*ch) || (*offset + (int)chk_length) > length) { *offset = length; - if (locked_tcb) { - SCTP_TCB_UNLOCK(locked_tcb); - } - return (NULL); + return (stcb); } SCTP_STAT_INCR_COUNTER64(sctps_incontrolchunks); /* - * INIT-ACK only gets the init ack "header" portion only - * because we don't have to process the peer's COOKIE. All - * others get a complete chunk. + * INIT and INIT-ACK only gets the init ack "header" portion + * only because we don't have to process the peer's COOKIE. + * All others get a complete chunk. */ - if ((ch->chunk_type == SCTP_INITIATION_ACK) || - (ch->chunk_type == SCTP_INITIATION)) { - /* get an init-ack chunk */ - ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, *offset, - sizeof(struct sctp_init_ack_chunk), chunk_buf); - if (ch == NULL) { - *offset = length; - if (locked_tcb) { - SCTP_TCB_UNLOCK(locked_tcb); - } - return (NULL); - } - } else { - /* For cookies and all other chunks. */ - if (chk_length > sizeof(chunk_buf)) { - /* - * use just the size of the chunk buffer - * so the front part of our chunks fit in - * contiguous space up to the chunk buffer - * size (508 bytes). - * For chunks that need to get more than that - * they must use the sctp_m_getptr() function - * or other means (e.g. know how to parse mbuf - * chains). Cookies do this already. - */ - ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, *offset, - (sizeof(chunk_buf) - 4), - chunk_buf); - if (ch == NULL) { - *offset = length; - if (locked_tcb) { - SCTP_TCB_UNLOCK(locked_tcb); - } - return (NULL); - } - } else { - /* We can fit it all */ - ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, *offset, - chk_length, chunk_buf); - if (ch == NULL) { - SCTP_PRINTF("sctp_process_control: Can't get the all data....\n"); - *offset = length; - if (locked_tcb) { - SCTP_TCB_UNLOCK(locked_tcb); - } - return (NULL); - } - } + switch (ch->chunk_type) { + case SCTP_INITIATION: + contiguous = sizeof(struct sctp_init_chunk); + break; + case SCTP_INITIATION_ACK: + contiguous = sizeof(struct sctp_init_ack_chunk); + break; + default: + contiguous = min(chk_length, sizeof(chunk_buf)); + break; } + ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, *offset, + contiguous, + chunk_buf); + if (ch == NULL) { + *offset = length; + if (stcb != NULL) { + SCTP_TCB_UNLOCK(stcb); + } + return (NULL); + } + num_chunks++; /* Save off the last place we got a control from */ if (stcb != NULL) { @@ -5018,8 +5023,8 @@ (length - *offset > (int)SCTP_SIZE32(chk_length))) { /* RFC 4960 requires that no ABORT is sent */ *offset = length; - if (locked_tcb) { - SCTP_TCB_UNLOCK(locked_tcb); + if (stcb != NULL) { + SCTP_TCB_UNLOCK(stcb); } return (NULL); } @@ -5043,26 +5048,22 @@ #endif vrf_id, port); *offset = length; - if ((!abort_no_unlock) && (locked_tcb)) { - SCTP_TCB_UNLOCK(locked_tcb); + if ((!abort_no_unlock) && (stcb != NULL)) { + SCTP_TCB_UNLOCK(stcb); } return (NULL); break; case SCTP_PAD_CHUNK: break; case SCTP_INITIATION_ACK: - SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_INIT-ACK\n"); + SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_INIT_ACK\n"); if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) { /* We are not interested anymore */ - if ((stcb) && (stcb->asoc.total_output_queue_size)) { + if ((stcb != NULL) && (stcb->asoc.total_output_queue_size)) { ; } else { - if ((locked_tcb != NULL) && (locked_tcb != stcb)) { - /* Very unlikely */ - SCTP_TCB_UNLOCK(locked_tcb); - } *offset = length; - if (stcb) { + if (stcb != NULL) { #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) so = SCTP_INP_SO(inp); atomic_add_int(&stcb->asoc.refcnt, 1); @@ -5084,12 +5085,9 @@ if ((num_chunks > 1) || (length - *offset > (int)SCTP_SIZE32(chk_length))) { *offset = length; - if (locked_tcb) { - SCTP_TCB_UNLOCK(locked_tcb); - } - return (NULL); + return (stcb); } - if ((netp) && (*netp)) { + if ((netp != NULL) && (*netp != NULL)) { ret = sctp_handle_init_ack(m, iphlen, *offset, src, dst, sh, (struct sctp_init_ack_chunk *)ch, @@ -5113,44 +5111,57 @@ if ((stcb != NULL) && (ret == 0)) { sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_CONTROL_PROC, SCTP_SO_NOT_LOCKED); } - if (locked_tcb) { - SCTP_TCB_UNLOCK(locked_tcb); - } - return (NULL); + return (stcb); break; case SCTP_SELECTIVE_ACK: - { - struct sctp_sack_chunk *sack; - int abort_now = 0; - uint32_t a_rwnd, cum_ack; - uint16_t num_seg, num_dup; - uint8_t flags; - int offset_seg, offset_dup; + case SCTP_NR_SELECTIVE_ACK: + { + int abort_now = 0; + uint32_t a_rwnd, cum_ack; + uint16_t num_seg, num_nr_seg, num_dup; + uint8_t flags; + int offset_seg, offset_dup; - SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_SACK\n"); - SCTP_STAT_INCR(sctps_recvsacks); - if (stcb == NULL) { - SCTPDBG(SCTP_DEBUG_INDATA1, "No stcb when processing SACK chunk\n"); - break; - } + SCTPDBG(SCTP_DEBUG_INPUT3, "%s\n", + ch->chunk_type == SCTP_SELECTIVE_ACK ? "SCTP_SACK" : "SCTP_NR_SACK"); + SCTP_STAT_INCR(sctps_recvsacks); + if (stcb == NULL) { + SCTPDBG(SCTP_DEBUG_INDATA1, "No stcb when processing %s chunk\n", + (ch->chunk_type == SCTP_SELECTIVE_ACK) ? "SCTP_SACK" : "SCTP_NR_SACK"); + break; + } + if (ch->chunk_type == SCTP_SELECTIVE_ACK) { if (chk_length < sizeof(struct sctp_sack_chunk)) { SCTPDBG(SCTP_DEBUG_INDATA1, "Bad size on SACK chunk, too small\n"); break; } - if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_ACK_SENT) { - /*- - * If we have sent a shutdown-ack, we will pay no - * attention to a sack sent in to us since - * we don't care anymore. - */ + } else { + if (stcb->asoc.nrsack_supported == 0) { + goto unknown_chunk; + } + if (chk_length < sizeof(struct sctp_nr_sack_chunk)) { + SCTPDBG(SCTP_DEBUG_INDATA1, "Bad size on NR_SACK chunk, too small\n"); break; } + } + if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_ACK_SENT) { + /*- + * If we have sent a shutdown-ack, we will pay no + * attention to a sack sent in to us since + * we don't care anymore. + */ + break; + } + flags = ch->chunk_flags; + if (ch->chunk_type == SCTP_SELECTIVE_ACK) { + struct sctp_sack_chunk *sack; + sack = (struct sctp_sack_chunk *)ch; - flags = ch->chunk_flags; cum_ack = ntohl(sack->sack.cum_tsn_ack); num_seg = ntohs(sack->sack.num_gap_ack_blks); + num_nr_seg = 0; num_dup = ntohs(sack->sack.num_dup_tsns); - a_rwnd = (uint32_t) ntohl(sack->sack.a_rwnd); + a_rwnd = ntohl(sack->sack.a_rwnd); if (sizeof(struct sctp_sack_chunk) + num_seg * sizeof(struct sctp_gap_ack_block) + num_dup * sizeof(uint32_t) != chk_length) { @@ -5159,78 +5170,15 @@ } offset_seg = *offset + sizeof(struct sctp_sack_chunk); offset_dup = offset_seg + num_seg * sizeof(struct sctp_gap_ack_block); - SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_SACK process cum_ack:%x num_seg:%d a_rwnd:%d\n", - cum_ack, num_seg, a_rwnd); - stcb->asoc.seen_a_sack_this_pkt = 1; - if ((stcb->asoc.pr_sctp_cnt == 0) && - (num_seg == 0) && - SCTP_TSN_GE(cum_ack, stcb->asoc.last_acked_seq) && - (stcb->asoc.saw_sack_with_frags == 0) && - (stcb->asoc.saw_sack_with_nr_frags == 0) && - (!TAILQ_EMPTY(&stcb->asoc.sent_queue)) - ) { - /* We have a SIMPLE sack having no prior segments and - * data on sent queue to be acked.. Use the faster - * path sack processing. We also allow window update - * sacks with no missing segments to go this way too. - */ - sctp_express_handle_sack(stcb, cum_ack, a_rwnd, &abort_now, ecne_seen); - } else { - if (netp && *netp) - sctp_handle_sack(m, offset_seg, offset_dup, stcb, - num_seg, 0, num_dup, &abort_now, flags, - cum_ack, a_rwnd, ecne_seen); - } - if (abort_now) { - /* ABORT signal from sack processing */ - *offset = length; - return (NULL); - } - if (TAILQ_EMPTY(&stcb->asoc.send_queue) && - TAILQ_EMPTY(&stcb->asoc.sent_queue) && - (stcb->asoc.stream_queue_cnt == 0)) { - sctp_ulp_notify(SCTP_NOTIFY_SENDER_DRY, stcb, 0, NULL, SCTP_SO_NOT_LOCKED); - } - } - break; - /* EY - nr_sack: If the received chunk is an nr_sack chunk */ - case SCTP_NR_SELECTIVE_ACK: - { + } else { struct sctp_nr_sack_chunk *nr_sack; - int abort_now = 0; - uint32_t a_rwnd, cum_ack; - uint16_t num_seg, num_nr_seg, num_dup; - uint8_t flags; - int offset_seg, offset_dup; - SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_NR_SACK\n"); - SCTP_STAT_INCR(sctps_recvsacks); - if (stcb == NULL) { - SCTPDBG(SCTP_DEBUG_INDATA1, "No stcb when processing NR-SACK chunk\n"); - break; - } - if (stcb->asoc.nrsack_supported == 0) { - goto unknown_chunk; - } - if (chk_length < sizeof(struct sctp_nr_sack_chunk)) { - SCTPDBG(SCTP_DEBUG_INDATA1, "Bad size on NR-SACK chunk, too small\n"); - break; - } - if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_ACK_SENT) { - /*- - * If we have sent a shutdown-ack, we will pay no - * attention to a sack sent in to us since - * we don't care anymore. - */ - break; - } nr_sack = (struct sctp_nr_sack_chunk *)ch; - flags = ch->chunk_flags; cum_ack = ntohl(nr_sack->nr_sack.cum_tsn_ack); num_seg = ntohs(nr_sack->nr_sack.num_gap_ack_blks); num_nr_seg = ntohs(nr_sack->nr_sack.num_nr_gap_ack_blks); num_dup = ntohs(nr_sack->nr_sack.num_dup_tsns); - a_rwnd = (uint32_t) ntohl(nr_sack->nr_sack.a_rwnd); + a_rwnd = ntohl(nr_sack->nr_sack.a_rwnd); if (sizeof(struct sctp_nr_sack_chunk) + (num_seg + num_nr_seg) * sizeof(struct sctp_gap_ack_block) + num_dup * sizeof(uint32_t) != chk_length) { @@ -5238,108 +5186,91 @@ break; } offset_seg = *offset + sizeof(struct sctp_nr_sack_chunk); - offset_dup = offset_seg + num_seg * sizeof(struct sctp_gap_ack_block); - SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_NR_SACK process cum_ack:%x num_seg:%d a_rwnd:%d\n", - cum_ack, num_seg, a_rwnd); - stcb->asoc.seen_a_sack_this_pkt = 1; - if ((stcb->asoc.pr_sctp_cnt == 0) && - (num_seg == 0) && (num_nr_seg == 0) && - SCTP_TSN_GE(cum_ack, stcb->asoc.last_acked_seq) && - (stcb->asoc.saw_sack_with_frags == 0) && - (stcb->asoc.saw_sack_with_nr_frags == 0) && - (!TAILQ_EMPTY(&stcb->asoc.sent_queue))) { - /* - * We have a SIMPLE sack having no - * prior segments and data on sent - * queue to be acked. Use the - * faster path sack processing. We - * also allow window update sacks - * with no missing segments to go - * this way too. - */ - sctp_express_handle_sack(stcb, cum_ack, a_rwnd, - &abort_now, ecne_seen); - } else { - if (netp && *netp) - sctp_handle_sack(m, offset_seg, offset_dup, stcb, - num_seg, num_nr_seg, num_dup, &abort_now, flags, - cum_ack, a_rwnd, ecne_seen); - } - if (abort_now) { - /* ABORT signal from sack processing */ - *offset = length; - return (NULL); - } - if (TAILQ_EMPTY(&stcb->asoc.send_queue) && - TAILQ_EMPTY(&stcb->asoc.sent_queue) && - (stcb->asoc.stream_queue_cnt == 0)) { - sctp_ulp_notify(SCTP_NOTIFY_SENDER_DRY, stcb, 0, NULL, SCTP_SO_NOT_LOCKED); + offset_dup = offset_seg + (num_seg + num_nr_seg) * sizeof(struct sctp_gap_ack_block); + } + SCTPDBG(SCTP_DEBUG_INPUT3, "%s process cum_ack:%x num_seg:%d a_rwnd:%d\n", + (ch->chunk_type == SCTP_SELECTIVE_ACK) ? "SCTP_SACK" : "SCTP_NR_SACK", + cum_ack, num_seg, a_rwnd); + stcb->asoc.seen_a_sack_this_pkt = 1; + if ((stcb->asoc.pr_sctp_cnt == 0) && + (num_seg == 0) && (num_nr_seg == 0) && + SCTP_TSN_GE(cum_ack, stcb->asoc.last_acked_seq) && + (stcb->asoc.saw_sack_with_frags == 0) && + (stcb->asoc.saw_sack_with_nr_frags == 0) && + (!TAILQ_EMPTY(&stcb->asoc.sent_queue))) { + /* + * We have a SIMPLE sack having no + * prior segments and data on sent + * queue to be acked. Use the + * faster path sack processing. We + * also allow window update sacks + * with no missing segments to go + * this way too. + */ + sctp_express_handle_sack(stcb, cum_ack, a_rwnd, + &abort_now, ecne_seen); + } else { + if ((netp != NULL) && (*netp != NULL)) { + sctp_handle_sack(m, offset_seg, offset_dup, stcb, + num_seg, num_nr_seg, num_dup, &abort_now, flags, + cum_ack, a_rwnd, ecne_seen); } } + if (abort_now) { + /* ABORT signal from sack processing */ + *offset = length; + return (NULL); + } + if (TAILQ_EMPTY(&stcb->asoc.send_queue) && + TAILQ_EMPTY(&stcb->asoc.sent_queue) && + (stcb->asoc.stream_queue_cnt == 0)) { + sctp_ulp_notify(SCTP_NOTIFY_SENDER_DRY, stcb, 0, NULL, SCTP_SO_NOT_LOCKED); + } break; - + } case SCTP_HEARTBEAT_REQUEST: SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_HEARTBEAT\n"); - if ((stcb) && netp && *netp) { + if ((stcb != NULL) && (netp != NULL) && (*netp != NULL)) { SCTP_STAT_INCR(sctps_recvheartbeat); sctp_send_heartbeat_ack(stcb, m, *offset, chk_length, *netp); - - /* He's alive so give him credit */ - if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { - sctp_misc_ints(SCTP_THRESHOLD_CLEAR, - stcb->asoc.overall_error_count, - 0, - SCTP_FROM_SCTP_INPUT, - __LINE__); - } - stcb->asoc.overall_error_count = 0; } break; case SCTP_HEARTBEAT_ACK: - SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_HEARTBEAT-ACK\n"); + SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_HEARTBEAT_ACK\n"); if ((stcb == NULL) || (chk_length != sizeof(struct sctp_heartbeat_chunk))) { /* Its not ours */ *offset = length; - if (locked_tcb) { - SCTP_TCB_UNLOCK(locked_tcb); - } - return (NULL); + return (stcb); } - /* He's alive so give him credit */ - if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { - sctp_misc_ints(SCTP_THRESHOLD_CLEAR, - stcb->asoc.overall_error_count, - 0, - SCTP_FROM_SCTP_INPUT, - __LINE__); - } - stcb->asoc.overall_error_count = 0; SCTP_STAT_INCR(sctps_recvheartbeatack); - if (netp && *netp) + if ((netp != NULL) && (*netp != NULL)) { sctp_handle_heartbeat_ack((struct sctp_heartbeat_chunk *)ch, stcb, *netp); + } break; case SCTP_ABORT_ASSOCIATION: SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_ABORT, stcb %p\n", (void *)stcb); - if ((stcb) && netp && *netp) - sctp_handle_abort((struct sctp_abort_chunk *)ch, - stcb, *netp); *offset = length; - return (NULL); + if ((stcb != NULL) && (netp != NULL) && (*netp != NULL)) { + if (sctp_handle_abort((struct sctp_abort_chunk *)ch, stcb, *netp)) { + return (NULL); + } else { + return (stcb); + } + } else { + return (NULL); + } break; case SCTP_SHUTDOWN: SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_SHUTDOWN, stcb %p\n", (void *)stcb); if ((stcb == NULL) || (chk_length != sizeof(struct sctp_shutdown_chunk))) { *offset = length; - if (locked_tcb) { - SCTP_TCB_UNLOCK(locked_tcb); - } - return (NULL); + return (stcb); } - if (netp && *netp) { + if ((netp != NULL) && (*netp != NULL)) { int abort_flag = 0; sctp_handle_shutdown((struct sctp_shutdown_chunk *)ch, @@ -5351,30 +5282,31 @@ } break; case SCTP_SHUTDOWN_ACK: - SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_SHUTDOWN-ACK, stcb %p\n", (void *)stcb); - if ((stcb) && (netp) && (*netp)) + SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_SHUTDOWN_ACK, stcb %p\n", (void *)stcb); + if ((stcb != NULL) && (netp != NULL) && (*netp != NULL)) { sctp_handle_shutdown_ack((struct sctp_shutdown_ack_chunk *)ch, stcb, *netp); + } *offset = length; return (NULL); break; - case SCTP_OPERATION_ERROR: - SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_OP-ERR\n"); - if ((stcb) && netp && *netp && sctp_handle_error(ch, stcb, *netp) < 0) { + SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_OP_ERR\n"); + if ((stcb != NULL) && (netp != NULL) && (*netp != NULL) && + sctp_handle_error(ch, stcb, *netp, contiguous) < 0) { *offset = length; return (NULL); } break; case SCTP_COOKIE_ECHO: SCTPDBG(SCTP_DEBUG_INPUT3, - "SCTP_COOKIE-ECHO, stcb %p\n", (void *)stcb); - if ((stcb) && (stcb->asoc.total_output_queue_size)) { + "SCTP_COOKIE_ECHO, stcb %p\n", (void *)stcb); + if ((stcb != NULL) && (stcb->asoc.total_output_queue_size > 0)) { ; } else { if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) { /* We are not interested anymore */ abend: - if (stcb) { + if (stcb != NULL) { SCTP_TCB_UNLOCK(stcb); } *offset = length; @@ -5427,7 +5359,7 @@ linp = inp; } - if (linp) { + if (linp != NULL) { SCTP_ASOC_CREATE_LOCK(linp); if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) || (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE)) { @@ -5436,7 +5368,10 @@ } } - if (netp) { + if (netp != NULL) { + struct sctp_tcb *locked_stcb; + + locked_stcb = stcb; ret_buf = sctp_handle_cookie_echo(m, iphlen, *offset, @@ -5447,22 +5382,28 @@ auth_skipped, auth_offset, auth_len, - &locked_tcb, + &locked_stcb, #if defined(__FreeBSD__) mflowtype, mflowid, #endif vrf_id, port); + if ((locked_stcb != NULL) && (locked_stcb != stcb)) { + SCTP_TCB_UNLOCK(locked_stcb); + } + if (stcb != NULL) { + SCTP_TCB_LOCK_ASSERT(stcb); + } } else { ret_buf = NULL; } - if (linp) { + if (linp != NULL) { SCTP_ASOC_CREATE_UNLOCK(linp); } if (ret_buf == NULL) { - if (locked_tcb) { - SCTP_TCB_UNLOCK(locked_tcb); + if (stcb != NULL) { + SCTP_TCB_UNLOCK(stcb); } SCTPDBG(SCTP_DEBUG_INPUT3, "GAK, null buffer\n"); @@ -5487,12 +5428,9 @@ } break; case SCTP_COOKIE_ACK: - SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_COOKIE-ACK, stcb %p\n", (void *)stcb); + SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_COOKIE_ACK, stcb %p\n", (void *)stcb); if ((stcb == NULL) || chk_length != sizeof(struct sctp_cookie_ack_chunk)) { - if (locked_tcb) { - SCTP_TCB_UNLOCK(locked_tcb); - } - return (NULL); + return (stcb); } if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) { /* We are not interested anymore */ @@ -5516,85 +5454,43 @@ return (NULL); } } - /* He's alive so give him credit */ - if ((stcb) && netp && *netp) { - if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { - sctp_misc_ints(SCTP_THRESHOLD_CLEAR, - stcb->asoc.overall_error_count, - 0, - SCTP_FROM_SCTP_INPUT, - __LINE__); - } - stcb->asoc.overall_error_count = 0; - sctp_handle_cookie_ack((struct sctp_cookie_ack_chunk *)ch,stcb, *netp); + if ((netp != NULL) && (*netp != NULL)) { + sctp_handle_cookie_ack((struct sctp_cookie_ack_chunk *)ch, stcb, *netp); } break; case SCTP_ECN_ECHO: - SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_ECN-ECHO\n"); - /* He's alive so give him credit */ + SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_ECN_ECHO\n"); if ((stcb == NULL) || (chk_length != sizeof(struct sctp_ecne_chunk))) { /* Its not ours */ - if (locked_tcb) { - SCTP_TCB_UNLOCK(locked_tcb); - } *offset = length; - return (NULL); + return (stcb); } - if (stcb) { - if (stcb->asoc.ecn_supported == 0) { - goto unknown_chunk; - } - if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { - sctp_misc_ints(SCTP_THRESHOLD_CLEAR, - stcb->asoc.overall_error_count, - 0, - SCTP_FROM_SCTP_INPUT, - __LINE__); - } - stcb->asoc.overall_error_count = 0; - sctp_handle_ecn_echo((struct sctp_ecne_chunk *)ch, - stcb); - ecne_seen = 1; + if (stcb->asoc.ecn_supported == 0) { + goto unknown_chunk; } + sctp_handle_ecn_echo((struct sctp_ecne_chunk *)ch, stcb); + ecne_seen = 1; break; case SCTP_ECN_CWR: - SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_ECN-CWR\n"); - /* He's alive so give him credit */ + SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_ECN_CWR\n"); if ((stcb == NULL) || (chk_length != sizeof(struct sctp_cwr_chunk))) { - /* Its not ours */ - if (locked_tcb) { - SCTP_TCB_UNLOCK(locked_tcb); - } *offset = length; - return (NULL); + return (stcb); } - if (stcb) { - if (stcb->asoc.ecn_supported == 0) { - goto unknown_chunk; - } - if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { - sctp_misc_ints(SCTP_THRESHOLD_CLEAR, - stcb->asoc.overall_error_count, - 0, - SCTP_FROM_SCTP_INPUT, - __LINE__); - } - stcb->asoc.overall_error_count = 0; - sctp_handle_ecn_cwr((struct sctp_cwr_chunk *)ch, stcb, *netp); + if (stcb->asoc.ecn_supported == 0) { + goto unknown_chunk; } + sctp_handle_ecn_cwr((struct sctp_cwr_chunk *)ch, stcb, *netp); break; case SCTP_SHUTDOWN_COMPLETE: - SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_SHUTDOWN-COMPLETE, stcb %p\n", (void *)stcb); + SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_SHUTDOWN_COMPLETE, stcb %p\n", (void *)stcb); /* must be first and only chunk */ if ((num_chunks > 1) || (length - *offset > (int)SCTP_SIZE32(chk_length))) { *offset = length; - if (locked_tcb) { - SCTP_TCB_UNLOCK(locked_tcb); - } - return (NULL); + return (stcb); } - if ((stcb) && netp && *netp) { + if ((stcb != NULL) && (netp != NULL) && (*netp != NULL)) { sctp_handle_shutdown_complete((struct sctp_shutdown_complete_chunk *)ch, stcb, *netp); } @@ -5603,35 +5499,23 @@ break; case SCTP_ASCONF: SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_ASCONF\n"); - /* He's alive so give him credit */ - if (stcb) { + if (stcb != NULL) { if (stcb->asoc.asconf_supported == 0) { goto unknown_chunk; } - if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { - sctp_misc_ints(SCTP_THRESHOLD_CLEAR, - stcb->asoc.overall_error_count, - 0, - SCTP_FROM_SCTP_INPUT, - __LINE__); - } - stcb->asoc.overall_error_count = 0; sctp_handle_asconf(m, *offset, src, (struct sctp_asconf_chunk *)ch, stcb, asconf_cnt == 0); asconf_cnt++; } break; case SCTP_ASCONF_ACK: - SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_ASCONF-ACK\n"); + SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_ASCONF_ACK\n"); if (chk_length < sizeof(struct sctp_asconf_ack_chunk)) { /* Its not ours */ - if (locked_tcb) { - SCTP_TCB_UNLOCK(locked_tcb); - } *offset = length; - return (NULL); + return (stcb); } - if ((stcb) && netp && *netp) { + if ((stcb != NULL) && (netp != NULL) && (*netp != NULL)) { if (stcb->asoc.asconf_supported == 0) { goto unknown_chunk; } @@ -5652,31 +5536,19 @@ break; case SCTP_FORWARD_CUM_TSN: case SCTP_IFORWARD_CUM_TSN: - SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_FWD-TSN\n"); + SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_FWD_TSN\n"); if (chk_length < sizeof(struct sctp_forward_tsn_chunk)) { /* Its not ours */ - if (locked_tcb) { - SCTP_TCB_UNLOCK(locked_tcb); - } *offset = length; - return (NULL); + return (stcb); } - /* He's alive so give him credit */ - if (stcb) { + if (stcb != NULL) { int abort_flag = 0; if (stcb->asoc.prsctp_supported == 0) { goto unknown_chunk; } - stcb->asoc.overall_error_count = 0; - if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { - sctp_misc_ints(SCTP_THRESHOLD_CLEAR, - stcb->asoc.overall_error_count, - 0, - SCTP_FROM_SCTP_INPUT, - __LINE__); - } *fwd_tsn_seen = 1; if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) { /* We are not interested anymore */ @@ -5706,28 +5578,15 @@ if (abort_flag) { *offset = length; return (NULL); - } else { - if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { - sctp_misc_ints(SCTP_THRESHOLD_CLEAR, - stcb->asoc.overall_error_count, - 0, - SCTP_FROM_SCTP_INPUT, - __LINE__); - } - stcb->asoc.overall_error_count = 0; } - } break; case SCTP_STREAM_RESET: SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_STREAM_RESET\n"); if (((stcb == NULL) || (ch == NULL) || (chk_length < sizeof(struct sctp_stream_reset_tsn_req)))) { /* Its not ours */ - if (locked_tcb) { - SCTP_TCB_UNLOCK(locked_tcb); - } *offset = length; - return (NULL); + return (stcb); } if (stcb->asoc.reconfig_supported == 0) { goto unknown_chunk; @@ -5743,24 +5602,18 @@ /* re-get it all please */ if (chk_length < sizeof(struct sctp_pktdrop_chunk)) { /* Its not ours */ - if (locked_tcb) { - SCTP_TCB_UNLOCK(locked_tcb); - } *offset = length; - return (NULL); + return (stcb); } - - if (ch && (stcb) && netp && (*netp)) { + if ((ch != NULL) && (stcb != NULL) && (netp != NULL) && (*netp != NULL)) { if (stcb->asoc.pktdrop_supported == 0) { goto unknown_chunk; } sctp_handle_packet_dropped((struct sctp_pktdrop_chunk *)ch, stcb, *netp, - min(chk_length, (sizeof(chunk_buf) - 4))); - + min(chk_length, contiguous)); } - break; case SCTP_AUTHENTICATION: SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_AUTHENTICATION\n"); @@ -5781,11 +5634,8 @@ (chk_length > (sizeof(struct sctp_auth_chunk) + SCTP_AUTH_DIGEST_LEN_MAX))) { /* Its not ours */ - if (locked_tcb) { - SCTP_TCB_UNLOCK(locked_tcb); - } *offset = length; - return (NULL); + return (stcb); } if (got_auth == 1) { /* skip this chunk... it's already auth'd */ @@ -5850,15 +5700,12 @@ ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, *offset, sizeof(struct sctp_chunkhdr), chunk_buf); if (ch == NULL) { - if (locked_tcb) { - SCTP_TCB_UNLOCK(locked_tcb); - } *offset = length; - return (NULL); + return (stcb); } } /* while */ - if (asconf_cnt > 0 && stcb != NULL) { + if ((asconf_cnt > 0) && (stcb != NULL)) { sctp_send_asconf_ack(stcb); } return (stcb); @@ -6155,14 +6002,6 @@ * shows us the cookie-ack was lost. Imply it was * there. */ - if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { - sctp_misc_ints(SCTP_THRESHOLD_CLEAR, - stcb->asoc.overall_error_count, - 0, - SCTP_FROM_SCTP_INPUT, - __LINE__); - } - stcb->asoc.overall_error_count = 0; sctp_handle_cookie_ack((struct sctp_cookie_ack_chunk *)ch, stcb, net); break; case SCTP_STATE_COOKIE_WAIT:
diff --git a/usrsctplib/netinet/sctp_input.h b/usrsctplib/netinet/sctp_input.h index bc4cf42..c92c8bd 100755 --- a/usrsctplib/netinet/sctp_input.h +++ b/usrsctplib/netinet/sctp_input.h
@@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved. * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved. * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
diff --git a/usrsctplib/netinet/sctp_lock_userspace.h b/usrsctplib/netinet/sctp_lock_userspace.h index 83a565c..7b8b0cb 100755 --- a/usrsctplib/netinet/sctp_lock_userspace.h +++ b/usrsctplib/netinet/sctp_lock_userspace.h
@@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved. * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved. * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
diff --git a/usrsctplib/netinet/sctp_os.h b/usrsctplib/netinet/sctp_os.h index 4888381..b3746dd 100755 --- a/usrsctplib/netinet/sctp_os.h +++ b/usrsctplib/netinet/sctp_os.h
@@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 2006-2007, by Cisco Systems, Inc. All rights reserved. * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved. * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
diff --git a/usrsctplib/netinet/sctp_os_userspace.h b/usrsctplib/netinet/sctp_os_userspace.h index 50b7de2..8613301 100755 --- a/usrsctplib/netinet/sctp_os_userspace.h +++ b/usrsctplib/netinet/sctp_os_userspace.h
@@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 2006-2007, by Cisco Systems, Inc. All rights reserved. * Copyright (c) 2008-2011, by Randall Stewart. All rights reserved. * Copyright (c) 2008-2011, by Michael Tuexen. All rights reserved. @@ -45,8 +47,8 @@ #include <winsock2.h> #include <ws2tcpip.h> #include <iphlpapi.h> -#include <mswsock.h> -#include <windows.h> +#include <Mswsock.h> +#include <Windows.h> #include "user_environment.h" typedef CRITICAL_SECTION userland_mutex_t; #if WINVER < 0x0600 @@ -216,6 +218,8 @@ typedef char* caddr_t; +#define bzero(buf, len) memset(buf, 0, len) +#define bcopy(srcKey, dstKey, len) memcpy(dstKey, srcKey, len) #if _MSC_VER < 1900 #define snprintf(data, size, format, ...) _snprintf_s(data, size, _TRUNCATE, format, __VA_ARGS__) #endif @@ -272,7 +276,7 @@ #else /* !defined(Userspace_os_Windows) */ #include <sys/socket.h> -#if defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD) || defined(__Userspace_os_Linux) || defined(__Userspace_os_NetBSD) || defined(__Userspace_os_OpenBSD) || defined(__Userspace_os_NaCl) +#if defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD) || defined(__Userspace_os_Linux) || defined(__Userspace_os_NetBSD) || defined(__Userspace_os_OpenBSD) || defined(__Userspace_os_NaCl) || defined(__Userspace_os_Fuchsia) #include <pthread.h> #endif typedef pthread_mutex_t userland_mutex_t; @@ -411,6 +415,8 @@ #endif #if defined(__Userspace_os_Windows) +int Win_getifaddrs(struct ifaddrs**); +#define getifaddrs(interfaces) (int)Win_getifaddrs(interfaces) int win_if_nametoindex(const char *); #define if_nametoindex(x) win_if_nametoindex(x) #endif @@ -459,7 +465,7 @@ #include <sys/priv.h> #endif /* #include <sys/random.h> */ -/* #include <sys/limits.h> */ +#include <limits.h> /* #include <machine/cpu.h> */ #if defined(__Userspace_os_Darwin) @@ -985,11 +991,6 @@ #define SCTP_SB_LIMIT_RCV(so) so->so_rcv.sb_hiwat #define SCTP_SB_LIMIT_SND(so) so->so_snd.sb_hiwat -/* Future zero copy wakeup/send function */ -#define SCTP_ZERO_COPY_EVENT(inp, so) -/* This is re-pulse ourselves for sendbuf */ -#define SCTP_ZERO_COPY_SENDQ_EVENT(inp, so) - #define SCTP_READ_RANDOM(buf, len) read_random(buf, len) #define SCTP_SHA1_CTX struct sctp_sha1_context
diff --git a/usrsctplib/netinet/sctp_output.c b/usrsctplib/netinet/sctp_output.c index 90b0bf3..6ac2059 100755 --- a/usrsctplib/netinet/sctp_output.c +++ b/usrsctplib/netinet/sctp_output.c
@@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 2001-2008, by Cisco Systems, Inc. All rights reserved. * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved. * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved. @@ -32,7 +34,7 @@ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_output.c 321204 2017-07-19 14:28:58Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp_output.c 325370 2017-11-03 20:46:12Z tuexen $"); #endif #include <netinet/sctp_os.h> @@ -3566,32 +3568,35 @@ #else struct cmsghdr cmh; #endif - int tlen, at, found; struct sctp_sndinfo sndinfo; struct sctp_prinfo prinfo; struct sctp_authinfo authinfo; + int tot_len, rem_len, cmsg_data_len, cmsg_data_off, off; + int found; - tlen = SCTP_BUF_LEN(control); - at = 0; - found = 0; /* * Independent of how many mbufs, find the c_type inside the control * structure and copy out the data. */ - while (at < tlen) { - if ((tlen - at) < (int)CMSG_ALIGN(sizeof(cmh))) { + found = 0; + tot_len = SCTP_BUF_LEN(control); + for (off = 0; off < tot_len; off += CMSG_ALIGN(cmh.cmsg_len)) { + rem_len = tot_len - off; + if (rem_len < (int)CMSG_ALIGN(sizeof(cmh))) { /* There is not enough room for one more. */ return (found); } - m_copydata(control, at, sizeof(cmh), (caddr_t)&cmh); + m_copydata(control, off, sizeof(cmh), (caddr_t)&cmh); if (cmh.cmsg_len < CMSG_ALIGN(sizeof(cmh))) { /* We dont't have a complete CMSG header. */ return (found); } - if (((int)cmh.cmsg_len + at) > tlen) { + if ((cmh.cmsg_len > INT_MAX) || ((int)cmh.cmsg_len > rem_len)) { /* We don't have the complete CMSG. */ return (found); } + cmsg_data_len = (int)cmh.cmsg_len - CMSG_ALIGN(sizeof(cmh)); + cmsg_data_off = off + CMSG_ALIGN(sizeof(cmh)); if ((cmh.cmsg_level == IPPROTO_SCTP) && ((c_type == cmh.cmsg_type) || ((c_type == SCTP_SNDRCV) && @@ -3599,11 +3604,14 @@ (cmh.cmsg_type == SCTP_PRINFO) || (cmh.cmsg_type == SCTP_AUTHINFO))))) { if (c_type == cmh.cmsg_type) { - if ((size_t)(cmh.cmsg_len - CMSG_ALIGN(sizeof(cmh))) < cpsize) { + if (cpsize > INT_MAX) { + return (found); + } + if (cmsg_data_len < (int)cpsize) { return (found); } /* It is exactly what we want. Copy it out. */ - m_copydata(control, at + CMSG_ALIGN(sizeof(cmh)), (int)cpsize, (caddr_t)data); + m_copydata(control, cmsg_data_off, (int)cpsize, (caddr_t)data); return (1); } else { struct sctp_sndrcvinfo *sndrcvinfo; @@ -3617,10 +3625,10 @@ } switch (cmh.cmsg_type) { case SCTP_SNDINFO: - if ((size_t)(cmh.cmsg_len - CMSG_ALIGN(sizeof(cmh))) < sizeof(struct sctp_sndinfo)) { + if (cmsg_data_len < (int)sizeof(struct sctp_sndinfo)) { return (found); } - m_copydata(control, at + CMSG_ALIGN(sizeof(cmh)), sizeof(struct sctp_sndinfo), (caddr_t)&sndinfo); + m_copydata(control, cmsg_data_off, sizeof(struct sctp_sndinfo), (caddr_t)&sndinfo); sndrcvinfo->sinfo_stream = sndinfo.snd_sid; sndrcvinfo->sinfo_flags = sndinfo.snd_flags; sndrcvinfo->sinfo_ppid = sndinfo.snd_ppid; @@ -3628,10 +3636,10 @@ sndrcvinfo->sinfo_assoc_id = sndinfo.snd_assoc_id; break; case SCTP_PRINFO: - if ((size_t)(cmh.cmsg_len - CMSG_ALIGN(sizeof(cmh))) < sizeof(struct sctp_prinfo)) { + if (cmsg_data_len < (int)sizeof(struct sctp_prinfo)) { return (found); } - m_copydata(control, at + CMSG_ALIGN(sizeof(cmh)), sizeof(struct sctp_prinfo), (caddr_t)&prinfo); + m_copydata(control, cmsg_data_off, sizeof(struct sctp_prinfo), (caddr_t)&prinfo); if (prinfo.pr_policy != SCTP_PR_SCTP_NONE) { sndrcvinfo->sinfo_timetolive = prinfo.pr_value; } else { @@ -3640,10 +3648,10 @@ sndrcvinfo->sinfo_flags |= prinfo.pr_policy; break; case SCTP_AUTHINFO: - if ((size_t)(cmh.cmsg_len - CMSG_ALIGN(sizeof(cmh))) < sizeof(struct sctp_authinfo)) { + if (cmsg_data_len < (int)sizeof(struct sctp_authinfo)) { return (found); } - m_copydata(control, at + CMSG_ALIGN(sizeof(cmh)), sizeof(struct sctp_authinfo), (caddr_t)&authinfo); + m_copydata(control, cmsg_data_off, sizeof(struct sctp_authinfo), (caddr_t)&authinfo); sndrcvinfo->sinfo_keynumber_valid = 1; sndrcvinfo->sinfo_keynumber = authinfo.auth_keynumber; break; @@ -3653,7 +3661,6 @@ found = 1; } } - at += CMSG_ALIGN(cmh.cmsg_len); } return (found); } @@ -4475,16 +4482,18 @@ } #endif } else { - /* PMTU check versus smallest asoc MTU goes here */ - if ((ro->ro_rt != NULL) && - (net->ro._s_addr)) { + if ((ro->ro_rt != NULL) && (net->ro._s_addr) && + ((net->dest_state & SCTP_ADDR_NO_PMTUD) == 0)) { uint32_t mtu; + mtu = SCTP_GATHER_MTU_FROM_ROUTE(net->ro._s_addr, &net->ro._l_addr.sa, ro->ro_rt); - if (net->port) { - mtu -= sizeof(struct udphdr); - } - if (mtu && (stcb->asoc.smallest_mtu > mtu)) { - sctp_mtu_size_reset(inp, &stcb->asoc, mtu); + if (mtu > 0) { + if (net->port) { + mtu -= sizeof(struct udphdr); + } + if ((stcb != NULL) && (stcb->asoc.smallest_mtu > mtu)) { + sctp_mtu_size_reset(inp, &stcb->asoc, mtu); + } net->mtu = mtu; } } else if (ro->ro_rt == NULL) { @@ -4943,17 +4952,19 @@ } net->src_addr_selected = 0; } - if ((ro->ro_rt != NULL) && - (net->ro._s_addr)) { + if ((ro->ro_rt != NULL) && (net->ro._s_addr) && + ((net->dest_state & SCTP_ADDR_NO_PMTUD) == 0)) { uint32_t mtu; + mtu = SCTP_GATHER_MTU_FROM_ROUTE(net->ro._s_addr, &net->ro._l_addr.sa, ro->ro_rt); - if (mtu && - (stcb->asoc.smallest_mtu > mtu)) { - sctp_mtu_size_reset(inp, &stcb->asoc, mtu); - net->mtu = mtu; + if (mtu > 0) { if (net->port) { - net->mtu -= sizeof(struct udphdr); + mtu -= sizeof(struct udphdr); } + if ((stcb != NULL) && (stcb->asoc.smallest_mtu > mtu)) { + sctp_mtu_size_reset(inp, &stcb->asoc, mtu); + } + net->mtu = mtu; } } #if !defined(__Panda__) && !defined(__Userspace__) @@ -5904,7 +5915,7 @@ #if defined(__FreeBSD__) uint8_t mflowtype, uint32_t mflowid, #endif - uint32_t vrf_id, uint16_t port, int hold_inp_lock) + uint32_t vrf_id, uint16_t port) { struct sctp_association *asoc; struct mbuf *m, *m_tmp, *m_last, *m_cookie, *op_err; @@ -5914,6 +5925,7 @@ struct sctp_paramhdr *ph; union sctp_sockstore *over_addr; struct sctp_scoping scp; + struct timeval now; #ifdef INET struct sockaddr_in *dst4 = (struct sockaddr_in *)dst; struct sockaddr_in *src4 = (struct sockaddr_in *)src; @@ -6024,7 +6036,9 @@ memset(&stc, 0, sizeof(struct sctp_state_cookie)); /* the time I built cookie */ - (void)SCTP_GETTIME_TIMEVAL(&stc.time_entered); + (void)SCTP_GETTIME_TIMEVAL(&now); + stc.time_entered.tv_sec = now.tv_sec; + stc.time_entered.tv_usec = now.tv_usec; /* populate any tie tags */ if (asoc != NULL) { @@ -6317,10 +6331,7 @@ initack->init.initial_tsn = htonl(asoc->init_seq_number); } else { uint32_t vtag, itsn; - if (hold_inp_lock) { - SCTP_INP_INCR_REF(inp); - SCTP_INP_RUNLOCK(inp); - } + if (asoc) { atomic_add_int(&asoc->refcnt, 1); SCTP_TCB_UNLOCK(stcb); @@ -6339,12 +6350,12 @@ SCTP_TCB_LOCK(stcb); atomic_add_int(&asoc->refcnt, -1); } else { + SCTP_INP_INCR_REF(inp); + SCTP_INP_RUNLOCK(inp); vtag = sctp_select_a_tag(inp, inp->sctp_lport, sh->src_port, 1); initack->init.initiate_tag = htonl(vtag); /* get a TSN to use too */ initack->init.initial_tsn = htonl(sctp_select_initial_TSN(&inp->sctp_ep)); - } - if (hold_inp_lock) { SCTP_INP_RLOCK(inp); SCTP_INP_DECR_REF(inp); } @@ -6737,7 +6748,15 @@ if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) { ovh = SCTP_MIN_OVERHEAD; } else { +#if defined(__Userspace__) + if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUND_CONN) { + ovh = sizeof(struct sctphdr); + } else { + ovh = SCTP_MIN_V4_OVERHEAD; + } +#else ovh = SCTP_MIN_V4_OVERHEAD; +#endif } ovh += SCTP_DATA_CHUNK_OVERHEAD(stcb); if (stcb->asoc.sctp_frag_point > asoc->smallest_mtu) @@ -8445,7 +8464,7 @@ sctp_log_cwnd(stcb, net, 1, SCTP_CWND_LOG_FILL_OUTQ_CALLED); } - continue; + continue; } if ((stcb->asoc.cc_functions.sctp_cwnd_new_transmission_begins) && (net->flight_size == 0)) { @@ -13317,10 +13336,9 @@ sp->sender_all_done = 0; sp->some_taken = 0; sp->put_last_out = 0; - resv_in_first = SCTP_DATA_CHUNK_OVERHEAD(stcb); + resv_in_first = SCTP_DATA_CHUNK_OVERHEAD(stcb); sp->data = sp->tail_mbuf = NULL; if (sp->length == 0) { - *error = 0; goto skip_copy; } if (srcv->sinfo_keynumber_valid) { @@ -13341,7 +13359,13 @@ #endif skip_copy: if (*error) { +#if defined(__Userspace__) + SCTP_TCB_LOCK(stcb); +#endif sctp_free_a_strmoq(stcb, sp, SCTP_SO_LOCKED); +#if defined(__Userspace__) + SCTP_TCB_UNLOCK(stcb); +#endif sp = NULL; } else { if (sp->sinfo_flags & SCTP_ADDR_OVER) { @@ -14204,7 +14228,7 @@ if (strm->last_msg_incomplete == 0) { do_a_copy_in: sp = sctp_copy_it_in(stcb, asoc, srcv, uio, net, max_len, user_marks_eor, &error); - if ((sp == NULL) || (error)) { + if (error) { goto out; } SCTP_TCB_SEND_LOCK(stcb);
diff --git a/usrsctplib/netinet/sctp_output.h b/usrsctplib/netinet/sctp_output.h index dfae447..597ddc3 100755 --- a/usrsctplib/netinet/sctp_output.h +++ b/usrsctplib/netinet/sctp_output.h
@@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved. * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved. * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved. @@ -32,7 +34,7 @@ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_output.h 321034 2017-07-15 19:54:03Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp_output.h 323861 2017-09-21 11:56:31Z tuexen $"); #endif #ifndef _NETINET_SCTP_OUTPUT_H_ @@ -91,7 +93,7 @@ #if defined(__FreeBSD__) uint8_t, uint32_t, #endif - uint32_t, uint16_t, int); + uint32_t, uint16_t); struct mbuf * sctp_arethere_unrecognized_parameters(struct mbuf *, int, int *,
diff --git a/usrsctplib/netinet/sctp_pcb.c b/usrsctplib/netinet/sctp_pcb.c index 9e9fca0..2bde696 100755 --- a/usrsctplib/netinet/sctp_pcb.c +++ b/usrsctplib/netinet/sctp_pcb.c
@@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 2001-2008, by Cisco Systems, Inc. All rights reserved. * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved. * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved. @@ -32,7 +34,7 @@ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_pcb.c 321204 2017-07-19 14:28:58Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp_pcb.c 325370 2017-11-03 20:46:12Z tuexen $"); #endif #include <netinet/sctp_os.h> @@ -801,12 +803,11 @@ SCTP_WQ_ADDR_LOCK(); LIST_INSERT_HEAD(&SCTP_BASE_INFO(addr_wq), wi, sctp_nxt_addr); - SCTP_WQ_ADDR_UNLOCK(); - sctp_timer_start(SCTP_TIMER_TYPE_ADDR_WQ, (struct sctp_inpcb *)NULL, (struct sctp_tcb *)NULL, (struct sctp_nets *)NULL); + SCTP_WQ_ADDR_UNLOCK(); } else { /* it's ready for use */ sctp_ifap->localifa_flags &= ~SCTP_ADDR_DEFER_USE; @@ -912,12 +913,11 @@ * newest first :-0 */ LIST_INSERT_HEAD(&SCTP_BASE_INFO(addr_wq), wi, sctp_nxt_addr); - SCTP_WQ_ADDR_UNLOCK(); - sctp_timer_start(SCTP_TIMER_TYPE_ADDR_WQ, (struct sctp_inpcb *)NULL, (struct sctp_tcb *)NULL, (struct sctp_nets *)NULL); + SCTP_WQ_ADDR_UNLOCK(); } return; } @@ -2877,16 +2877,16 @@ inp->sctp_flags = (SCTP_PCB_FLAGS_TCPTYPE | SCTP_PCB_FLAGS_UNBOUND); /* Be sure we have blocking IO by default */ + SOCK_LOCK(so); SCTP_CLEAR_SO_NBIO(so); + SOCK_UNLOCK(so); #if defined(__Panda__) } else if (SCTP_SO_TYPE(so) == SOCK_FASTSEQPACKET) { inp->sctp_flags = (SCTP_PCB_FLAGS_UDPTYPE | SCTP_PCB_FLAGS_UNBOUND); - sctp_feature_on(inp, SCTP_PCB_FLAGS_ZERO_COPY_ACTIVE); } else if (SCTP_SO_TYPE(so) == SOCK_FASTSTREAM) { inp->sctp_flags = (SCTP_PCB_FLAGS_TCPTYPE | SCTP_PCB_FLAGS_UNBOUND); - sctp_feature_on(inp, SCTP_PCB_FLAGS_ZERO_COPY_ACTIVE); #endif } else { /* @@ -3030,6 +3030,7 @@ /* number of streams to pre-open on a association */ m->pre_open_stream_count = SCTP_BASE_SYSCTL(sctp_nr_outgoing_streams_default); + m->default_mtu = 0; /* Add adaptation cookie */ m->adaptation_layer_indicator = 0; m->adaptation_layer_indicator_provided = 0; @@ -3445,7 +3446,7 @@ /* got to be root to get at low ports */ #if !defined(__Windows__) if (ntohs(lport) < IPPORT_RESERVED) { - if (p && (error = + if ((p != NULL) && ((error = #ifdef __FreeBSD__ #if __FreeBSD_version > 602000 priv_check(p, PRIV_NETINET_RESERVEDPORT) @@ -3461,7 +3462,7 @@ #else suser(p, 0) #endif - )) { + ) != 0)) { SCTP_INP_DECR_REF(inp); SCTP_INP_WUNLOCK(inp); SCTP_INP_INFO_WUNLOCK(); @@ -4199,18 +4200,6 @@ #endif #endif -#if defined(__Panda__) - if (inp->pak_to_read) { - (void)SCTP_OS_TIMER_STOP(&inp->sctp_ep.zero_copy_timer.timer); - SCTP_RELEASE_PKT(inp->pak_to_read); - inp->pak_to_read = NULL; - } - if (inp->pak_to_read_sendq) { - (void)SCTP_OS_TIMER_STOP(&inp->sctp_ep.zero_copy_sendq_timer.timer); - SCTP_RELEASE_PKT(inp->pak_to_read_sendq); - inp->pak_to_read_sendq = NULL; - } -#endif if ((inp->sctp_asocidhash) != NULL) { SCTP_HASH_FREE(inp->sctp_asocidhash, inp->hashasocidmark); inp->sctp_asocidhash = NULL; @@ -4656,7 +4645,33 @@ net, 0, stcb->asoc.vrf_id); - if (net->ro._s_addr != NULL) { + if (stcb->asoc.default_mtu > 0) { + net->mtu = stcb->asoc.default_mtu; + switch (net->ro._l_addr.sa.sa_family) { +#ifdef INET + case AF_INET: + net->mtu += SCTP_MIN_V4_OVERHEAD; + break; +#endif +#ifdef INET6 + case AF_INET6: + net->mtu += SCTP_MIN_OVERHEAD; + break; +#endif +#if defined(__Userspace__) + case AF_CONN: + net->mtu += sizeof(struct sctphdr); + break; +#endif + default: + break; + } +#if defined(INET) || defined(INET6) + if (net->port) { + net->mtu += (uint32_t)sizeof(struct udphdr); + } +#endif + } else if (net->ro._s_addr != NULL) { uint32_t imtu, rmtu, hcmtu; net->src_addr_selected = 1; @@ -4682,24 +4697,52 @@ } #endif if (net->mtu == 0) { - switch (newaddr->sa_family) { + if (stcb->asoc.default_mtu > 0) { + net->mtu = stcb->asoc.default_mtu; + switch (net->ro._l_addr.sa.sa_family) { #ifdef INET - case AF_INET: - net->mtu = SCTP_DEFAULT_MTU; - break; + case AF_INET: + net->mtu += SCTP_MIN_V4_OVERHEAD; + break; #endif #ifdef INET6 - case AF_INET6: - net->mtu = 1280; - break; + case AF_INET6: + net->mtu += SCTP_MIN_OVERHEAD; + break; #endif #if defined(__Userspace__) - case AF_CONN: - net->mtu = 1280; - break; + case AF_CONN: + net->mtu += sizeof(struct sctphdr); + break; #endif - default: - break; + default: + break; + } +#if defined(INET) || defined(INET6) + if (net->port) { + net->mtu += (uint32_t)sizeof(struct udphdr); + } +#endif + } else { + switch (newaddr->sa_family) { +#ifdef INET + case AF_INET: + net->mtu = SCTP_DEFAULT_MTU; + break; +#endif +#ifdef INET6 + case AF_INET6: + net->mtu = 1280; + break; +#endif +#if defined(__Userspace__) + case AF_CONN: + net->mtu = 1280; + break; +#endif + default: + break; + } } } #if defined(INET) || defined(INET6)
diff --git a/usrsctplib/netinet/sctp_pcb.h b/usrsctplib/netinet/sctp_pcb.h index b938625..47aaa24 100755 --- a/usrsctplib/netinet/sctp_pcb.h +++ b/usrsctplib/netinet/sctp_pcb.h
@@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved. * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved. * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved. @@ -32,7 +34,7 @@ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_pcb.h 310590 2016-12-26 11:06:41Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp_pcb.h 325370 2017-11-03 20:46:12Z tuexen $"); #endif #ifndef _NETINET_SCTP_PCB_H_ @@ -373,6 +375,7 @@ sctp_auth_chklist_t *local_auth_chunks; sctp_hmaclist_t *local_hmacs; uint16_t default_keyid; + uint32_t default_mtu; /* various thresholds */ /* Max times I will init at a guy */ @@ -400,10 +403,6 @@ */ struct sctp_timer signature_change; - /* Zero copy full buffer timer */ - struct sctp_timer zero_copy_timer; - /* Zero copy app to transport (sendq) read repulse timer */ - struct sctp_timer zero_copy_sendq_timer; uint32_t def_cookie_life; /* defaults to 0 */ int auto_close_time;
diff --git a/usrsctplib/netinet/sctp_peeloff.c b/usrsctplib/netinet/sctp_peeloff.c index 7c55aa3..391b4f5 100755 --- a/usrsctplib/netinet/sctp_peeloff.c +++ b/usrsctplib/netinet/sctp_peeloff.c
@@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved. * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved. * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved. @@ -280,8 +282,10 @@ SCTP_FROM_SCTP_PEELOFF + SCTP_LOC_1); } /* Turn off any non-blocking semantic. */ + SOCK_LOCK(newso); SCTP_CLEAR_SO_NBIO(newso); - newso->so_state |= SS_ISCONNECTED; + newso->so_state |= SS_ISCONNECTED; + SOCK_UNLOCK(newso); /* We remove it right away */ #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__) || defined(__Userspace__) @@ -294,7 +298,7 @@ head->so_qlen--; SOCK_UNLOCK(head); #else - newso = TAILQ_FIRST(&head->so_q); + newso = TAILQ_FIRST(&head->so_q); if (soqremque(newso, 1) == 0) { SCTP_PRINTF("soremque failed, peeloff-fails (invarients would panic)\n"); SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PEELOFF, ENOTCONN); @@ -307,7 +311,7 @@ * Now we must move it from one hash table to another and get the * stcb in the right place. */ - sctp_move_pcb_and_assoc(inp, n_inp, stcb); + sctp_move_pcb_and_assoc(inp, n_inp, stcb); atomic_add_int(&stcb->asoc.refcnt, 1); SCTP_TCB_UNLOCK(stcb); /*
diff --git a/usrsctplib/netinet/sctp_peeloff.h b/usrsctplib/netinet/sctp_peeloff.h index 22375e3..adefcde 100755 --- a/usrsctplib/netinet/sctp_peeloff.h +++ b/usrsctplib/netinet/sctp_peeloff.h
@@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved. * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved. * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
diff --git a/usrsctplib/netinet/sctp_process_lock.h b/usrsctplib/netinet/sctp_process_lock.h index 1d10985..ca66921 100755 --- a/usrsctplib/netinet/sctp_process_lock.h +++ b/usrsctplib/netinet/sctp_process_lock.h
@@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved. * Copyright (c) 2008-2011, by Randall Stewart. All rights reserved. * Copyright (c) 2008-2011, by Michael Tuexen. All rights reserved. @@ -115,13 +117,13 @@ #if defined(__Userspace_os_Windows) #define SCTP_WQ_ADDR_INIT() \ - InitializeCriticalSection(&SCTP_BASE_INFO(wq_addr_mtx)) + InitializeCriticalSection(&SCTP_BASE_INFO(wq_addr_mtx)) #define SCTP_WQ_ADDR_DESTROY() \ DeleteCriticalSection(&SCTP_BASE_INFO(wq_addr_mtx)) #define SCTP_WQ_ADDR_LOCK() \ - EnterCriticalSection(&SCTP_BASE_INFO(wq_addr_mtx)) + EnterCriticalSection(&SCTP_BASE_INFO(wq_addr_mtx)) #define SCTP_WQ_ADDR_UNLOCK() \ - LeaveCriticalSection(&SCTP_BASE_INFO(wq_addr_mtx)) + LeaveCriticalSection(&SCTP_BASE_INFO(wq_addr_mtx)) #define SCTP_INP_INFO_LOCK_INIT() \ @@ -131,20 +133,20 @@ #define SCTP_INP_INFO_RLOCK() \ EnterCriticalSection(&SCTP_BASE_INFO(ipi_ep_mtx)) #define SCTP_INP_INFO_TRYLOCK() \ - TryEnterCriticalSection(&SCTP_BASE_INFO(ipi_ep_mtx)) + TryEnterCriticalSection(&SCTP_BASE_INFO(ipi_ep_mtx)) #define SCTP_INP_INFO_WLOCK() \ EnterCriticalSection(&SCTP_BASE_INFO(ipi_ep_mtx)) #define SCTP_INP_INFO_RUNLOCK() \ - LeaveCriticalSection(&SCTP_BASE_INFO(ipi_ep_mtx)) + LeaveCriticalSection(&SCTP_BASE_INFO(ipi_ep_mtx)) #define SCTP_INP_INFO_WUNLOCK() \ LeaveCriticalSection(&SCTP_BASE_INFO(ipi_ep_mtx)) #define SCTP_IP_PKTLOG_INIT() \ - InitializeCriticalSection(&SCTP_BASE_INFO(ipi_pktlog_mtx)) + InitializeCriticalSection(&SCTP_BASE_INFO(ipi_pktlog_mtx)) #define SCTP_IP_PKTLOG_DESTROY () \ DeleteCriticalSection(&SCTP_BASE_INFO(ipi_pktlog_mtx)) #define SCTP_IP_PKTLOG_LOCK() \ - EnterCriticalSection(&SCTP_BASE_INFO(ipi_pktlog_mtx)) + EnterCriticalSection(&SCTP_BASE_INFO(ipi_pktlog_mtx)) #define SCTP_IP_PKTLOG_UNLOCK() \ LeaveCriticalSection(&SCTP_BASE_INFO(ipi_pktlog_mtx)) @@ -164,63 +166,51 @@ #define SCTP_INP_LOCK_INIT(_inp) \ InitializeCriticalSection(&(_inp)->inp_mtx) - -#define SCTP_ASOC_CREATE_LOCK_INIT(_inp) \ - InitializeCriticalSection(&(_inp)->inp_create_mtx) - #define SCTP_INP_LOCK_DESTROY(_inp) \ DeleteCriticalSection(&(_inp)->inp_mtx) - -#define SCTP_ASOC_CREATE_LOCK_DESTROY(_inp) \ - DeleteCriticalSection(&(_inp)->inp_create_mtx) - #ifdef SCTP_LOCK_LOGGING -#define SCTP_INP_RLOCK(_inp) do { \ - if(SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOCK_LOGGING_ENABLE) sctp_log_lock(_inp, (struct sctp_tcb *)NULL, SCTP_LOG_LOCK_INP);\ - EnterCriticalSection(&(_inp)->inp_mtx); \ +#define SCTP_INP_RLOCK(_inp) do { \ + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOCK_LOGGING_ENABLE) \ + sctp_log_lock(_inp, NULL, SCTP_LOG_LOCK_INP); \ + EnterCriticalSection(&(_inp)->inp_mtx); \ } while (0) - -#define SCTP_INP_WLOCK(_inp) do { \ - sctp_log_lock(_inp, (struct sctp_tcb *)NULL, SCTP_LOG_LOCK_INP);\ - EnterCriticalSection(&(_inp)->inp_mtx); \ +#define SCTP_INP_WLOCK(_inp) do { \ + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOCK_LOGGING_ENABLE) \ + sctp_log_lock(_inp, NULL, SCTP_LOG_LOCK_INP); \ + EnterCriticalSection(&(_inp)->inp_mtx); \ } while (0) #else - -#define SCTP_INP_RLOCK(_inp) do { \ - EnterCriticalSection(&(_inp)->inp_mtx); \ -} while (0) - -#define SCTP_INP_WLOCK(_inp) do { \ - EnterCriticalSection(&(_inp)->inp_mtx); \ -} while (0) +#define SCTP_INP_RLOCK(_inp) \ + EnterCriticalSection(&(_inp)->inp_mtx) +#define SCTP_INP_WLOCK(_inp) \ + EnterCriticalSection(&(_inp)->inp_mtx) #endif - #define SCTP_TCB_SEND_LOCK_INIT(_tcb) \ InitializeCriticalSection(&(_tcb)->tcb_send_mtx) - #define SCTP_TCB_SEND_LOCK_DESTROY(_tcb) \ DeleteCriticalSection(&(_tcb)->tcb_send_mtx) - -#define SCTP_TCB_SEND_LOCK(_tcb) do { \ - EnterCriticalSection(&(_tcb)->tcb_send_mtx); \ -} while (0) - +#define SCTP_TCB_SEND_LOCK(_tcb) \ + EnterCriticalSection(&(_tcb)->tcb_send_mtx) #define SCTP_TCB_SEND_UNLOCK(_tcb) \ LeaveCriticalSection(&(_tcb)->tcb_send_mtx) #define SCTP_INP_INCR_REF(_inp) atomic_add_int(&((_inp)->refcount), 1) #define SCTP_INP_DECR_REF(_inp) atomic_add_int(&((_inp)->refcount), -1) +#define SCTP_ASOC_CREATE_LOCK_INIT(_inp) \ + InitializeCriticalSection(&(_inp)->inp_create_mtx) +#define SCTP_ASOC_CREATE_LOCK_DESTROY(_inp) \ + DeleteCriticalSection(&(_inp)->inp_create_mtx) #ifdef SCTP_LOCK_LOGGING -#define SCTP_ASOC_CREATE_LOCK(_inp) do { \ - if(SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOCK_LOGGING_ENABLE) sctp_log_lock(_inp, (struct sctp_tcb *)NULL, SCTP_LOG_LOCK_CREATE); \ - EnterCriticalSection(&(_inp)->inp_create_mtx); \ +#define SCTP_ASOC_CREATE_LOCK(_inp) do { \ + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOCK_LOGGING_ENABLE) \ + sctp_log_lock(_inp, NULL, SCTP_LOG_LOCK_CREATE); \ + EnterCriticalSection(&(_inp)->inp_create_mtx); \ } while (0) #else -#define SCTP_ASOC_CREATE_LOCK(_inp) do { \ - EnterCriticalSection(&(_inp)->inp_create_mtx); \ -} while (0) +#define SCTP_ASOC_CREATE_LOCK(_inp) \ + EnterCriticalSection(&(_inp)->inp_create_mtx) #endif #define SCTP_INP_RUNLOCK(_inp) \ @@ -240,65 +230,81 @@ #define SCTP_TCB_LOCK_INIT(_tcb) \ InitializeCriticalSection(&(_tcb)->tcb_mtx) - #define SCTP_TCB_LOCK_DESTROY(_tcb) \ DeleteCriticalSection(&(_tcb)->tcb_mtx) - #ifdef SCTP_LOCK_LOGGING -#define SCTP_TCB_LOCK(_tcb) do { \ - if(SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOCK_LOGGING_ENABLE) sctp_log_lock(_tcb->sctp_ep, _tcb, SCTP_LOG_LOCK_TCB); \ - EnterCriticalSection(&(_tcb)->tcb_mtx); \ +#define SCTP_TCB_LOCK(_tcb) do { \ + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOCK_LOGGING_ENABLE) \ + sctp_log_lock(_tcb->sctp_ep, _tcb, SCTP_LOG_LOCK_TCB); \ + EnterCriticalSection(&(_tcb)->tcb_mtx); \ } while (0) - #else -#define SCTP_TCB_LOCK(_tcb) do { \ - EnterCriticalSection(&(_tcb)->tcb_mtx); \ -} while (0) +#define SCTP_TCB_LOCK(_tcb) \ + EnterCriticalSection(&(_tcb)->tcb_mtx) #endif - #define SCTP_TCB_TRYLOCK(_tcb) ((TryEnterCriticalSection(&(_tcb)->tcb_mtx))) - -#define SCTP_TCB_UNLOCK(_tcb) do { \ - LeaveCriticalSection(&(_tcb)->tcb_mtx); \ -} while (0) - +#define SCTP_TCB_UNLOCK(_tcb) \ + LeaveCriticalSection(&(_tcb)->tcb_mtx) #define SCTP_TCB_LOCK_ASSERT(_tcb) #else /* all Userspaces except Windows */ #define SCTP_WQ_ADDR_INIT() \ - (void)pthread_mutex_init(&SCTP_BASE_INFO(wq_addr_mtx), NULL) + (void)pthread_mutex_init(&SCTP_BASE_INFO(wq_addr_mtx), &SCTP_BASE_VAR(mtx_attr)) #define SCTP_WQ_ADDR_DESTROY() \ (void)pthread_mutex_destroy(&SCTP_BASE_INFO(wq_addr_mtx)) +#ifdef INVARIANTS #define SCTP_WQ_ADDR_LOCK() \ - (void)pthread_mutex_lock(&SCTP_BASE_INFO(wq_addr_mtx)) + KASSERT(pthread_mutex_lock(&SCTP_BASE_INFO(wq_addr_mtx)) == 0, ("%s: wq_addr_mtx already locked", __func__)) #define SCTP_WQ_ADDR_UNLOCK() \ - (void)pthread_mutex_unlock(&SCTP_BASE_INFO(wq_addr_mtx)) - + KASSERT(pthread_mutex_unlock(&SCTP_BASE_INFO(wq_addr_mtx)) == 0, ("%s: wq_addr_mtx not locked", __func__)) +#else +#define SCTP_WQ_ADDR_LOCK() \ + (void)pthread_mutex_lock(&SCTP_BASE_INFO(wq_addr_mtx)) +#define SCTP_WQ_ADDR_UNLOCK() \ + (void)pthread_mutex_unlock(&SCTP_BASE_INFO(wq_addr_mtx)) +#endif #define SCTP_INP_INFO_LOCK_INIT() \ - (void)pthread_mutex_init(&SCTP_BASE_INFO(ipi_ep_mtx), NULL) + (void)pthread_mutex_init(&SCTP_BASE_INFO(ipi_ep_mtx), &SCTP_BASE_VAR(mtx_attr)) #define SCTP_INP_INFO_LOCK_DESTROY() \ (void)pthread_mutex_destroy(&SCTP_BASE_INFO(ipi_ep_mtx)) +#ifdef INVARIANTS +#define SCTP_INP_INFO_RLOCK() \ + KASSERT(pthread_mutex_lock(&SCTP_BASE_INFO(ipi_ep_mtx)) == 0, ("%s: ipi_ep_mtx already locked", __func__)) +#define SCTP_INP_INFO_WLOCK() \ + KASSERT(pthread_mutex_lock(&SCTP_BASE_INFO(ipi_ep_mtx)) == 0, ("%s: ipi_ep_mtx already locked", __func__)) +#define SCTP_INP_INFO_RUNLOCK() \ + KASSERT(pthread_mutex_unlock(&SCTP_BASE_INFO(ipi_ep_mtx)) == 0, ("%s: ipi_ep_mtx not locked", __func__)) +#define SCTP_INP_INFO_WUNLOCK() \ + KASSERT(pthread_mutex_unlock(&SCTP_BASE_INFO(ipi_ep_mtx)) == 0, ("%s: ipi_ep_mtx not locked", __func__)) +#else #define SCTP_INP_INFO_RLOCK() \ (void)pthread_mutex_lock(&SCTP_BASE_INFO(ipi_ep_mtx)) -#define SCTP_INP_INFO_TRYLOCK() \ - (!(pthread_mutex_trylock(&SCTP_BASE_INFO(ipi_ep_mtx)))) #define SCTP_INP_INFO_WLOCK() \ (void)pthread_mutex_lock(&SCTP_BASE_INFO(ipi_ep_mtx)) -#define SCTP_INP_INFO_RUNLOCK() \ +#define SCTP_INP_INFO_RUNLOCK() \ (void)pthread_mutex_unlock(&SCTP_BASE_INFO(ipi_ep_mtx)) -#define SCTP_INP_INFO_WUNLOCK() \ +#define SCTP_INP_INFO_WUNLOCK() \ (void)pthread_mutex_unlock(&SCTP_BASE_INFO(ipi_ep_mtx)) +#endif +#define SCTP_INP_INFO_TRYLOCK() \ + (!(pthread_mutex_trylock(&SCTP_BASE_INFO(ipi_ep_mtx)))) #define SCTP_IP_PKTLOG_INIT() \ - (void)pthread_mutex_init(&SCTP_BASE_INFO(ipi_pktlog_mtx), NULL) + (void)pthread_mutex_init(&SCTP_BASE_INFO(ipi_pktlog_mtx), &SCTP_BASE_VAR(mtx_attr)) #define SCTP_IP_PKTLOG_DESTROY() \ (void)pthread_mutex_destroy(&SCTP_BASE_INFO(ipi_pktlog_mtx)) +#ifdef INVARIANTS #define SCTP_IP_PKTLOG_LOCK() \ - (void)pthread_mutex_lock(&SCTP_BASE_INFO(ipi_pktlog_mtx)) -#define SCTP_IP_PKTLOG_UNLOCK() \ - (void)pthread_mutex_unlock(&SCTP_BASE_INFO(ipi_pktlog_mtx)) - + KASSERT(pthread_mutex_lock(&SCTP_BASE_INFO(ipi_pktlog_mtx)) == 0, ("%s: ipi_pktlog_mtx already locked", __func__)) +#define SCTP_IP_PKTLOG_UNLOCK() \ + KASSERT(pthread_mutex_unlock(&SCTP_BASE_INFO(ipi_pktlog_mtx)) == 0, ("%s: ipi_pktlog_mtx not locked", __func__)) +#else +#define SCTP_IP_PKTLOG_LOCK() \ + (void)pthread_mutex_lock(&SCTP_BASE_INFO(ipi_pktlog_mtx)) +#define SCTP_IP_PKTLOG_UNLOCK() \ + (void)pthread_mutex_unlock(&SCTP_BASE_INFO(ipi_pktlog_mtx)) +#endif /* @@ -307,88 +313,120 @@ * or cookie secrets we lock the INP level. */ #define SCTP_INP_READ_INIT(_inp) \ - (void)pthread_mutex_init(&(_inp)->inp_rdata_mtx, NULL) - + (void)pthread_mutex_init(&(_inp)->inp_rdata_mtx, &SCTP_BASE_VAR(mtx_attr)) #define SCTP_INP_READ_DESTROY(_inp) \ (void)pthread_mutex_destroy(&(_inp)->inp_rdata_mtx) - -#define SCTP_INP_READ_LOCK(_inp) do { \ - (void)pthread_mutex_lock(&(_inp)->inp_rdata_mtx); \ -} while (0) - - +#ifdef INVARIANTS +#define SCTP_INP_READ_LOCK(_inp) \ + KASSERT(pthread_mutex_lock(&(_inp)->inp_rdata_mtx) == 0, ("%s: inp_rdata_mtx already locked", __func__)) +#define SCTP_INP_READ_UNLOCK(_inp) \ + KASSERT(pthread_mutex_unlock(&(_inp)->inp_rdata_mtx) == 0, ("%s: inp_rdata_mtx not locked", __func__)) +#else +#define SCTP_INP_READ_LOCK(_inp) \ + (void)pthread_mutex_lock(&(_inp)->inp_rdata_mtx) #define SCTP_INP_READ_UNLOCK(_inp) \ (void)pthread_mutex_unlock(&(_inp)->inp_rdata_mtx) +#endif #define SCTP_INP_LOCK_INIT(_inp) \ - (void)pthread_mutex_init(&(_inp)->inp_mtx, NULL) - -#define SCTP_ASOC_CREATE_LOCK_INIT(_inp) \ - (void)pthread_mutex_init(&(_inp)->inp_create_mtx, NULL) - + (void)pthread_mutex_init(&(_inp)->inp_mtx, &SCTP_BASE_VAR(mtx_attr)) #define SCTP_INP_LOCK_DESTROY(_inp) \ (void)pthread_mutex_destroy(&(_inp)->inp_mtx) - -#define SCTP_ASOC_CREATE_LOCK_DESTROY(_inp) \ - (void)pthread_mutex_destroy(&(_inp)->inp_create_mtx) - +#ifdef INVARIANTS #ifdef SCTP_LOCK_LOGGING -#define SCTP_INP_RLOCK(_inp) do { \ - if(SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOCK_LOGGING_ENABLE) sctp_log_lock(_inp, (struct sctp_tcb *)NULL, SCTP_LOG_LOCK_INP);\ - (void)pthread_mutex_lock(&(_inp)->inp_mtx); \ +#define SCTP_INP_RLOCK(_inp) do { \ + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOCK_LOGGING_ENABLE) \ + sctp_log_lock(_inp, NULL, SCTP_LOG_LOCK_INP); \ + KASSERT(pthread_mutex_lock(&(_inp)->inp_mtx) == 0, ("%s: inp_mtx already locked", __func__)) \ } while (0) - -#define SCTP_INP_WLOCK(_inp) do { \ - sctp_log_lock(_inp, (struct sctp_tcb *)NULL, SCTP_LOG_LOCK_INP);\ - (void)pthread_mutex_lock(&(_inp)->inp_mtx); \ -} while (0) - -#else - -#define SCTP_INP_RLOCK(_inp) do { \ - (void)pthread_mutex_lock(&(_inp)->inp_mtx); \ -} while (0) - -#define SCTP_INP_WLOCK(_inp) do { \ - (void)pthread_mutex_lock(&(_inp)->inp_mtx); \ -} while (0) -#endif - - -#define SCTP_TCB_SEND_LOCK_INIT(_tcb) \ - (void)pthread_mutex_init(&(_tcb)->tcb_send_mtx, NULL) - -#define SCTP_TCB_SEND_LOCK_DESTROY(_tcb) \ - (void)pthread_mutex_destroy(&(_tcb)->tcb_send_mtx) - -#define SCTP_TCB_SEND_LOCK(_tcb) do { \ - (void)pthread_mutex_lock(&(_tcb)->tcb_send_mtx); \ -} while (0) - -#define SCTP_TCB_SEND_UNLOCK(_tcb) \ - (void)pthread_mutex_unlock(&(_tcb)->tcb_send_mtx) - -#define SCTP_INP_INCR_REF(_inp) atomic_add_int(&((_inp)->refcount), 1) -#define SCTP_INP_DECR_REF(_inp) atomic_add_int(&((_inp)->refcount), -1) - -#ifdef SCTP_LOCK_LOGGING -#define SCTP_ASOC_CREATE_LOCK(_inp) do { \ - if(SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOCK_LOGGING_ENABLE) sctp_log_lock(_inp, (struct sctp_tcb *)NULL, SCTP_LOG_LOCK_CREATE); \ - (void)pthread_mutex_lock(&(_inp)->inp_create_mtx); \ +#define SCTP_INP_WLOCK(_inp) do { \ + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOCK_LOGGING_ENABLE) \ + sctp_log_lock(_inp, NULL, SCTP_LOG_LOCK_INP); \ + KASSERT(pthread_mutex_lock(&(_inp)->inp_mtx) == 0, ("%s: inp_mtx already locked", __func__)) } while (0) #else -#define SCTP_ASOC_CREATE_LOCK(_inp) do { \ - (void)pthread_mutex_lock(&(_inp)->inp_create_mtx); \ -} while (0) +#define SCTP_INP_RLOCK(_inp) \ + KASSERT(pthread_mutex_lock(&(_inp)->inp_mtx) == 0, ("%s: inp_mtx already locked", __func__)) +#define SCTP_INP_WLOCK(_inp) \ + KASSERT(pthread_mutex_lock(&(_inp)->inp_mtx) == 0, ("%s: inp_mtx already locked", __func__)) #endif - +#define SCTP_INP_RUNLOCK(_inp) \ + KASSERT(pthread_mutex_unlock(&(_inp)->inp_mtx) == 0, ("%s: inp_mtx not locked", __func__)) +#define SCTP_INP_WUNLOCK(_inp) \ + KASSERT(pthread_mutex_unlock(&(_inp)->inp_mtx) == 0, ("%s: inp_mtx not locked", __func__)) +#else +#ifdef SCTP_LOCK_LOGGING +#define SCTP_INP_RLOCK(_inp) do { \ + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOCK_LOGGING_ENABLE) \ + sctp_log_lock(_inp, NULL, SCTP_LOG_LOCK_INP); \ + (void)pthread_mutex_lock(&(_inp)->inp_mtx); \ +} while (0) +#define SCTP_INP_WLOCK(_inp) do { \ + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOCK_LOGGING_ENABLE) \ + sctp_log_lock(_inp, NULL, SCTP_LOG_LOCK_INP); \ + (void)pthread_mutex_lock(&(_inp)->inp_mtx); \ +} while (0) +#else +#define SCTP_INP_RLOCK(_inp) \ + (void)pthread_mutex_lock(&(_inp)->inp_mtx) +#define SCTP_INP_WLOCK(_inp) \ + (void)pthread_mutex_lock(&(_inp)->inp_mtx) +#endif #define SCTP_INP_RUNLOCK(_inp) \ (void)pthread_mutex_unlock(&(_inp)->inp_mtx) #define SCTP_INP_WUNLOCK(_inp) \ (void)pthread_mutex_unlock(&(_inp)->inp_mtx) +#endif +#define SCTP_INP_INCR_REF(_inp) atomic_add_int(&((_inp)->refcount), 1) +#define SCTP_INP_DECR_REF(_inp) atomic_add_int(&((_inp)->refcount), -1) + +#define SCTP_TCB_SEND_LOCK_INIT(_tcb) \ + (void)pthread_mutex_init(&(_tcb)->tcb_send_mtx, &SCTP_BASE_VAR(mtx_attr)) +#define SCTP_TCB_SEND_LOCK_DESTROY(_tcb) \ + (void)pthread_mutex_destroy(&(_tcb)->tcb_send_mtx) +#ifdef INVARIANTS +#define SCTP_TCB_SEND_LOCK(_tcb) \ + KASSERT(pthread_mutex_lock(&(_tcb)->tcb_send_mtx) == 0, ("%s: tcb_send_mtx already locked", __func__)) +#define SCTP_TCB_SEND_UNLOCK(_tcb) \ + KASSERT(pthread_mutex_unlock(&(_tcb)->tcb_send_mtx) == 0, ("%s: tcb_send_mtx not locked", __func__)) +#else +#define SCTP_TCB_SEND_LOCK(_tcb) \ + (void)pthread_mutex_lock(&(_tcb)->tcb_send_mtx) +#define SCTP_TCB_SEND_UNLOCK(_tcb) \ + (void)pthread_mutex_unlock(&(_tcb)->tcb_send_mtx) +#endif + +#define SCTP_ASOC_CREATE_LOCK_INIT(_inp) \ + (void)pthread_mutex_init(&(_inp)->inp_create_mtx, &SCTP_BASE_VAR(mtx_attr)) +#define SCTP_ASOC_CREATE_LOCK_DESTROY(_inp) \ + (void)pthread_mutex_destroy(&(_inp)->inp_create_mtx) +#ifdef INVARIANTS +#ifdef SCTP_LOCK_LOGGING +#define SCTP_ASOC_CREATE_LOCK(_inp) do { \ + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOCK_LOGGING_ENABLE) \ + sctp_log_lock(_inp, NULL, SCTP_LOG_LOCK_CREATE); \ + KASSERT(pthread_mutex_lock(&(_inp)->inp_create_mtx) == 0, ("%s: inp_create_mtx already locked", __func__)) \ +} while (0) +#else +#define SCTP_ASOC_CREATE_LOCK(_inp) \ + KASSERT(pthread_mutex_lock(&(_inp)->inp_create_mtx) == 0, ("%s: inp_create_mtx already locked", __func__)) +#endif +#define SCTP_ASOC_CREATE_UNLOCK(_inp) \ + KASSERT(pthread_mutex_unlock(&(_inp)->inp_create_mtx) == 0, ("%s: inp_create_mtx not locked", __func__)) +#else +#ifdef SCTP_LOCK_LOGGING +#define SCTP_ASOC_CREATE_LOCK(_inp) do { \ + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOCK_LOGGING_ENABLE) \ + sctp_log_lock(_inp, NULL, SCTP_LOG_LOCK_CREATE); \ + (void)pthread_mutex_lock(&(_inp)->inp_create_mtx); \ +} while (0) +#else +#define SCTP_ASOC_CREATE_LOCK(_inp) \ + (void)pthread_mutex_lock(&(_inp)->inp_create_mtx) +#endif #define SCTP_ASOC_CREATE_UNLOCK(_inp) \ (void)pthread_mutex_unlock(&(_inp)->inp_create_mtx) - +#endif /* * For the majority of things (once we have found the association) we will * lock the actual association mutex. This will protect all the assoiciation @@ -398,28 +436,38 @@ */ #define SCTP_TCB_LOCK_INIT(_tcb) \ - (void)pthread_mutex_init(&(_tcb)->tcb_mtx, NULL) - + (void)pthread_mutex_init(&(_tcb)->tcb_mtx, &SCTP_BASE_VAR(mtx_attr)) #define SCTP_TCB_LOCK_DESTROY(_tcb) \ (void)pthread_mutex_destroy(&(_tcb)->tcb_mtx) - +#ifdef INVARIANTS #ifdef SCTP_LOCK_LOGGING -#define SCTP_TCB_LOCK(_tcb) do { \ - if(SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOCK_LOGGING_ENABLE) sctp_log_lock(_tcb->sctp_ep, _tcb, SCTP_LOG_LOCK_TCB); \ - (void)pthread_mutex_lock(&(_tcb)->tcb_mtx); \ +#define SCTP_TCB_LOCK(_tcb) do { \ + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOCK_LOGGING_ENABLE) \ + sctp_log_lock(_tcb->sctp_ep, _tcb, SCTP_LOG_LOCK_TCB); \ + KASSERT(pthread_mutex_lock(&(_tcb)->tcb_mtx) == 0, ("%s: tcb_mtx already locked", __func__)) \ } while (0) - #else -#define SCTP_TCB_LOCK(_tcb) do { \ - (void)pthread_mutex_lock(&(_tcb)->tcb_mtx); \ -} while (0) +#define SCTP_TCB_LOCK(_tcb) \ + KASSERT(pthread_mutex_lock(&(_tcb)->tcb_mtx) == 0, ("%s: tcb_mtx already locked", __func__)) #endif - -#define SCTP_TCB_TRYLOCK(_tcb) (!(pthread_mutex_trylock(&(_tcb)->tcb_mtx))) - -#define SCTP_TCB_UNLOCK(_tcb) (void)pthread_mutex_unlock(&(_tcb)->tcb_mtx) - -#define SCTP_TCB_LOCK_ASSERT(_tcb) +#define SCTP_TCB_UNLOCK(_tcb) \ + KASSERT(pthread_mutex_unlock(&(_tcb)->tcb_mtx) == 0, ("%s: tcb_mtx not locked", __func__)) +#else +#ifdef SCTP_LOCK_LOGGING +#define SCTP_TCB_LOCK(_tcb) do { \ + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOCK_LOGGING_ENABLE) \ + sctp_log_lock(_tcb->sctp_ep, _tcb, SCTP_LOG_LOCK_TCB); \ + (void)pthread_mutex_lock(&(_tcb)->tcb_mtx); \ +} while (0) +#else +#define SCTP_TCB_LOCK(_tcb) \ + (void)pthread_mutex_lock(&(_tcb)->tcb_mtx) +#endif +#define SCTP_TCB_UNLOCK(_tcb) (void)pthread_mutex_unlock(&(_tcb)->tcb_mtx) +#endif +#define SCTP_TCB_LOCK_ASSERT(_tcb) \ + KASSERT(pthread_mutex_trylock(&(_tcb)->tcb_mtx) == EBUSY, ("%s: tcb_mtx not locked", __func__)) +#define SCTP_TCB_TRYLOCK(_tcb) (!(pthread_mutex_trylock(&(_tcb)->tcb_mtx))) #endif #endif /* SCTP_PER_SOCKET_LOCKING */ @@ -434,29 +482,36 @@ #define SCTP_INP_READ_CONTENDED(_inp) (0) /* Don't know if this is possible */ #define SCTP_ASOC_CREATE_LOCK_CONTENDED(_inp) (0) /* Don't know if this is possible */ - /* socket locks */ -#if defined(__Userspace__) #if defined(__Userspace_os_Windows) #define SOCKBUF_LOCK_ASSERT(_so_buf) -#define SOCKBUF_LOCK(_so_buf) EnterCriticalSection(&(_so_buf)->sb_mtx) -#define SOCKBUF_UNLOCK(_so_buf) LeaveCriticalSection(&(_so_buf)->sb_mtx) -#define SOCK_LOCK(_so) SOCKBUF_LOCK(&(_so)->so_rcv) -#define SOCK_UNLOCK(_so) SOCKBUF_UNLOCK(&(_so)->so_rcv) +#define SOCKBUF_LOCK(_so_buf) \ + EnterCriticalSection(&(_so_buf)->sb_mtx) +#define SOCKBUF_UNLOCK(_so_buf) \ + LeaveCriticalSection(&(_so_buf)->sb_mtx) +#define SOCK_LOCK(_so) \ + SOCKBUF_LOCK(&(_so)->so_rcv) +#define SOCK_UNLOCK(_so) \ + SOCKBUF_UNLOCK(&(_so)->so_rcv) #else -#define SOCKBUF_LOCK_ASSERT(_so_buf) KASSERT(pthread_mutex_trylock(SOCKBUF_MTX(_so_buf)) == EBUSY, ("%s: socket buffer not locked", __func__)) -#define SOCKBUF_LOCK(_so_buf) pthread_mutex_lock(SOCKBUF_MTX(_so_buf)) -#define SOCKBUF_UNLOCK(_so_buf) pthread_mutex_unlock(SOCKBUF_MTX(_so_buf)) -#define SOCK_LOCK(_so) SOCKBUF_LOCK(&(_so)->so_rcv) -#define SOCK_UNLOCK(_so) SOCKBUF_UNLOCK(&(_so)->so_rcv) +#define SOCKBUF_LOCK_ASSERT(_so_buf) \ + KASSERT(pthread_mutex_trylock(SOCKBUF_MTX(_so_buf)) == EBUSY, ("%s: socket buffer not locked", __func__)) +#ifdef INVARIANTS +#define SOCKBUF_LOCK(_so_buf) \ + KASSERT(pthread_mutex_lock(SOCKBUF_MTX(_so_buf)) == 0, ("%s: sockbuf_mtx already locked", __func__)) +#define SOCKBUF_UNLOCK(_so_buf) \ + KASSERT(pthread_mutex_unlock(SOCKBUF_MTX(_so_buf)) == 0, ("%s: sockbuf_mtx not locked", __func__)) +#else +#define SOCKBUF_LOCK(_so_buf) \ + pthread_mutex_lock(SOCKBUF_MTX(_so_buf)) +#define SOCKBUF_UNLOCK(_so_buf) \ + pthread_mutex_unlock(SOCKBUF_MTX(_so_buf)) #endif -#else -#define SOCK_LOCK(_so) -#define SOCK_UNLOCK(_so) -#define SOCKBUF_LOCK(_so_buf) -#define SOCKBUF_UNLOCK(_so_buf) -#define SOCKBUF_LOCK_ASSERT(_so_buf) +#define SOCK_LOCK(_so) \ + SOCKBUF_LOCK(&(_so)->so_rcv) +#define SOCK_UNLOCK(_so) \ + SOCKBUF_UNLOCK(&(_so)->so_rcv) #endif #define SCTP_STATLOG_INIT_LOCK() @@ -470,18 +525,12 @@ InitializeCriticalSection(&SCTP_BASE_INFO(ipi_addr_mtx)) #define SCTP_IPI_ADDR_DESTROY() \ DeleteCriticalSection(&SCTP_BASE_INFO(ipi_addr_mtx)) - -#define SCTP_IPI_ADDR_RLOCK() \ - do { \ - EnterCriticalSection(&SCTP_BASE_INFO(ipi_addr_mtx)); \ - } while (0) +#define SCTP_IPI_ADDR_RLOCK() \ + EnterCriticalSection(&SCTP_BASE_INFO(ipi_addr_mtx)) #define SCTP_IPI_ADDR_RUNLOCK() \ LeaveCriticalSection(&SCTP_BASE_INFO(ipi_addr_mtx)) - -#define SCTP_IPI_ADDR_WLOCK() \ - do { \ - EnterCriticalSection(&SCTP_BASE_INFO(ipi_addr_mtx)); \ - } while (0) +#define SCTP_IPI_ADDR_WLOCK() \ + EnterCriticalSection(&SCTP_BASE_INFO(ipi_addr_mtx)) #define SCTP_IPI_ADDR_WUNLOCK() \ LeaveCriticalSection(&SCTP_BASE_INFO(ipi_addr_mtx)) @@ -489,154 +538,122 @@ /* iterator locks */ #define SCTP_ITERATOR_LOCK_INIT() \ InitializeCriticalSection(&sctp_it_ctl.it_mtx) - -#define SCTP_ITERATOR_LOCK() \ - do { \ - EnterCriticalSection(&sctp_it_ctl.it_mtx); \ - } while (0) - +#define SCTP_ITERATOR_LOCK_DESTROY() \ + DeleteCriticalSection(&sctp_it_ctl.it_mtx) +#define SCTP_ITERATOR_LOCK() \ + EnterCriticalSection(&sctp_it_ctl.it_mtx) #define SCTP_ITERATOR_UNLOCK() \ LeaveCriticalSection(&sctp_it_ctl.it_mtx) -#define SCTP_ITERATOR_LOCK_DESTROY() \ - DeleteCriticalSection(&sctp_it_ctl.it_mtx) - - #define SCTP_IPI_ITERATOR_WQ_INIT() \ InitializeCriticalSection(&sctp_it_ctl.ipi_iterator_wq_mtx) - #define SCTP_IPI_ITERATOR_WQ_DESTROY() \ DeleteCriticalSection(&sctp_it_ctl.ipi_iterator_wq_mtx) - #define SCTP_IPI_ITERATOR_WQ_LOCK() \ - do { \ - EnterCriticalSection(&sctp_it_ctl.ipi_iterator_wq_mtx); \ - } while (0) - + EnterCriticalSection(&sctp_it_ctl.ipi_iterator_wq_mtx) #define SCTP_IPI_ITERATOR_WQ_UNLOCK() \ LeaveCriticalSection(&sctp_it_ctl.ipi_iterator_wq_mtx) #else /* end of __Userspace_os_Windows */ /* address list locks */ #define SCTP_IPI_ADDR_INIT() \ - (void)pthread_mutex_init(&SCTP_BASE_INFO(ipi_addr_mtx), NULL) + (void)pthread_mutex_init(&SCTP_BASE_INFO(ipi_addr_mtx), &SCTP_BASE_VAR(mtx_attr)) #define SCTP_IPI_ADDR_DESTROY() \ (void)pthread_mutex_destroy(&SCTP_BASE_INFO(ipi_addr_mtx)) - -#define SCTP_IPI_ADDR_RLOCK() \ - do { \ - (void)pthread_mutex_lock(&SCTP_BASE_INFO(ipi_addr_mtx)); \ - } while (0) +#ifdef INVARIANTS +#define SCTP_IPI_ADDR_RLOCK() \ + KASSERT(pthread_mutex_lock(&SCTP_BASE_INFO(ipi_addr_mtx)) == 0, ("%s: ipi_addr_mtx already locked", __func__)) +#define SCTP_IPI_ADDR_RUNLOCK() \ + KASSERT(pthread_mutex_unlock(&SCTP_BASE_INFO(ipi_addr_mtx)) == 0, ("%s: ipi_addr_mtx not locked", __func__)) +#define SCTP_IPI_ADDR_WLOCK() \ + KASSERT(pthread_mutex_lock(&SCTP_BASE_INFO(ipi_addr_mtx)) == 0, ("%s: ipi_addr_mtx already locked", __func__)) +#define SCTP_IPI_ADDR_WUNLOCK() \ + KASSERT(pthread_mutex_unlock(&SCTP_BASE_INFO(ipi_addr_mtx)) == 0, ("%s: ipi_addr_mtx not locked", __func__)) +#else +#define SCTP_IPI_ADDR_RLOCK() \ + (void)pthread_mutex_lock(&SCTP_BASE_INFO(ipi_addr_mtx)) #define SCTP_IPI_ADDR_RUNLOCK() \ (void)pthread_mutex_unlock(&SCTP_BASE_INFO(ipi_addr_mtx)) - -#define SCTP_IPI_ADDR_WLOCK() \ - do { \ - (void)pthread_mutex_lock(&SCTP_BASE_INFO(ipi_addr_mtx)); \ - } while (0) +#define SCTP_IPI_ADDR_WLOCK() \ + (void)pthread_mutex_lock(&SCTP_BASE_INFO(ipi_addr_mtx)) #define SCTP_IPI_ADDR_WUNLOCK() \ (void)pthread_mutex_unlock(&SCTP_BASE_INFO(ipi_addr_mtx)) - +#endif /* iterator locks */ #define SCTP_ITERATOR_LOCK_INIT() \ - (void)pthread_mutex_init(&sctp_it_ctl.it_mtx, NULL) - -#define SCTP_ITERATOR_LOCK() \ - do { \ - (void)pthread_mutex_lock(&sctp_it_ctl.it_mtx); \ - } while (0) - -#define SCTP_ITERATOR_UNLOCK() \ - (void)pthread_mutex_unlock(&sctp_it_ctl.it_mtx) - + (void)pthread_mutex_init(&sctp_it_ctl.it_mtx, &SCTP_BASE_VAR(mtx_attr)) #define SCTP_ITERATOR_LOCK_DESTROY() \ (void)pthread_mutex_destroy(&sctp_it_ctl.it_mtx) - +#ifdef INVARIANTS +#define SCTP_ITERATOR_LOCK() \ + KASSERT(pthread_mutex_lock(&sctp_it_ctl.it_mtx) == 0, ("%s: it_mtx already locked", __func__)) +#define SCTP_ITERATOR_UNLOCK() \ + KASSERT(pthread_mutex_unlock(&sctp_it_ctl.it_mtx) == 0, ("%s: it_mtx not locked", __func__)) +#else +#define SCTP_ITERATOR_LOCK() \ + (void)pthread_mutex_lock(&sctp_it_ctl.it_mtx) +#define SCTP_ITERATOR_UNLOCK() \ + (void)pthread_mutex_unlock(&sctp_it_ctl.it_mtx) +#endif #define SCTP_IPI_ITERATOR_WQ_INIT() \ - (void)pthread_mutex_init(&sctp_it_ctl.ipi_iterator_wq_mtx, NULL) - + (void)pthread_mutex_init(&sctp_it_ctl.ipi_iterator_wq_mtx, &SCTP_BASE_VAR(mtx_attr)) #define SCTP_IPI_ITERATOR_WQ_DESTROY() \ (void)pthread_mutex_destroy(&sctp_it_ctl.ipi_iterator_wq_mtx) - +#ifdef INVARIANTS #define SCTP_IPI_ITERATOR_WQ_LOCK() \ - do { \ - (void)pthread_mutex_lock(&sctp_it_ctl.ipi_iterator_wq_mtx); \ - } while (0) - + KASSERT(pthread_mutex_lock(&sctp_it_ctl.ipi_iterator_wq_mtx) == 0, ("%s: ipi_iterator_wq_mtx already locked", __func__)) +#define SCTP_IPI_ITERATOR_WQ_UNLOCK() \ + KASSERT(pthread_mutex_unlock(&sctp_it_ctl.ipi_iterator_wq_mtx) == 0, ("%s: ipi_iterator_wq_mtx not locked", __func__)) +#else +#define SCTP_IPI_ITERATOR_WQ_LOCK() \ + (void)pthread_mutex_lock(&sctp_it_ctl.ipi_iterator_wq_mtx) #define SCTP_IPI_ITERATOR_WQ_UNLOCK() \ (void)pthread_mutex_unlock(&sctp_it_ctl.ipi_iterator_wq_mtx) #endif +#endif #define SCTP_INCR_EP_COUNT() \ - do { \ - atomic_add_int(&SCTP_BASE_INFO(ipi_count_ep), 1); \ - } while (0) + atomic_add_int(&SCTP_BASE_INFO(ipi_count_ep), 1) #define SCTP_DECR_EP_COUNT() \ - do { \ - atomic_subtract_int(&SCTP_BASE_INFO(ipi_count_ep), 1); \ - } while (0) + atomic_subtract_int(&SCTP_BASE_INFO(ipi_count_ep), 1) #define SCTP_INCR_ASOC_COUNT() \ - do { \ - atomic_add_int(&SCTP_BASE_INFO(ipi_count_asoc), 1); \ - } while (0) + atomic_add_int(&SCTP_BASE_INFO(ipi_count_asoc), 1) #define SCTP_DECR_ASOC_COUNT() \ - do { \ - atomic_subtract_int(&SCTP_BASE_INFO(ipi_count_asoc), 1); \ - } while (0) + atomic_subtract_int(&SCTP_BASE_INFO(ipi_count_asoc), 1) #define SCTP_INCR_LADDR_COUNT() \ - do { \ - atomic_add_int(&SCTP_BASE_INFO(ipi_count_laddr), 1); \ - } while (0) + atomic_add_int(&SCTP_BASE_INFO(ipi_count_laddr), 1) #define SCTP_DECR_LADDR_COUNT() \ - do { \ - atomic_subtract_int(&SCTP_BASE_INFO(ipi_count_laddr), 1); \ - } while (0) + atomic_subtract_int(&SCTP_BASE_INFO(ipi_count_laddr), 1) #define SCTP_INCR_RADDR_COUNT() \ - do { \ - atomic_add_int(&SCTP_BASE_INFO(ipi_count_raddr), 1); \ - } while (0) + atomic_add_int(&SCTP_BASE_INFO(ipi_count_raddr), 1) #define SCTP_DECR_RADDR_COUNT() \ - do { \ - atomic_subtract_int(&SCTP_BASE_INFO(ipi_count_raddr), 1); \ - } while (0) + atomic_subtract_int(&SCTP_BASE_INFO(ipi_count_raddr), 1) #define SCTP_INCR_CHK_COUNT() \ - do { \ - atomic_add_int(&SCTP_BASE_INFO(ipi_count_chunk), 1); \ - } while (0) + atomic_add_int(&SCTP_BASE_INFO(ipi_count_chunk), 1) #define SCTP_DECR_CHK_COUNT() \ - do { \ - atomic_subtract_int(&SCTP_BASE_INFO(ipi_count_chunk), 1); \ - } while (0) + atomic_subtract_int(&SCTP_BASE_INFO(ipi_count_chunk), 1) #define SCTP_INCR_READQ_COUNT() \ - do { \ - atomic_add_int(&SCTP_BASE_INFO(ipi_count_readq), 1); \ - } while (0) + atomic_add_int(&SCTP_BASE_INFO(ipi_count_readq), 1) #define SCTP_DECR_READQ_COUNT() \ - do { \ - atomic_subtract_int(&SCTP_BASE_INFO(ipi_count_readq), 1); \ - } while (0) + atomic_subtract_int(&SCTP_BASE_INFO(ipi_count_readq), 1) #define SCTP_INCR_STRMOQ_COUNT() \ - do { \ - atomic_add_int(&SCTP_BASE_INFO(ipi_count_strmoq), 1); \ - } while (0) + atomic_add_int(&SCTP_BASE_INFO(ipi_count_strmoq), 1) #define SCTP_DECR_STRMOQ_COUNT() \ - do { \ - atomic_subtract_int(&SCTP_BASE_INFO(ipi_count_strmoq), 1); \ - } while (0) + atomic_subtract_int(&SCTP_BASE_INFO(ipi_count_strmoq), 1) #endif
diff --git a/usrsctplib/netinet/sctp_sha1.c b/usrsctplib/netinet/sctp_sha1.c index c86517f..aba6160 100755 --- a/usrsctplib/netinet/sctp_sha1.c +++ b/usrsctplib/netinet/sctp_sha1.c
@@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved. * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved. * Copyright (c) 2008-2013, by Michael Tuexen. All rights reserved.
diff --git a/usrsctplib/netinet/sctp_sha1.h b/usrsctplib/netinet/sctp_sha1.h index 01e3c2e..6d6a05c 100755 --- a/usrsctplib/netinet/sctp_sha1.h +++ b/usrsctplib/netinet/sctp_sha1.h
@@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved. * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved. * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
diff --git a/usrsctplib/netinet/sctp_ss_functions.c b/usrsctplib/netinet/sctp_ss_functions.c index b609ca5..f198257 100755 --- a/usrsctplib/netinet/sctp_ss_functions.c +++ b/usrsctplib/netinet/sctp_ss_functions.c
@@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2010-2012, by Michael Tuexen. All rights reserved. * Copyright (c) 2010-2012, by Randall Stewart. All rights reserved. * Copyright (c) 2010-2012, by Robin Seggelmann. All rights reserved. @@ -28,7 +30,7 @@ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_ss_functions.c 321289 2017-07-20 11:09:33Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp_ss_functions.c 326180 2017-11-24 19:38:59Z tuexen $"); #endif #include <netinet/sctp_pcb.h>
diff --git a/usrsctplib/netinet/sctp_structs.h b/usrsctplib/netinet/sctp_structs.h index b5f3ef2..543d386 100755 --- a/usrsctplib/netinet/sctp_structs.h +++ b/usrsctplib/netinet/sctp_structs.h
@@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 2001-2008, by Cisco Systems, Inc. All rights reserved. * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved. * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved. @@ -32,7 +34,7 @@ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_structs.h 310590 2016-12-26 11:06:41Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp_structs.h 325370 2017-11-03 20:46:12Z tuexen $"); #endif #ifndef _NETINET_SCTP_STRUCTS_H_ @@ -1155,6 +1157,7 @@ uint32_t chunks_on_out_queue; /* total chunks floating around, * locked by send socket buffer */ uint32_t peers_adaptation; + uint32_t default_mtu; uint16_t peer_hmac_id; /* peer HMAC id to send */ /*
diff --git a/usrsctplib/netinet/sctp_sysctl.c b/usrsctplib/netinet/sctp_sysctl.c index 1846475..59b22e4 100755 --- a/usrsctplib/netinet/sctp_sysctl.c +++ b/usrsctplib/netinet/sctp_sysctl.c
@@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 2007, by Cisco Systems, Inc. All rights reserved. * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved. * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved. @@ -32,7 +34,7 @@ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_sysctl.c 318958 2017-05-26 16:29:00Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp_sysctl.c 323505 2017-09-12 21:08:50Z tuexen $"); #endif #include <netinet/sctp_os.h> @@ -629,11 +631,27 @@ xraddr.rtt = net->rtt / 1000; xraddr.heartbeat_interval = net->heart_beat_delay; xraddr.ssthresh = net->ssthresh; + xraddr.encaps_port = net->port; + if (net->dest_state & SCTP_ADDR_UNCONFIRMED) { + xraddr.state = SCTP_UNCONFIRMED; + } else if (net->dest_state & SCTP_ADDR_REACHABLE) { + xraddr.state = SCTP_ACTIVE; + } else { + xraddr.state = SCTP_INACTIVE; + } #endif #else xraddr.rtt = net->rtt / 1000; xraddr.heartbeat_interval = net->heart_beat_delay; xraddr.ssthresh = net->ssthresh; + xraddr.encaps_port = net->port; + if (net->dest_state & SCTP_ADDR_UNCONFIRMED) { + xraddr.state = SCTP_UNCONFIRMED; + } else if (net->dest_state & SCTP_ADDR_REACHABLE) { + xraddr.state = SCTP_ACTIVE; + } else { + xraddr.state = SCTP_INACTIVE; + } #endif xraddr.start_time.tv_sec = (uint32_t)net->start_time.tv_sec; xraddr.start_time.tv_usec = (uint32_t)net->start_time.tv_usec;
diff --git a/usrsctplib/netinet/sctp_sysctl.h b/usrsctplib/netinet/sctp_sysctl.h index cbd29e3..22ae57e 100755 --- a/usrsctplib/netinet/sctp_sysctl.h +++ b/usrsctplib/netinet/sctp_sysctl.h
@@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 2007, by Cisco Systems, Inc. All rights reserved. * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved. * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
diff --git a/usrsctplib/netinet/sctp_timer.c b/usrsctplib/netinet/sctp_timer.c index 9507c71..426ba44 100755 --- a/usrsctplib/netinet/sctp_timer.c +++ b/usrsctplib/netinet/sctp_timer.c
@@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved. * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved. * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
diff --git a/usrsctplib/netinet/sctp_timer.h b/usrsctplib/netinet/sctp_timer.h index a519bb6..822d5b4 100755 --- a/usrsctplib/netinet/sctp_timer.h +++ b/usrsctplib/netinet/sctp_timer.h
@@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved. * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved. * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
diff --git a/usrsctplib/netinet/sctp_uio.h b/usrsctplib/netinet/sctp_uio.h index c46989b..956d754 100755 --- a/usrsctplib/netinet/sctp_uio.h +++ b/usrsctplib/netinet/sctp_uio.h
@@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved. * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved. * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved. @@ -32,7 +34,7 @@ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_uio.h 309607 2016-12-06 10:21:25Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp_uio.h 323505 2017-09-12 21:08:50Z tuexen $"); #endif #ifndef _NETINET_SCTP_UIO_H_ @@ -1306,13 +1308,17 @@ uint32_t rtt; uint32_t heartbeat_interval; uint32_t ssthresh; - uint32_t extra_padding[30]; /* future */ + uint16_t encaps_port; + uint16_t state; + uint32_t extra_padding[29]; /* future */ #endif #else uint32_t rtt; uint32_t heartbeat_interval; uint32_t ssthresh; - uint32_t extra_padding[30]; /* future */ + uint16_t encaps_port; + uint16_t state; + uint32_t extra_padding[29]; /* future */ #endif };
diff --git a/usrsctplib/netinet/sctp_usrreq.c b/usrsctplib/netinet/sctp_usrreq.c index 619eee5..0325571 100755 --- a/usrsctplib/netinet/sctp_usrreq.c +++ b/usrsctplib/netinet/sctp_usrreq.c
@@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 2001-2008, by Cisco Systems, Inc. All rights reserved. * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved. * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved. @@ -32,7 +34,7 @@ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_usrreq.c 321204 2017-07-19 14:28:58Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp_usrreq.c 325370 2017-11-03 20:46:12Z tuexen $"); #endif #include <netinet/sctp_os.h> @@ -170,7 +172,7 @@ static void sctp_finish(void *unused __unused) { - sctp_pcb_finish(); + sctp_pcb_finish(); } VNET_SYSUNINIT(sctp, SI_SUB_PROTO_DOMAIN, SI_ORDER_FOURTH, sctp_finish, NULL); #endif @@ -356,6 +358,10 @@ #endif /* no need to unlock here, since the TCB is gone */ } else if (icmp_code == ICMP_UNREACH_NEEDFRAG) { + if ((net->dest_state & SCTP_ADDR_NO_PMTUD) == 0) { + SCTP_TCB_UNLOCK(stcb); + return; + } /* Find the next (smaller) MTU */ if (next_mtu == 0) { /* @@ -1253,7 +1259,7 @@ int sctp_flush(struct socket *so, int how) { - /* + /* * We will just clear out the values and let * subsequent close clear out the data, if any. * Note if the user did a shutdown(SHUT_RD) they @@ -1274,7 +1280,7 @@ return (0); } SCTP_INP_RUNLOCK(inp); - if ((how == PRU_FLUSH_RD) || (how == PRU_FLUSH_RDWR)) { + if ((how == PRU_FLUSH_RD) || (how == PRU_FLUSH_RDWR)) { /* First make sure the sb will be happy, we don't * use these except maybe the count */ @@ -1287,7 +1293,7 @@ so->so_rcv.sb_mbcnt = 0; so->so_rcv.sb_mb = NULL; } - if ((how == PRU_FLUSH_WR) || (how == PRU_FLUSH_RDWR)) { + if ((how == PRU_FLUSH_WR) || (how == PRU_FLUSH_RDWR)) { /* First make sure the sb will be happy, we don't * use these except maybe the count */ @@ -1320,7 +1326,9 @@ so->so_rcv.sb_state &= ~SBS_CANTRCVMORE; SOCKBUF_UNLOCK(&so->so_rcv); #else + SOCK_LOCK(so); so->so_state &= ~SS_CANTRCVMORE; + SOCK_UNLOCK(so); #endif /* This proc will wakeup for read and do nothing (I hope) */ SCTP_INP_RUNLOCK(inp); @@ -2557,6 +2565,7 @@ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error); } else { id->assoc_value = stcb->asoc.vrf_id; + SCTP_TCB_UNLOCK(stcb); *optsize = sizeof(struct sctp_assoc_value); } break; @@ -3060,7 +3069,12 @@ #endif #ifdef INET6 case AF_INET6: - paddrp->spp_pathmtu -= SCTP_MIN_V4_OVERHEAD; + paddrp->spp_pathmtu -= SCTP_MIN_OVERHEAD; + break; +#endif +#if defined(__Userspace__) + case AF_CONN: + paddrp->spp_pathmtu -= sizeof(struct sctphdr); break; #endif default: @@ -3095,7 +3109,7 @@ * value */ paddrp->spp_pathmaxrxt = stcb->asoc.def_net_failure; - paddrp->spp_pathmtu = 0; + paddrp->spp_pathmtu = stcb->asoc.default_mtu; if (stcb->asoc.default_dscp & 0x01) { paddrp->spp_dscp = stcb->asoc.default_dscp & 0xfc; paddrp->spp_flags |= SPP_DSCP; @@ -3142,8 +3156,7 @@ paddrp->spp_flags |= SPP_IPV6_FLOWLABEL; } #endif - /* can't return this */ - paddrp->spp_pathmtu = 0; + paddrp->spp_pathmtu = inp->sctp_ep.default_mtu; if (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_DONOT_HEARTBEAT)) { paddrp->spp_flags |= SPP_HB_ENABLE; @@ -3237,6 +3250,11 @@ paddri->spinfo_mtu -= SCTP_MIN_OVERHEAD; break; #endif +#if defined(__Userspace__) + case AF_CONN: + paddri->spinfo_mtu -= sizeof(struct sctphdr); + break; +#endif default: break; } @@ -3246,7 +3264,7 @@ if (stcb != NULL) { SCTP_TCB_UNLOCK(stcb); } - SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT); + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT); error = ENOENT; } break; @@ -3334,6 +3352,11 @@ sstat->sstat_primary.spinfo_mtu -= SCTP_MIN_OVERHEAD; break; #endif +#if defined(__Userspace__) + case AF_CONN: + sstat->sstat_primary.spinfo_mtu -= sizeof(struct sctphdr); + break; +#endif default: break; } @@ -3740,7 +3763,6 @@ if (event_type > 0) { if (stcb) { event->se_on = sctp_stcb_is_feature_on(inp, stcb, event_type); - SCTP_TCB_UNLOCK(stcb); } else { if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) || @@ -3754,6 +3776,9 @@ } } } + if (stcb != NULL) { + SCTP_TCB_UNLOCK(stcb); + } if (error == 0) { *optsize = sizeof(struct sctp_event); } @@ -4346,12 +4371,16 @@ sprstat->sprstat_abandoned_unsent = stcb->asoc.strmout[sid].abandoned_unsent[0]; sprstat->sprstat_abandoned_sent = stcb->asoc.strmout[sid].abandoned_sent[0]; #endif - SCTP_TCB_UNLOCK(stcb); - *optsize = sizeof(struct sctp_prstatus); } else { SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); error = EINVAL; } + if (stcb != NULL) { + SCTP_TCB_UNLOCK(stcb); + } + if (error == 0) { + *optsize = sizeof(struct sctp_prstatus); + } break; } case SCTP_PR_ASSOC_STATUS: @@ -4374,12 +4403,16 @@ sprstat->sprstat_abandoned_unsent = stcb->asoc.abandoned_unsent[policy]; sprstat->sprstat_abandoned_sent = stcb->asoc.abandoned_sent[policy]; } - SCTP_TCB_UNLOCK(stcb); - *optsize = sizeof(struct sctp_prstatus); } else { SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); error = EINVAL; } + if (stcb != NULL) { + SCTP_TCB_UNLOCK(stcb); + } + if (error == 0) { + *optsize = sizeof(struct sctp_prstatus); + } break; } case SCTP_MAX_CWND: @@ -6130,6 +6163,11 @@ net->mtu += SCTP_MIN_OVERHEAD; break; #endif +#if defined(__Userspace__) + case AF_CONN: + net->mtu += sizeof(struct sctphdr); + break; +#endif default: break; } @@ -6273,6 +6311,11 @@ net->mtu += SCTP_MIN_OVERHEAD; break; #endif +#if defined(__Userspace__) + case AF_CONN: + net->mtu += sizeof(struct sctphdr); + break; +#endif default: break; } @@ -6280,6 +6323,7 @@ sctp_pathmtu_adjustment(stcb, net->mtu); } } + stcb->asoc.default_mtu = paddrp->spp_pathmtu; sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_DO_NOT_PMTUD); } if (paddrp->spp_flags & SPP_PMTUD_ENABLE) { @@ -6289,6 +6333,7 @@ } net->dest_state &= ~SCTP_ADDR_NO_PMTUD; } + stcb->asoc.default_mtu = 0; sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_DO_NOT_PMTUD); } if (paddrp->spp_flags & SPP_DSCP) { @@ -6346,8 +6391,12 @@ sctp_feature_on(inp, SCTP_PCB_FLAGS_DONOT_HEARTBEAT); } if (paddrp->spp_flags & SPP_PMTUD_ENABLE) { + inp->sctp_ep.default_mtu = 0; sctp_feature_off(inp, SCTP_PCB_FLAGS_DO_NOT_PMTUD); } else if (paddrp->spp_flags & SPP_PMTUD_DISABLE) { + if (paddrp->spp_pathmtu >= SCTP_SMALLEST_PMTU) { + inp->sctp_ep.default_mtu = paddrp->spp_pathmtu; + } sctp_feature_on(inp, SCTP_PCB_FLAGS_DO_NOT_PMTUD); } if (paddrp->spp_flags & SPP_DSCP) { @@ -6595,9 +6644,9 @@ #else error = suser(p, 0); #endif -#endif if (error) break; +#endif SCTP_CHECK_AND_CAST(ss, optval, union sctp_sockstore, optsize); /* SUPER USER CHECK? */ @@ -7835,7 +7884,7 @@ (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) { /* Should I really unlock ? */ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EFAULT); - error = EFAULT; + error = EFAULT; goto out_now; } #ifdef INET6 @@ -8256,8 +8305,8 @@ sctp_log_lock(inp, (struct sctp_tcb *)NULL, SCTP_LOG_LOCK_SOCK); } #endif - SOCK_LOCK(so); #if (defined(__FreeBSD__) && __FreeBSD_version > 500000) || defined(__Userspace__) + SOCK_LOCK(so); error = solisten_proto_check(so); SOCK_UNLOCK(so); if (error) {
diff --git a/usrsctplib/netinet/sctp_var.h b/usrsctplib/netinet/sctp_var.h index 9922685..860eceb 100755 --- a/usrsctplib/netinet/sctp_var.h +++ b/usrsctplib/netinet/sctp_var.h
@@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 2001-2008, by Cisco Systems, Inc. All rights reserved. * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved. * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
diff --git a/usrsctplib/netinet/sctputil.c b/usrsctplib/netinet/sctputil.c index 88cc6d4..2e404eb 100755 --- a/usrsctplib/netinet/sctputil.c +++ b/usrsctplib/netinet/sctputil.c
@@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 2001-2008, by Cisco Systems, Inc. All rights reserved. * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved. * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved. @@ -32,7 +34,7 @@ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctputil.c 321204 2017-07-19 14:28:58Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctputil.c 326163 2017-11-24 12:18:48Z tuexen $"); #endif #include <netinet/sctp_os.h> @@ -1110,6 +1112,7 @@ asoc->initial_init_rto_max = inp->sctp_ep.initial_init_rto_max; asoc->initial_rto = inp->sctp_ep.initial_rto; + asoc->default_mtu = inp->sctp_ep.default_mtu; asoc->max_init_times = inp->sctp_ep.max_init_times; asoc->max_send_times = inp->sctp_ep.max_send_times; asoc->def_net_failure = inp->sctp_ep.def_net_failure; @@ -1558,13 +1561,11 @@ LIST_INIT(&asc->list_of_work); asc->cnt = 0; - SCTP_WQ_ADDR_LOCK(); LIST_FOREACH_SAFE(wi, &SCTP_BASE_INFO(addr_wq), sctp_nxt_addr, nwi) { LIST_REMOVE(wi, sctp_nxt_addr); LIST_INSERT_HEAD(&asc->list_of_work, wi, sctp_nxt_addr); asc->cnt++; } - SCTP_WQ_ADDR_UNLOCK(); if (asc->cnt == 0) { SCTP_FREE(asc, SCTP_M_ASC_IT); @@ -1585,11 +1586,9 @@ if (SCTP_BASE_VAR(sctp_pcb_initialized) == 0) { sctp_asconf_iterator_end(asc, 0); } else { - SCTP_WQ_ADDR_LOCK(); LIST_FOREACH(wi, &asc->list_of_work, sctp_nxt_addr) { LIST_INSERT_HEAD(&SCTP_BASE_INFO(addr_wq), wi, sctp_nxt_addr); } - SCTP_WQ_ADDR_UNLOCK(); SCTP_FREE(asc, SCTP_M_ASC_IT); } } @@ -1666,8 +1665,7 @@ (tmr->type != SCTP_TIMER_TYPE_SHUTDOWN) && (tmr->type != SCTP_TIMER_TYPE_SHUTDOWNACK) && (tmr->type != SCTP_TIMER_TYPE_SHUTDOWNGUARD) && - (tmr->type != SCTP_TIMER_TYPE_ASOCKILL)) - ) { + (tmr->type != SCTP_TIMER_TYPE_ASOCKILL))) { SCTP_INP_DECR_REF(inp); #if defined(__FreeBSD__) && __FreeBSD_version >= 801000 CURVNET_RESTORE(); @@ -1721,6 +1719,12 @@ #endif return; } + } else if (inp != NULL) { + if (type != SCTP_TIMER_TYPE_INPKILL) { + SCTP_INP_WLOCK(inp); + } + } else { + SCTP_WQ_ADDR_LOCK(); } /* record in stopped what t-o occurred */ tmr->stopped_from = type; @@ -1742,22 +1746,6 @@ /* call the handler for the appropriate timer type */ switch (type) { - case SCTP_TIMER_TYPE_ZERO_COPY: - if (inp == NULL) { - break; - } - if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_ZERO_COPY_ACTIVE)) { - SCTP_ZERO_COPY_EVENT(inp, inp->sctp_socket); - } - break; - case SCTP_TIMER_TYPE_ZCOPY_SENDQ: - if (inp == NULL) { - break; - } - if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_ZERO_COPY_ACTIVE)) { - SCTP_ZERO_COPY_SENDQ_EVENT(inp, inp->sctp_socket); - } - break; case SCTP_TIMER_TYPE_ADDR_WQ: sctp_handle_addr_wq(); break; @@ -1884,7 +1872,6 @@ } SCTP_STAT_INCR(sctps_timosecret); (void)SCTP_GETTIME_TIMEVAL(&tv); - SCTP_INP_WLOCK(inp); inp->sctp_ep.time_of_secret_change = tv.tv_sec; inp->sctp_ep.last_secret_number = inp->sctp_ep.current_secret_number; @@ -1898,7 +1885,6 @@ inp->sctp_ep.secret_key[secret][i] = sctp_select_initial_TSN(&inp->sctp_ep); } - SCTP_INP_WUNLOCK(inp); sctp_timer_start(SCTP_TIMER_TYPE_NEWCOOKIE, inp, stcb, net); } did_output = 0; @@ -2052,6 +2038,10 @@ get_out: if (stcb) { SCTP_TCB_UNLOCK(stcb); + } else if (inp != NULL) { + SCTP_INP_WUNLOCK(inp); + } else { + SCTP_WQ_ADDR_UNLOCK(); } out_decr: @@ -2081,14 +2071,6 @@ SCTP_TCB_LOCK_ASSERT(stcb); } switch (t_type) { - case SCTP_TIMER_TYPE_ZERO_COPY: - tmr = &inp->sctp_ep.zero_copy_timer; - to_ticks = SCTP_ZERO_COPY_TICK_DELAY; - break; - case SCTP_TIMER_TYPE_ZCOPY_SENDQ: - tmr = &inp->sctp_ep.zero_copy_sendq_timer; - to_ticks = SCTP_ZERO_COPY_SENDQ_TICK_DELAY; - break; case SCTP_TIMER_TYPE_ADDR_WQ: /* Only 1 tick away :-) */ tmr = &SCTP_BASE_INFO(addr_wq_timer); @@ -2374,12 +2356,6 @@ SCTP_TCB_LOCK_ASSERT(stcb); } switch (t_type) { - case SCTP_TIMER_TYPE_ZERO_COPY: - tmr = &inp->sctp_ep.zero_copy_timer; - break; - case SCTP_TIMER_TYPE_ZCOPY_SENDQ: - tmr = &inp->sctp_ep.zero_copy_sendq_timer; - break; case SCTP_TIMER_TYPE_ADDR_WQ: tmr = &SCTP_BASE_INFO(addr_wq_timer); break; @@ -2571,8 +2547,8 @@ sctp_calculate_rto(struct sctp_tcb *stcb, struct sctp_association *asoc, struct sctp_nets *net, - struct timeval *told, - int safe, int rtt_from_sack) + struct timeval *old, + int rtt_from_sack) { /*- * given an association and the starting time of the current RTT @@ -2581,19 +2557,8 @@ int32_t rtt; /* RTT in ms */ uint32_t new_rto; int first_measure = 0; - struct timeval now, then, *old; + struct timeval now; - /* Copy it out for sparc64 */ - if (safe == sctp_align_unsafe_makecopy) { - old = &then; - memcpy(&then, told, sizeof(struct timeval)); - } else if (safe == sctp_align_safe_nocopy) { - old = told; - } else { - /* error */ - SCTP_PRINTF("Huh, bad rto calc call\n"); - return (0); - } /************************/ /* 1. calculate new RTT */ /************************/ @@ -4675,17 +4640,18 @@ struct sctp_queued_to_read *control, *nctl; struct sctp_readhead tmp_queue; struct mbuf *m; +#if defined(__FreeBSD__) || defined(__APPLE__) int error = 0; +#endif old_so = old_inp->sctp_socket; new_so = new_inp->sctp_socket; TAILQ_INIT(&tmp_queue); +#if defined(__FreeBSD__) || defined(__APPLE__) #if defined(__FreeBSD__) && __FreeBSD_version < 700000 SOCKBUF_LOCK(&(old_so->so_rcv)); #endif -#if defined(__FreeBSD__) || defined(__APPLE__) error = sblock(&old_so->so_rcv, waitflags); -#endif #if defined(__FreeBSD__) && __FreeBSD_version < 700000 SOCKBUF_UNLOCK(&(old_so->so_rcv)); #endif @@ -4702,6 +4668,7 @@ */ return; } +#endif /* lock the socket buffers */ SCTP_INP_READ_LOCK(old_inp); TAILQ_FOREACH_SAFE(control, &old_inp->read_queue, next, nctl) { @@ -4767,36 +4734,32 @@ ) { if ((inp != NULL) && (inp->sctp_socket != NULL)) { - if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_ZERO_COPY_ACTIVE)) { - SCTP_ZERO_COPY_EVENT(inp, inp->sctp_socket); - } else { #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) - struct socket *so; + struct socket *so; - so = SCTP_INP_SO(inp); - if (!so_locked) { - if (stcb) { - atomic_add_int(&stcb->asoc.refcnt, 1); - SCTP_TCB_UNLOCK(stcb); - } - SCTP_SOCKET_LOCK(so, 1); - if (stcb) { - SCTP_TCB_LOCK(stcb); - atomic_subtract_int(&stcb->asoc.refcnt, 1); - } - if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) { - SCTP_SOCKET_UNLOCK(so, 1); - return; - } + so = SCTP_INP_SO(inp); + if (!so_locked) { + if (stcb) { + atomic_add_int(&stcb->asoc.refcnt, 1); + SCTP_TCB_UNLOCK(stcb); } -#endif - sctp_sorwakeup(inp, inp->sctp_socket); -#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) - if (!so_locked) { + SCTP_SOCKET_LOCK(so, 1); + if (stcb) { + SCTP_TCB_LOCK(stcb); + atomic_subtract_int(&stcb->asoc.refcnt, 1); + } + if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) { SCTP_SOCKET_UNLOCK(so, 1); + return; } -#endif } +#endif + sctp_sorwakeup(inp, inp->sctp_socket); +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) + if (!so_locked) { + SCTP_SOCKET_UNLOCK(so, 1); + } +#endif } } #if defined(__Userspace__) @@ -5128,14 +5091,14 @@ stcb->asoc.abandoned_sent[PR_SCTP_POLICY(tp1->flags)]++; stcb->asoc.strmout[sid].abandoned_sent[0]++; #if defined(SCTP_DETAILED_STR_STATS) - stcb->asoc.strmout[stream].abandoned_sent[PR_SCTP_POLICY(tp1->flags)]++; + stcb->asoc.strmout[sid].abandoned_sent[PR_SCTP_POLICY(tp1->flags)]++; #endif } else { stcb->asoc.abandoned_unsent[0]++; stcb->asoc.abandoned_unsent[PR_SCTP_POLICY(tp1->flags)]++; stcb->asoc.strmout[sid].abandoned_unsent[0]++; #if defined(SCTP_DETAILED_STR_STATS) - stcb->asoc.strmout[stream].abandoned_unsent[PR_SCTP_POLICY(tp1->flags)]++; + stcb->asoc.strmout[sid].abandoned_unsent[PR_SCTP_POLICY(tp1->flags)]++; #endif } do { @@ -6775,11 +6738,11 @@ * newest first :-0 */ LIST_INSERT_HEAD(&SCTP_BASE_INFO(addr_wq), wi, sctp_nxt_addr); - SCTP_WQ_ADDR_UNLOCK(); sctp_timer_start(SCTP_TIMER_TYPE_ADDR_WQ, (struct sctp_inpcb *)NULL, (struct sctp_tcb *)NULL, (struct sctp_nets *)NULL); + SCTP_WQ_ADDR_UNLOCK(); return (0); }
diff --git a/usrsctplib/netinet/sctputil.h b/usrsctplib/netinet/sctputil.h index 59dd364..69fe484 100755 --- a/usrsctplib/netinet/sctputil.h +++ b/usrsctplib/netinet/sctputil.h
@@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved. * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved. * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved. @@ -32,7 +34,7 @@ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctputil.h 320260 2017-06-23 08:34:01Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctputil.h 324615 2017-10-14 10:02:59Z tuexen $"); #endif #ifndef _NETINET_SCTP_UTIL_H_ @@ -144,7 +146,7 @@ uint32_t sctp_calculate_rto(struct sctp_tcb *, struct sctp_association *, - struct sctp_nets *, struct timeval *, int, int); + struct sctp_nets *, struct timeval *, int); uint32_t sctp_calculate_len(struct mbuf *);
diff --git a/usrsctplib/netinet6/sctp6_usrreq.c b/usrsctplib/netinet6/sctp6_usrreq.c index 1c9bbd9..752f52b 100644 --- a/usrsctplib/netinet6/sctp6_usrreq.c +++ b/usrsctplib/netinet6/sctp6_usrreq.c
@@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved. * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved. * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved. @@ -32,7 +34,7 @@ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet6/sctp6_usrreq.c 321204 2017-07-19 14:28:58Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet6/sctp6_usrreq.c 325370 2017-11-03 20:46:12Z tuexen $"); #endif #include <netinet/sctp_os.h> @@ -396,6 +398,10 @@ } break; case ICMP6_PACKET_TOO_BIG: + if ((net->dest_state & SCTP_ADDR_NO_PMTUD) == 0) { + SCTP_TCB_UNLOCK(stcb); + break; + } if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) { timer_stopped = 1; sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net, @@ -1247,7 +1253,7 @@ if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) { stcb = LIST_FIRST(&inp->sctp_asoc_list); if (stcb) { - SCTP_TCB_UNLOCK(stcb); + SCTP_TCB_LOCK(stcb); } SCTP_INP_RUNLOCK(inp); } else {
diff --git a/usrsctplib/netinet6/sctp6_var.h b/usrsctplib/netinet6/sctp6_var.h index 2dca684..a962b12 100755 --- a/usrsctplib/netinet6/sctp6_var.h +++ b/usrsctplib/netinet6/sctp6_var.h
@@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved. * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved. * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
diff --git a/usrsctplib/user_environment.c b/usrsctplib/user_environment.c index 6830a23..767c4ba 100755 --- a/usrsctplib/user_environment.c +++ b/usrsctplib/user_environment.c
@@ -60,22 +60,20 @@ */ userland_mutex_t atomic_mtx; -/* Source: /usr/src/sys/dev/random/harvest.c */ -static int read_random_phony(void *, int); - -static int (*read_func)(void *, int) = read_random_phony; - -/* Userland-visible version of read_random */ -int -read_random(void *buf, int count) -{ - return ((*read_func)(buf, count)); -} - /* If the entropy device is not loaded, make a token effort to * provide _some_ kind of randomness. This should only be used * inside other RNG's, like arc4random(9). */ +#if defined(__Userspace_os_FreeBSD) || defined(__Userspace_os_Darwin) +static int +read_random_phony(void *buf, int count) +{ + if (count >= 0) { + arc4random_buf(buf, count); + } + return (count); +} +#else static int read_random_phony(void *buf, int count) { @@ -93,4 +91,14 @@ return (count); } +#endif + +static int (*read_func)(void *, int) = read_random_phony; + +/* Userland-visible version of read_random */ +int +read_random(void *buf, int count) +{ + return ((*read_func)(buf, count)); +}
diff --git a/usrsctplib/user_environment.h b/usrsctplib/user_environment.h index 306ff6b..6e37d07 100755 --- a/usrsctplib/user_environment.h +++ b/usrsctplib/user_environment.h
@@ -94,17 +94,18 @@ abort(); } -#define panic(...) \ - do { \ - SCTP_PRINTF(__VA_ARGS__);\ - SCTP_PRINTF("\n"); \ - terminate_non_graceful();\ +#define panic(...) \ + do { \ + SCTP_PRINTF("%s(): ", __FUNCTION__);\ + SCTP_PRINTF(__VA_ARGS__); \ + SCTP_PRINTF("\n"); \ + terminate_non_graceful(); \ } while (0) #define KASSERT(cond, args) \ do { \ if (!(cond)) { \ - panic args ;\ + panic args ; \ } \ } while (0) #else
diff --git a/usrsctplib/user_mbuf.c b/usrsctplib/user_mbuf.c index 7a1aaba..ec83931 100755 --- a/usrsctplib/user_mbuf.c +++ b/usrsctplib/user_mbuf.c
@@ -204,41 +204,41 @@ } -static int clust_constructor_dup(caddr_t m_clust, struct mbuf* m) +static void +clust_constructor_dup(caddr_t m_clust, struct mbuf* m) { u_int *refcnt; int type, size; + if (m == NULL) { + return; + } /* Assigning cluster of MCLBYTES. TODO: Add jumbo frame functionality */ type = EXT_CLUSTER; size = MCLBYTES; refcnt = SCTP_ZONE_GET(zone_ext_refcnt, u_int); /*refcnt = (u_int *)umem_cache_alloc(zone_ext_refcnt, UMEM_DEFAULT);*/ - if (refcnt == NULL) { #if !defined(SCTP_SIMPLE_ALLOCATOR) + if (refcnt == NULL) { umem_reap(); -#endif refcnt = SCTP_ZONE_GET(zone_ext_refcnt, u_int); /*refcnt = (u_int *)umem_cache_alloc(zone_ext_refcnt, UMEM_DEFAULT);*/ } +#endif *refcnt = 1; - if (m != NULL) { - m->m_ext.ext_buf = (caddr_t)m_clust; - m->m_data = m->m_ext.ext_buf; - m->m_flags |= M_EXT; - m->m_ext.ext_free = NULL; - m->m_ext.ext_args = NULL; - m->m_ext.ext_size = size; - m->m_ext.ext_type = type; - m->m_ext.ref_cnt = refcnt; - } - - return (0); + m->m_ext.ext_buf = (caddr_t)m_clust; + m->m_data = m->m_ext.ext_buf; + m->m_flags |= M_EXT; + m->m_ext.ext_free = NULL; + m->m_ext.ext_args = NULL; + m->m_ext.ext_size = size; + m->m_ext.ext_type = type; + m->m_ext.ref_cnt = refcnt; + return; } - /* __Userspace__ */ void m_clget(struct mbuf *m, int how)
diff --git a/usrsctplib/user_recv_thread.c b/usrsctplib/user_recv_thread.c index b1a9d01..b7cb06a 100755 --- a/usrsctplib/user_recv_thread.c +++ b/usrsctplib/user_recv_thread.c
@@ -361,13 +361,13 @@ i = 0; SCTP_BUF_LEN(recvmbuf[0]) = iovlen; - ncounter -= iovlen; + ncounter -= min(ncounter, iovlen); (to_fill)++; do { recvmbuf[i]->m_next = recvmbuf[i+1]; SCTP_BUF_LEN(recvmbuf[i]->m_next) = min(ncounter, iovlen); i++; - ncounter -= iovlen; + ncounter -= min(ncounter, iovlen); (to_fill)++; } while (ncounter > 0); } @@ -564,13 +564,13 @@ i = 0; SCTP_BUF_LEN(recvmbuf6[0]) = iovlen; - ncounter -= iovlen; + ncounter -= min(ncounter, iovlen); (to_fill)++; do { recvmbuf6[i]->m_next = recvmbuf6[i+1]; SCTP_BUF_LEN(recvmbuf6[i]->m_next) = min(ncounter, iovlen); i++; - ncounter -= iovlen; + ncounter -= min(ncounter, iovlen); (to_fill)++; } while (ncounter > 0); } @@ -764,13 +764,13 @@ i = 0; SCTP_BUF_LEN(udprecvmbuf[0]) = iovlen; - ncounter -= iovlen; + ncounter -= min(ncounter, iovlen); (to_fill)++; do { udprecvmbuf[i]->m_next = udprecvmbuf[i+1]; SCTP_BUF_LEN(udprecvmbuf[i]->m_next) = min(ncounter, iovlen); i++; - ncounter -= iovlen; + ncounter -= min(ncounter, iovlen); (to_fill)++; } while (ncounter > 0); } @@ -978,13 +978,13 @@ i = 0; SCTP_BUF_LEN(udprecvmbuf6[0]) = iovlen; - ncounter -= iovlen; + ncounter -= min(ncounter, iovlen); (to_fill)++; do { udprecvmbuf6[i]->m_next = udprecvmbuf6[i+1]; SCTP_BUF_LEN(udprecvmbuf6[i]->m_next) = min(ncounter, iovlen); i++; - ncounter -= iovlen; + ncounter -= min(ncounter, iovlen); (to_fill)++; } while (ncounter > 0); }
diff --git a/usrsctplib/user_socket.c b/usrsctplib/user_socket.c index 1f5f77f..8122e58 100755 --- a/usrsctplib/user_socket.c +++ b/usrsctplib/user_socket.c
@@ -2436,6 +2436,121 @@ } int +usrsctp_opt_info(struct socket *so, sctp_assoc_t id, int opt, void *arg, socklen_t *size) +{ + if (arg == NULL) { + errno = EINVAL; + return (-1); + } + if ((id == SCTP_CURRENT_ASSOC) || + (id == SCTP_ALL_ASSOC)) { + errno = EINVAL; + return (-1); + } + switch (opt) { + case SCTP_RTOINFO: + ((struct sctp_rtoinfo *)arg)->srto_assoc_id = id; + break; + case SCTP_ASSOCINFO: + ((struct sctp_assocparams *)arg)->sasoc_assoc_id = id; + break; + case SCTP_DEFAULT_SEND_PARAM: + ((struct sctp_assocparams *)arg)->sasoc_assoc_id = id; + break; + case SCTP_PRIMARY_ADDR: + ((struct sctp_setprim *)arg)->ssp_assoc_id = id; + break; + case SCTP_PEER_ADDR_PARAMS: + ((struct sctp_paddrparams *)arg)->spp_assoc_id = id; + break; + case SCTP_MAXSEG: + ((struct sctp_assoc_value *)arg)->assoc_id = id; + break; + case SCTP_AUTH_KEY: + ((struct sctp_authkey *)arg)->sca_assoc_id = id; + break; + case SCTP_AUTH_ACTIVE_KEY: + ((struct sctp_authkeyid *)arg)->scact_assoc_id = id; + break; + case SCTP_DELAYED_SACK: + ((struct sctp_sack_info *)arg)->sack_assoc_id = id; + break; + case SCTP_CONTEXT: + ((struct sctp_assoc_value *)arg)->assoc_id = id; + break; + case SCTP_STATUS: + ((struct sctp_status *)arg)->sstat_assoc_id = id; + break; + case SCTP_GET_PEER_ADDR_INFO: + ((struct sctp_paddrinfo *)arg)->spinfo_assoc_id = id; + break; + case SCTP_PEER_AUTH_CHUNKS: + ((struct sctp_authchunks *)arg)->gauth_assoc_id = id; + break; + case SCTP_LOCAL_AUTH_CHUNKS: + ((struct sctp_authchunks *)arg)->gauth_assoc_id = id; + break; + case SCTP_TIMEOUTS: + ((struct sctp_timeouts *)arg)->stimo_assoc_id = id; + break; + case SCTP_EVENT: + ((struct sctp_event *)arg)->se_assoc_id = id; + break; + case SCTP_DEFAULT_SNDINFO: + ((struct sctp_sndinfo *)arg)->snd_assoc_id = id; + break; + case SCTP_DEFAULT_PRINFO: + ((struct sctp_default_prinfo *)arg)->pr_assoc_id = id; + break; + case SCTP_PEER_ADDR_THLDS: + ((struct sctp_paddrthlds *)arg)->spt_assoc_id = id; + break; + case SCTP_REMOTE_UDP_ENCAPS_PORT: + ((struct sctp_udpencaps *)arg)->sue_assoc_id = id; + break; + case SCTP_ECN_SUPPORTED: + ((struct sctp_assoc_value *)arg)->assoc_id = id; + break; + case SCTP_PR_SUPPORTED: + ((struct sctp_assoc_value *)arg)->assoc_id = id; + break; + case SCTP_AUTH_SUPPORTED: + ((struct sctp_assoc_value *)arg)->assoc_id = id; + break; + case SCTP_ASCONF_SUPPORTED: + ((struct sctp_assoc_value *)arg)->assoc_id = id; + break; + case SCTP_RECONFIG_SUPPORTED: + ((struct sctp_assoc_value *)arg)->assoc_id = id; + break; + case SCTP_NRSACK_SUPPORTED: + ((struct sctp_assoc_value *)arg)->assoc_id = id; + break; + case SCTP_PKTDROP_SUPPORTED: + ((struct sctp_assoc_value *)arg)->assoc_id = id; + break; + case SCTP_MAX_BURST: + ((struct sctp_assoc_value *)arg)->assoc_id = id; + break; + case SCTP_ENABLE_STREAM_RESET: + ((struct sctp_assoc_value *)arg)->assoc_id = id; + break; + case SCTP_PR_STREAM_STATUS: + ((struct sctp_prstatus *)arg)->sprstat_assoc_id = id; + break; + case SCTP_PR_ASSOC_STATUS: + ((struct sctp_prstatus *)arg)->sprstat_assoc_id = id; + break; + case SCTP_MAX_CWND: + ((struct sctp_assoc_value *)arg)->assoc_id = id; + break; + default: + break; + } + return (usrsctp_getsockopt(so, IPPROTO_SCTP, opt, arg, size)); +} + +int usrsctp_set_ulpinfo(struct socket *so, void *ulp_info) { return (register_ulp_info(so, ulp_info)); @@ -2657,9 +2772,13 @@ return (-1); } #endif + len += sizeof(struct sockaddr_in); + if (len > SCTP_STACK_BUF_SIZE) { + errno = ENOMEM; + return (-1); + } memcpy(cpto, at, sizeof(struct sockaddr_in)); cpto = ((caddr_t)cpto + sizeof(struct sockaddr_in)); - len += sizeof(struct sockaddr_in); at = (struct sockaddr *)((caddr_t)at + sizeof(struct sockaddr_in)); break; #endif @@ -2673,18 +2792,30 @@ #endif #ifdef INET if (IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)at)->sin6_addr)) { + len += sizeof(struct sockaddr_in); + if (len > SCTP_STACK_BUF_SIZE) { + errno = ENOMEM; + return (-1); + } in6_sin6_2_sin((struct sockaddr_in *)cpto, (struct sockaddr_in6 *)at); cpto = ((caddr_t)cpto + sizeof(struct sockaddr_in)); - len += sizeof(struct sockaddr_in); } else { + len += sizeof(struct sockaddr_in6); + if (len > SCTP_STACK_BUF_SIZE) { + errno = ENOMEM; + return (-1); + } memcpy(cpto, at, sizeof(struct sockaddr_in6)); cpto = ((caddr_t)cpto + sizeof(struct sockaddr_in6)); - len += sizeof(struct sockaddr_in6); } #else + len += sizeof(struct sockaddr_in6); + if (len > SCTP_STACK_BUF_SIZE) { + errno = ENOMEM; + return (-1); + } memcpy(cpto, at, sizeof(struct sockaddr_in6)); cpto = ((caddr_t)cpto + sizeof(struct sockaddr_in6)); - len += sizeof(struct sockaddr_in6); #endif at = (struct sockaddr *)((caddr_t)at + sizeof(struct sockaddr_in6)); break; @@ -2693,18 +2824,8 @@ errno = EINVAL; return (-1); } - if (len > (sizeof(buf) - sizeof(int))) { - /* Never enough memory */ - errno = E2BIG; - return (-1); - } cnt++; } - /* do we have any? */ - if (cnt == 0) { - errno = EINVAL; - return (-1); - } aa = (int *)buf; *aa = cnt; ret = usrsctp_setsockopt(so, IPPROTO_SCTP, SCTP_CONNECT_X, (void *)buf, (socklen_t)len);
diff --git a/usrsctplib/usrsctp.h b/usrsctplib/usrsctp.h index 6c98033..70b719a 100644 --- a/usrsctplib/usrsctp.h +++ b/usrsctplib/usrsctp.h
@@ -898,6 +898,13 @@ socklen_t *option_len); int +usrsctp_opt_info(struct socket *so, + sctp_assoc_t id, + int opt, + void *arg, + socklen_t *size); + +int usrsctp_getpaddrs(struct socket *so, sctp_assoc_t id, struct sockaddr **raddrs);