diff options
author | Allan Sandfeld Jensen <allan.jensen@theqtcompany.com> | 2016-01-25 11:39:07 +0100 |
---|---|---|
committer | Oswald Buddenhagen <oswald.buddenhagen@theqtcompany.com> | 2016-01-25 15:20:42 +0000 |
commit | 6c91641271e536ffaa88a1dff5127e42ee99a91e (patch) | |
tree | 703d9dd49602377ddc90cbf886aad37913f2496b /chromium/third_party/usrsctp | |
parent | b145b7fafd36f0c260d6a768c81fc14e32578099 (diff) | |
download | qtwebengine-chromium-6c91641271e536ffaa88a1dff5127e42ee99a91e.tar.gz |
BASELINE: Update Chromium to 49.0.2623.23
Also adds missing printing sources.
Change-Id: I3726b8f0c7d6751c9fc846096c571fadca7108cd
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@theqtcompany.com>
Diffstat (limited to 'chromium/third_party/usrsctp')
92 files changed, 11004 insertions, 1579 deletions
diff --git a/chromium/third_party/usrsctp/BUILD.gn b/chromium/third_party/usrsctp/BUILD.gn index 0069a2e6b43..8c38fb82091 100644 --- a/chromium/third_party/usrsctp/BUILD.gn +++ b/chromium/third_party/usrsctp/BUILD.gn @@ -2,12 +2,10 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import("//build/config/crypto.gni") - config("usrsctp_config") { include_dirs = [ - "usrsctplib", - "usrsctplib/netinet", + "usrsctplib/usrsctplib", + "usrsctplib/usrsctplib/netinet", ] } @@ -20,67 +18,67 @@ config("usrsctp_warnings") { static_library("usrsctp") { sources = [ - "usrsctplib/netinet/sctp.h", - "usrsctplib/netinet/sctp_asconf.c", - "usrsctplib/netinet/sctp_asconf.h", - "usrsctplib/netinet/sctp_auth.c", - "usrsctplib/netinet/sctp_auth.h", - "usrsctplib/netinet/sctp_bsd_addr.c", - "usrsctplib/netinet/sctp_bsd_addr.h", - "usrsctplib/netinet/sctp_callout.c", - "usrsctplib/netinet/sctp_callout.h", - "usrsctplib/netinet/sctp_cc_functions.c", - "usrsctplib/netinet/sctp_constants.h", - "usrsctplib/netinet/sctp_crc32.c", - "usrsctplib/netinet/sctp_crc32.h", - "usrsctplib/netinet/sctp_header.h", - "usrsctplib/netinet/sctp_indata.c", - "usrsctplib/netinet/sctp_indata.h", - "usrsctplib/netinet/sctp_input.c", - "usrsctplib/netinet/sctp_input.h", - "usrsctplib/netinet/sctp_lock_userspace.h", - "usrsctplib/netinet/sctp_os.h", - "usrsctplib/netinet/sctp_os_userspace.h", - "usrsctplib/netinet/sctp_output.c", - "usrsctplib/netinet/sctp_output.h", - "usrsctplib/netinet/sctp_pcb.c", - "usrsctplib/netinet/sctp_pcb.h", - "usrsctplib/netinet/sctp_peeloff.c", - "usrsctplib/netinet/sctp_peeloff.h", - "usrsctplib/netinet/sctp_process_lock.h", - "usrsctplib/netinet/sctp_sha1.c", - "usrsctplib/netinet/sctp_sha1.h", - "usrsctplib/netinet/sctp_ss_functions.c", - "usrsctplib/netinet/sctp_structs.h", - "usrsctplib/netinet/sctp_sysctl.c", - "usrsctplib/netinet/sctp_sysctl.h", - "usrsctplib/netinet/sctp_timer.c", - "usrsctplib/netinet/sctp_timer.h", - "usrsctplib/netinet/sctp_uio.h", - "usrsctplib/netinet/sctp_userspace.c", - "usrsctplib/netinet/sctp_usrreq.c", - "usrsctplib/netinet/sctp_var.h", - "usrsctplib/netinet/sctputil.c", - "usrsctplib/netinet/sctputil.h", - "usrsctplib/netinet6/sctp6_usrreq.c", - "usrsctplib/netinet6/sctp6_var.h", - "usrsctplib/user_atomic.h", - "usrsctplib/user_environment.c", - "usrsctplib/user_environment.h", - "usrsctplib/user_inpcb.h", - "usrsctplib/user_ip6_var.h", - "usrsctplib/user_ip_icmp.h", - "usrsctplib/user_malloc.h", - "usrsctplib/user_mbuf.c", - "usrsctplib/user_mbuf.h", - "usrsctplib/user_queue.h", - "usrsctplib/user_recv_thread.c", - "usrsctplib/user_recv_thread.h", - "usrsctplib/user_route.h", - "usrsctplib/user_socket.c", - "usrsctplib/user_socketvar.h", - "usrsctplib/user_uma.h", - "usrsctplib/usrsctp.h", + "usrsctplib/usrsctplib/netinet/sctp.h", + "usrsctplib/usrsctplib/netinet/sctp_asconf.c", + "usrsctplib/usrsctplib/netinet/sctp_asconf.h", + "usrsctplib/usrsctplib/netinet/sctp_auth.c", + "usrsctplib/usrsctplib/netinet/sctp_auth.h", + "usrsctplib/usrsctplib/netinet/sctp_bsd_addr.c", + "usrsctplib/usrsctplib/netinet/sctp_bsd_addr.h", + "usrsctplib/usrsctplib/netinet/sctp_callout.c", + "usrsctplib/usrsctplib/netinet/sctp_callout.h", + "usrsctplib/usrsctplib/netinet/sctp_cc_functions.c", + "usrsctplib/usrsctplib/netinet/sctp_constants.h", + "usrsctplib/usrsctplib/netinet/sctp_crc32.c", + "usrsctplib/usrsctplib/netinet/sctp_crc32.h", + "usrsctplib/usrsctplib/netinet/sctp_header.h", + "usrsctplib/usrsctplib/netinet/sctp_indata.c", + "usrsctplib/usrsctplib/netinet/sctp_indata.h", + "usrsctplib/usrsctplib/netinet/sctp_input.c", + "usrsctplib/usrsctplib/netinet/sctp_input.h", + "usrsctplib/usrsctplib/netinet/sctp_lock_userspace.h", + "usrsctplib/usrsctplib/netinet/sctp_os.h", + "usrsctplib/usrsctplib/netinet/sctp_os_userspace.h", + "usrsctplib/usrsctplib/netinet/sctp_output.c", + "usrsctplib/usrsctplib/netinet/sctp_output.h", + "usrsctplib/usrsctplib/netinet/sctp_pcb.c", + "usrsctplib/usrsctplib/netinet/sctp_pcb.h", + "usrsctplib/usrsctplib/netinet/sctp_peeloff.c", + "usrsctplib/usrsctplib/netinet/sctp_peeloff.h", + "usrsctplib/usrsctplib/netinet/sctp_process_lock.h", + "usrsctplib/usrsctplib/netinet/sctp_sha1.c", + "usrsctplib/usrsctplib/netinet/sctp_sha1.h", + "usrsctplib/usrsctplib/netinet/sctp_ss_functions.c", + "usrsctplib/usrsctplib/netinet/sctp_structs.h", + "usrsctplib/usrsctplib/netinet/sctp_sysctl.c", + "usrsctplib/usrsctplib/netinet/sctp_sysctl.h", + "usrsctplib/usrsctplib/netinet/sctp_timer.c", + "usrsctplib/usrsctplib/netinet/sctp_timer.h", + "usrsctplib/usrsctplib/netinet/sctp_uio.h", + "usrsctplib/usrsctplib/netinet/sctp_userspace.c", + "usrsctplib/usrsctplib/netinet/sctp_usrreq.c", + "usrsctplib/usrsctplib/netinet/sctp_var.h", + "usrsctplib/usrsctplib/netinet/sctputil.c", + "usrsctplib/usrsctplib/netinet/sctputil.h", + "usrsctplib/usrsctplib/netinet6/sctp6_usrreq.c", + "usrsctplib/usrsctplib/netinet6/sctp6_var.h", + "usrsctplib/usrsctplib/user_atomic.h", + "usrsctplib/usrsctplib/user_environment.c", + "usrsctplib/usrsctplib/user_environment.h", + "usrsctplib/usrsctplib/user_inpcb.h", + "usrsctplib/usrsctplib/user_ip6_var.h", + "usrsctplib/usrsctplib/user_ip_icmp.h", + "usrsctplib/usrsctplib/user_malloc.h", + "usrsctplib/usrsctplib/user_mbuf.c", + "usrsctplib/usrsctplib/user_mbuf.h", + "usrsctplib/usrsctplib/user_queue.h", + "usrsctplib/usrsctplib/user_recv_thread.c", + "usrsctplib/usrsctplib/user_recv_thread.h", + "usrsctplib/usrsctplib/user_route.h", + "usrsctplib/usrsctplib/user_socket.c", + "usrsctplib/usrsctplib/user_socketvar.h", + "usrsctplib/usrsctplib/user_uma.h", + "usrsctplib/usrsctplib/usrsctp.h", ] defines = [ @@ -104,8 +102,16 @@ static_library("usrsctp") { public_configs = [ ":usrsctp_config" ] + cflags = [ + "-UINET", + "-UINET6", + ] + if (is_linux || is_android) { - defines += [ "__Userspace_os_Linux" ] + defines += [ + "__Userspace_os_Linux", + "_GNU_SOURCE", + ] } else if (is_mac || is_ios) { defines += [ "HAVE_SA_LEN", @@ -113,6 +119,7 @@ static_library("usrsctp") { "__APPLE_USE_RFC_2292", "__Userspace_os_Darwin", ] + cflags += [ "-U__APPLE__" ] } if (is_win) { diff --git a/chromium/third_party/usrsctp/README.chromium b/chromium/third_party/usrsctp/README.chromium index 464699e2cd8..fa30f26e25e 100644 --- a/chromium/third_party/usrsctp/README.chromium +++ b/chromium/third_party/usrsctp/README.chromium @@ -1,9 +1,9 @@ Name: usrsctp -URL: http://sctp-refimpl.googlecode.com/svn/trunk/KERN/usrsctp +URL: http://github.com/sctplab/usrsctp Version: 0 -Date: 8 July 2014 -Revision: 9045 -License: New BSD License +Date: 4 Nov 2015 +Revision: ef6e3302205dbadf0584b712f53e48159be2dffb +License: New BSD License File: LICENSE Security Critical: yes diff --git a/chromium/third_party/usrsctp/usrsctp.gyp b/chromium/third_party/usrsctp/usrsctp.gyp index b4a86b245a1..9533fb8ed12 100644 --- a/chromium/third_party/usrsctp/usrsctp.gyp +++ b/chromium/third_party/usrsctp/usrsctp.gyp @@ -14,16 +14,16 @@ # 'SCTP_DEBUG', # Uncomment for SCTP debugging. ], 'include_dirs': [ - 'usrsctplib/', - 'usrsctplib/netinet', + 'usrsctplib/usrsctplib/', + 'usrsctplib/usrsctplib/netinet', ], 'dependencies': [ '<(DEPTH)/third_party/boringssl/boringssl.gyp:boringssl', ], 'direct_dependent_settings': { 'include_dirs': [ - 'usrsctplib/', - 'usrsctplib/netinet', + 'usrsctplib/usrsctplib/', + 'usrsctplib/usrsctplib/netinet', ], }, }, @@ -34,67 +34,67 @@ 'type': 'static_library', 'sources': [ # Note: sources list duplicated in GN build. - 'usrsctplib/netinet/sctp.h', - 'usrsctplib/netinet/sctp_asconf.c', - 'usrsctplib/netinet/sctp_asconf.h', - 'usrsctplib/netinet/sctp_auth.c', - 'usrsctplib/netinet/sctp_auth.h', - 'usrsctplib/netinet/sctp_bsd_addr.c', - 'usrsctplib/netinet/sctp_bsd_addr.h', - 'usrsctplib/netinet/sctp_callout.c', - 'usrsctplib/netinet/sctp_callout.h', - 'usrsctplib/netinet/sctp_cc_functions.c', - 'usrsctplib/netinet/sctp_constants.h', - 'usrsctplib/netinet/sctp_crc32.c', - 'usrsctplib/netinet/sctp_crc32.h', - 'usrsctplib/netinet/sctp_header.h', - 'usrsctplib/netinet/sctp_indata.c', - 'usrsctplib/netinet/sctp_indata.h', - 'usrsctplib/netinet/sctp_input.c', - 'usrsctplib/netinet/sctp_input.h', - 'usrsctplib/netinet/sctp_lock_userspace.h', - 'usrsctplib/netinet/sctp_os.h', - 'usrsctplib/netinet/sctp_os_userspace.h', - 'usrsctplib/netinet/sctp_output.c', - 'usrsctplib/netinet/sctp_output.h', - 'usrsctplib/netinet/sctp_pcb.c', - 'usrsctplib/netinet/sctp_pcb.h', - 'usrsctplib/netinet/sctp_peeloff.c', - 'usrsctplib/netinet/sctp_peeloff.h', - 'usrsctplib/netinet/sctp_process_lock.h', - 'usrsctplib/netinet/sctp_sha1.c', - 'usrsctplib/netinet/sctp_sha1.h', - 'usrsctplib/netinet/sctp_ss_functions.c', - 'usrsctplib/netinet/sctp_structs.h', - 'usrsctplib/netinet/sctp_sysctl.c', - 'usrsctplib/netinet/sctp_sysctl.h', - 'usrsctplib/netinet/sctp_timer.c', - 'usrsctplib/netinet/sctp_timer.h', - 'usrsctplib/netinet/sctp_uio.h', - 'usrsctplib/netinet/sctp_userspace.c', - 'usrsctplib/netinet/sctp_usrreq.c', - 'usrsctplib/netinet/sctp_var.h', - 'usrsctplib/netinet/sctputil.c', - 'usrsctplib/netinet/sctputil.h', - 'usrsctplib/netinet6/sctp6_usrreq.c', - 'usrsctplib/netinet6/sctp6_var.h', - 'usrsctplib/user_atomic.h', - 'usrsctplib/user_environment.c', - 'usrsctplib/user_environment.h', - 'usrsctplib/user_inpcb.h', - 'usrsctplib/user_ip6_var.h', - 'usrsctplib/user_ip_icmp.h', - 'usrsctplib/user_malloc.h', - 'usrsctplib/user_mbuf.c', - 'usrsctplib/user_mbuf.h', - 'usrsctplib/user_queue.h', - 'usrsctplib/user_recv_thread.c', - 'usrsctplib/user_recv_thread.h', - 'usrsctplib/user_route.h', - 'usrsctplib/user_socket.c', - 'usrsctplib/user_socketvar.h', - 'usrsctplib/user_uma.h', - 'usrsctplib/usrsctp.h' + 'usrsctplib/usrsctplib/netinet/sctp.h', + 'usrsctplib/usrsctplib/netinet/sctp_asconf.c', + 'usrsctplib/usrsctplib/netinet/sctp_asconf.h', + 'usrsctplib/usrsctplib/netinet/sctp_auth.c', + 'usrsctplib/usrsctplib/netinet/sctp_auth.h', + 'usrsctplib/usrsctplib/netinet/sctp_bsd_addr.c', + 'usrsctplib/usrsctplib/netinet/sctp_bsd_addr.h', + 'usrsctplib/usrsctplib/netinet/sctp_callout.c', + 'usrsctplib/usrsctplib/netinet/sctp_callout.h', + 'usrsctplib/usrsctplib/netinet/sctp_cc_functions.c', + 'usrsctplib/usrsctplib/netinet/sctp_constants.h', + 'usrsctplib/usrsctplib/netinet/sctp_crc32.c', + 'usrsctplib/usrsctplib/netinet/sctp_crc32.h', + 'usrsctplib/usrsctplib/netinet/sctp_header.h', + 'usrsctplib/usrsctplib/netinet/sctp_indata.c', + 'usrsctplib/usrsctplib/netinet/sctp_indata.h', + 'usrsctplib/usrsctplib/netinet/sctp_input.c', + 'usrsctplib/usrsctplib/netinet/sctp_input.h', + 'usrsctplib/usrsctplib/netinet/sctp_lock_userspace.h', + 'usrsctplib/usrsctplib/netinet/sctp_os.h', + 'usrsctplib/usrsctplib/netinet/sctp_os_userspace.h', + 'usrsctplib/usrsctplib/netinet/sctp_output.c', + 'usrsctplib/usrsctplib/netinet/sctp_output.h', + 'usrsctplib/usrsctplib/netinet/sctp_pcb.c', + 'usrsctplib/usrsctplib/netinet/sctp_pcb.h', + 'usrsctplib/usrsctplib/netinet/sctp_peeloff.c', + 'usrsctplib/usrsctplib/netinet/sctp_peeloff.h', + 'usrsctplib/usrsctplib/netinet/sctp_process_lock.h', + 'usrsctplib/usrsctplib/netinet/sctp_sha1.c', + 'usrsctplib/usrsctplib/netinet/sctp_sha1.h', + 'usrsctplib/usrsctplib/netinet/sctp_ss_functions.c', + 'usrsctplib/usrsctplib/netinet/sctp_structs.h', + 'usrsctplib/usrsctplib/netinet/sctp_sysctl.c', + 'usrsctplib/usrsctplib/netinet/sctp_sysctl.h', + 'usrsctplib/usrsctplib/netinet/sctp_timer.c', + 'usrsctplib/usrsctplib/netinet/sctp_timer.h', + 'usrsctplib/usrsctplib/netinet/sctp_uio.h', + 'usrsctplib/usrsctplib/netinet/sctp_userspace.c', + 'usrsctplib/usrsctplib/netinet/sctp_usrreq.c', + 'usrsctplib/usrsctplib/netinet/sctp_var.h', + 'usrsctplib/usrsctplib/netinet/sctputil.c', + 'usrsctplib/usrsctplib/netinet/sctputil.h', + 'usrsctplib/usrsctplib/netinet6/sctp6_usrreq.c', + 'usrsctplib/usrsctplib/netinet6/sctp6_var.h', + 'usrsctplib/usrsctplib/user_atomic.h', + 'usrsctplib/usrsctplib/user_environment.c', + 'usrsctplib/usrsctplib/user_environment.h', + 'usrsctplib/usrsctplib/user_inpcb.h', + 'usrsctplib/usrsctplib/user_ip6_var.h', + 'usrsctplib/usrsctplib/user_ip_icmp.h', + 'usrsctplib/usrsctplib/user_malloc.h', + 'usrsctplib/usrsctplib/user_mbuf.c', + 'usrsctplib/usrsctplib/user_mbuf.h', + 'usrsctplib/usrsctplib/user_queue.h', + 'usrsctplib/usrsctplib/user_recv_thread.c', + 'usrsctplib/usrsctplib/user_recv_thread.h', + 'usrsctplib/usrsctplib/user_route.h', + 'usrsctplib/usrsctplib/user_socket.c', + 'usrsctplib/usrsctplib/user_socketvar.h', + 'usrsctplib/usrsctplib/user_uma.h', + 'usrsctplib/usrsctplib/usrsctp.h', ], # sources 'variables': { 'clang_warning_flags': [ @@ -106,6 +106,7 @@ ['OS=="linux" or OS=="android"', { 'defines': [ '__Userspace_os_Linux', + '_GNU_SOURCE' ], 'cflags!': [ '-Werror', '-Wall' ], 'cflags': [ '-w' ], @@ -130,15 +131,15 @@ 'defines': [ '__Userspace_os_Windows', # Manually setting WINVER and _WIN32_WINNT is needed because Chrome - # sets WINVER to a newer version of windows. But compiling usrsctp - # this way would is incompatible with windows XP. + # sets WINVER to a newer version of Windows. But compiling usrsctp + # this way would be incompatible with Windows XP. 'WINVER=0x0502', '_WIN32_WINNT=0x0502', ], 'defines!': [ # Remove Chrome's WINVER defines to avoid redefinition warnings. - 'WINVER=0x0603', - '_WIN32_WINNT=0x0603', + 'WINVER=0x0A00', + '_WIN32_WINNT=0x0A00', ], 'cflags!': [ '/W3', '/WX' ], 'cflags': [ '/w' ], diff --git a/chromium/third_party/usrsctp/usrsctplib/.cvsignore b/chromium/third_party/usrsctp/usrsctplib/.cvsignore deleted file mode 100644 index bd6854532e5..00000000000 --- a/chromium/third_party/usrsctp/usrsctplib/.cvsignore +++ /dev/null @@ -1,7 +0,0 @@ -.deps -.libs -Makefile -Makefile.in -*.lo -*.la -*.lib diff --git a/chromium/third_party/usrsctp/usrsctplib/CMakeLists.txt b/chromium/third_party/usrsctp/usrsctplib/CMakeLists.txt new file mode 100644 index 00000000000..36d0ed3081c --- /dev/null +++ b/chromium/third_party/usrsctp/usrsctplib/CMakeLists.txt @@ -0,0 +1,35 @@ +# +# Copyright (C) 2015-2015 Oleg Alexeenkov +# Copyright (C) 2015-2015 Felix Weinrank +# +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the project nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# + +cmake_minimum_required(VERSION 2.6) +message(">> WARNINING: CMAKE SUPPORT IS EXPERIMENTAL <<") +add_subdirectory(usrsctplib) +add_subdirectory(programs) diff --git a/chromium/third_party/usrsctp/usrsctplib/LICENSE.md b/chromium/third_party/usrsctp/usrsctplib/LICENSE.md new file mode 100644 index 00000000000..a2d1f989cff --- /dev/null +++ b/chromium/third_party/usrsctp/usrsctplib/LICENSE.md @@ -0,0 +1,27 @@ +Copyright (c) 2015, Randall Stewart and Michael Tuexen +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of usrsctp nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/chromium/third_party/usrsctp/usrsctplib/Makefile.am b/chromium/third_party/usrsctp/usrsctplib/Makefile.am index 85240b7cea8..de364243d11 100644 --- a/chromium/third_party/usrsctp/usrsctplib/Makefile.am +++ b/chromium/third_party/usrsctp/usrsctplib/Makefile.am @@ -28,54 +28,6 @@ # SUCH DAMAGE. # -AUTOMAKE_OPTIONS = subdir-objects -EXTRA_DIST = Makefile.nmake -lib_LTLIBRARIES = libusrsctp.la -libusrsctp_la_SOURCES = user_atomic.h \ - user_environment.c user_environment.h \ - user_inpcb.h \ - user_ip_icmp.h \ - user_ip6_var.h \ - user_malloc.h \ - user_mbuf.c \ - user_mbuf.h \ - user_queue.h \ - user_recv_thread.c user_recv_thread.h \ - user_route.h \ - user_socket.c \ - user_socketvar.h \ - user_uma.h \ - netinet/sctp.h \ - netinet/sctp_asconf.c netinet/sctp_asconf.h \ - netinet/sctp_auth.c netinet/sctp_auth.h \ - netinet/sctp_bsd_addr.c netinet/sctp_bsd_addr.h \ - netinet/sctp_callout.c netinet/sctp_callout.h \ - netinet/sctp_cc_functions.c \ - netinet/sctp_constants.h \ - netinet/sctp_crc32.c netinet/sctp_crc32.h \ - netinet/sctp_header.h \ - netinet/sctp_indata.c netinet/sctp_indata.h \ - netinet/sctp_input.c netinet/sctp_input.h \ - netinet/sctp_lock_userspace.h \ - netinet/sctp_os.h \ - netinet/sctp_os_userspace.h \ - netinet/sctp_output.c netinet/sctp_output.h \ - netinet/sctp_pcb.c netinet/sctp_pcb.h \ - netinet/sctp_peeloff.c netinet/sctp_peeloff.h \ - netinet/sctp_process_lock.h \ - netinet/sctp_sha1.c netinet/sctp_sha1.h \ - netinet/sctp_ss_functions.c \ - netinet/sctp_structs.h \ - netinet/sctp_sysctl.c netinet/sctp_sysctl.h \ - netinet/sctp_userspace.c \ - netinet/sctp_timer.c netinet/sctp_timer.h \ - netinet/sctp_uio.h \ - netinet/sctp_usrreq.c \ - netinet/sctp_var.h \ - netinet/sctputil.c netinet/sctputil.h \ - netinet6/sctp6_var.h \ - netinet6/sctp6_usrreq.c -libusrsctp_la_CFLAGS = $(LIBCFLAGS) -libusrsctp_la_LDFLAGS = -version-info 1:0:0 -include_HEADERS = usrsctp.h - +SUBDIRS = usrsctplib programs +EXTRA_DIST = bootstrap Makefile.nmake +ACLOCAL_AMFLAGS = -I m4 diff --git a/chromium/third_party/usrsctp/usrsctplib/Makefile.nmake b/chromium/third_party/usrsctp/usrsctplib/Makefile.nmake index e16dc1e7875..c439c8b3a71 100644 --- a/chromium/third_party/usrsctp/usrsctplib/Makefile.nmake +++ b/chromium/third_party/usrsctp/usrsctplib/Makefile.nmake @@ -28,152 +28,18 @@ # SUCH DAMAGE. # -CFLAGS=/I. /W3 /WX - -CVARSDLL=-DSCTP_DEBUG -DSCTP_SIMPLE_ALLOCATOR -DSCTP_PROCESS_LEVEL_LOCKS -CVARSDLL=$(CVARSDLL) -D__Userspace__ -D__Userspace_os_Windows -CVARSDLL=$(CVARSDLL) -DINET -DINET6 -CVARSDLL=$(CVARSDLL) -D_LIB - -LINKFLAGS=/LIBPATH:. Ws2_32.lib - -usrsctp_OBJECTS = \ - user_environment.obj \ - user_mbuf.obj \ - user_recv_thread.obj \ - user_socket.obj \ - sctp_asconf.obj \ - sctp_auth.obj \ - sctp_bsd_addr.obj \ - sctp_callout.obj \ - sctp_cc_functions.obj \ - sctp_crc32.obj \ - sctp_indata.obj \ - sctp_input.obj \ - sctp_output.obj \ - sctp_pcb.obj \ - sctp_peeloff.obj \ - sctp_sha1.obj \ - sctp_ss_functions.obj \ - sctp_sysctl.obj \ - sctp_timer.obj \ - sctp_userspace.obj \ - sctp_usrreq.obj \ - sctputil.obj \ - sctp6_usrreq.obj - -usrsctp_HEADERS = \ - user_atomic.h \ - user_environment.h \ - user_inpcb.h \ - user_ip6_var.h \ - user_malloc.h \ - user_mbuf.h \ - user_recv_thread.h \ - user_route.h \ - user_socketvar.h \ - user_uma.h \ - user_queue.h \ - user_ip_icmp.h \ - user_ip6_var.h \ - netinet\sctp.h \ - 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.h \ - netinet\sctp_os_userspace.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 \ - netinet6\sctp6_var.h - -usrsctp.lib : $(usrsctp_OBJECTS) - lib /out:usrsctp.lib $(LINKFLAGS) $(usrsctp_OBJECTS) - -user_environment.obj : user_environment.c $(usrsctp_HEADERS) - cl $(CVARSDLL) $(CFLAGS) -c user_environment.c - -user_mbuf.obj : user_mbuf.c $(usrsctp_HEADERS) - cl $(CVARSDLL) $(CFLAGS) -c user_mbuf.c - -user_recv_thread.obj: user_recv_thread.c $(usrsctp_HEADERS) - cl $(CVARSDLL) $(CFLAGS) -c user_recv_thread.c - -user_socket.obj : user_socket.c $(usrsctp_HEADERS) - cl $(CVARSDLL) $(CFLAGS) -c user_socket.c - -sctp_asconf.obj : netinet\sctp_asconf.c $(usrsctp_HEADERS) - cl $(CVARSDLL) $(CFLAGS) -c netinet\sctp_asconf.c - -sctp_auth.obj : netinet\sctp_auth.c $(usrsctp_HEADERS) - cl $(CVARSDLL) $(CFLAGS) -c netinet\sctp_auth.c - -sctp_bsd_addr.obj : netinet\sctp_bsd_addr.c $(usrsctp_HEADERS) - cl $(CVARSDLL) $(CFLAGS) -c netinet\sctp_bsd_addr.c - -sctp_callout.obj : netinet\sctp_callout.c $(usrsctp_HEADERS) - cl $(CVARSDLL) $(CFLAGS) -c netinet\sctp_callout.c - -sctp_cc_functions.obj : netinet\sctp_cc_functions.c $(usrsctp_HEADERS) - cl $(CVARSDLL) $(CFLAGS) -c netinet\sctp_cc_functions.c - -sctp_crc32.obj : netinet\sctp_crc32.c $(usrsctp_HEADERS) - cl $(CVARSDLL) $(CFLAGS) -c netinet\sctp_crc32.c - -sctp_indata.obj : netinet\sctp_indata.c $(usrsctp_HEADERS) - cl $(CVARSDLL) $(CFLAGS) -c netinet\sctp_indata.c - -sctp_input.obj : netinet\sctp_input.c $(usrsctp_HEADERS) - cl $(CVARSDLL) $(CFLAGS) -c netinet\sctp_input.c - -sctp_output.obj : netinet\sctp_output.c $(usrsctp_HEADERS) - cl $(CVARSDLL) $(CFLAGS) -c netinet\sctp_output.c - -sctp_pcb.obj : netinet\sctp_pcb.c $(usrsctp_HEADERS) - cl $(CVARSDLL) $(CFLAGS) -c netinet\sctp_pcb.c - -sctp_peeloff.obj : netinet\sctp_peeloff.c $(usrsctp_HEADERS) - cl $(CVARSDLL) $(CFLAGS) -c netinet\sctp_peeloff.c - -sctp_sha1.obj : netinet\sctp_sha1.c $(usrsctp_HEADERS) - cl $(CVARSDLL) $(CFLAGS) -c netinet\sctp_sha1.c - -sctp_ss_functions.obj : netinet\sctp_ss_functions.c $(usrsctp_HEADERS) - cl $(CVARSDLL) $(CFLAGS) -c netinet\sctp_ss_functions.c - -sctp_sysctl.obj : netinet\sctp_sysctl.c $(usrsctp_HEADERS) - cl $(CVARSDLL) $(CFLAGS) -c netinet\sctp_sysctl.c - -sctp_timer.obj : netinet\sctp_timer.c $(usrsctp_HEADERS) - cl $(CVARSDLL) $(CFLAGS) -c netinet\sctp_timer.c - -sctp_userspace.obj : netinet\sctp_userspace.c $(usrsctp_HEADERS) - cl $(CVARSDLL) $(CFLAGS) -c netinet\sctp_userspace.c - -sctp_usrreq.obj : netinet\sctp_usrreq.c $(usrsctp_HEADERS) - cl $(CVARSDLL) $(CFLAGS) -c netinet\sctp_usrreq.c - -sctputil.obj : netinet\sctputil.c $(usrsctp_HEADERS) - cl $(CVARSDLL) $(CFLAGS) -c netinet\sctputil.c - -sctp6_usrreq.obj : netinet6\sctp6_usrreq.c $(usrsctp_HEADERS) - cl $(CVARSDLL) $(CFLAGS) -c netinet6\sctp6_usrreq.c +all: + cd usrsctplib + nmake -f Makefile.nmake + cd .. + cd programs + nmake all -f Makefile.nmake + cd .. clean: - del *.obj - del usrsctp.lib + cd usrsctplib + nmake clean -f Makefile.nmake + cd .. + cd programs + nmake clean -f Makefile.nmake + cd .. diff --git a/chromium/third_party/usrsctp/usrsctplib/Manual.md b/chromium/third_party/usrsctp/usrsctplib/Manual.md new file mode 100644 index 00000000000..6a1f5493cad --- /dev/null +++ b/chromium/third_party/usrsctp/usrsctplib/Manual.md @@ -0,0 +1,778 @@ +# SCTP user-land implementation (usrsctp) + +SCTP is a message oriented, reliable transport protocol with direct support for multihoming that runs on top of IP or UDP, and supports both v4 and v6 versions. + +Like TCP, SCTP provides reliable, connection oriented data delivery with congestion control. Unlike TCP, SCTP also provides message boundary preservation, ordered and unordered message delivery, multi-streaming and multi-homing. Detection of data corruption, loss of data and duplication of data is achieved by using checksums and sequence numbers. A selective retransmission mechanism is applied to correct loss or corruption of data. + +In this manual the socket API for the SCTP User-land implementation will be described. It is based on [RFC 6458](http://tools.ietf.org/html/rfc6458). The main focus of this document is on pointing out the differences to the SCTP Sockets API. For all aspects of the sockets API that are not mentioned in this document, please refer to [RFC 6458](http://tools.ietf.org/html/rfc6458). Questions about SCTP itself can hopefully be answered by [RFC 4960](http://tools.ietf.org/html/rfc4960). + +## Getting Started +The user-land stack has been tested on FreeBSD 10.0, Ubuntu 11.10, Windows 7, Mac OS X 10.6, and Mac OS X 10.7. The current version of the user-land stack is provided on [github](https://github.com/sctplab/usrsctp). Download the tarball and untar it in a folder of your choice. The tarball contains all the sources to build the libusrsctp, which has to be linked to the object file of an example program. In addition there are two applications in the folder `programs` that can be built and run. + +### Building the Library and the Applications +#### Unix-like Operating Systems +In the folder `usrsctp` type + + $ ./bootstrap + $ ./configure + $ make + +Now, the library `libusrsctp.la` has been built in the subdirectory `usrsctplib`, and the example programs are ready to run from the subdirectory `programs`. + +If you have root privileges or are in the sudoer group, you can install the library in `/usr/local/lib` and copy the header file to `/usr/include` with the command + + $ sudo make install + +#### Windows +On Windows you need a compiler like Microsoft Visual Studio. You can build the library and the example programs with the command line tool of the compiler by typing + + $ nmake -f Makefile.nmake + +in the directory `usrsctp`. + +#### CMake (experimental) +Create a directory outside the `usrsctp` directory, enter it and generate files by typing + + $ cmake <path-to-usrsctp-sources> + +By using the `-G`flag you can specify the target buildsystem e.g. `cmake -G Xcode ../usrsctp` will generate project files for Xcode. + +### Running the Test Programs + +Several test programs are included, including a discard server and a client. You can run both to send data from the client to the server. The client reads data from stdin and sends them to the server, which prints the message in the terminal and discards it. The sources of the server are also provided [here](https://github.com/sctplab/usrsctp/blob/master/programs/discard_server.c) and those of the client [here](https://github.com/sctplab/usrsctp/blob/master/programs/client.c). + +### Using UDP Encapsulation + +Both programs can either send data over SCTP directly or use UDP encapsulation, thus encapsulating the SCTP packet in a UDP datagram. The first mode works on loopback or in a protected setup without any NAT boxes involved. In all other cases it is better to use UDP encapsulation. + +The usage of the `discard_server` is + + $ discard_server [local_encaps_port remote_encaps_port] + +For UDP encapsulation the ports have to be specified. The local and remote encapsulation ports can be arbitrarily set. For example, you can call + + $ ./discard_server 11111 22222 + +on a Unix-like OS and + + $ discard_server.exe 11111 22222 + +on Windows. + +The client needs two additional parameters, the server's address and its port. Its usage is + + $ client remote_addr remote_port [local_port local_encaps_port remote_encaps_port] + +The remote address is the server's address. If client and server are started on the same machine, the loopback address `127.0.0.1` can be used for Unix-like OSs and the local address on Windows. The discard port is 9, thus 9 has to be taken as remote port. The encapsulation ports have to match those of the server, i.e. the server's `local_encaps_port` is the client's `remote_encaps_port` and vice versa. Thus, the client can be started with + + $ ./client 127.0.0.1 9 0 22222 11111 + +on a Unix-like OS and + + $ client.exe 192.168.0.1 9 0 22222 11111 + +on Windows provided your local IP address is 192.168.0.1. + +### Sending over SCTP + +To send data over SCTP directly you might need root privileges because raw sockets are used. Thus instead of specifying the encapsulation ports you have to start the programs prepending `sudo` or in case of Windows start the program from an administrator console. + +### Using the Callback API + +Instead of asking constantly for new data, a callback API can be used that is triggered by SCTP. A callback function has to be registered that will be called whenever data is ready to be delivered to the application. + +The `discard_server` has a flag to switch between the two modi. If `use_cb` is set to 1, the callback API will be used. To change the setting, just set the flag and compile the program again. + + +## Basic Operations + +All system calls start with the prefix `usrsctp_` to distinguish them from the kernel variants. Some of them are changed to account for the different demands in the userland environment. + +## Differences to RFC 6458 + +### usrsctp_init() + +Every application has to start with `usrsctp_init()`. This function calls `sctp_init()` and reserves the memory necessary to administer the data transfer. The function prototype is + +```c +void usrsctp_init(uint16_t udp_port) +``` + +As it is not always possible to send data directly over SCTP because not all NAT boxes can process SCTP packets, the data can be sent over UDP. To encapsulate SCTP into UDP a UDP port has to be specified, to which the datagrams can be sent. This local UDP port is set with the parameter `udp_port`. The default value is 9899, the standard UDP encapsulation port. If UDP encapsulation is not necessary, the UDP port has to be set to 0. + +### usrsctp_finish() + +At the end of the program `usrsctp_finish()` should be called to free all the memory that has been allocated before. The function prototype is + +```c +int usrsctp_finish(void) +``` + +The return code is 0 on success and -1 in case of an error. + +### usrsctp_socket() + +A representation of an SCTP endpoint is a socket. Is it created with `usrsctp_socket()`. The function prototype is + +```c +struct socket * +usrsctp_socket(int domain, + int type, + int protocol, + int (*receive_cb)(struct socket *sock, + union sctp_sockstore addr, + void *data, + size_t datalen, + struct sctp_rcvinfo, + int flags), + int (*send_cb)(struct socket *sock, + uint32_t sb_free), + uint32_t sb_threshold) +``` + +and the arguments taken from [RFC 6458](http://tools.ietf.org/html/rfc6458) are + +* domain: PF_INET or PF_INET6 can be used. +* type: In case of a one-to-many style socket it is SOCK_SEQPACKET, in case of a one-to-one style +socket it is SOCK_STREAM. For an explanation of the differences between the socket types please +refer to [RFC 6458](http://tools.ietf.org/html/rfc6458). +* protocol: Set IPPROTO_SCTP. + +In usrsctp a callback API can be used. The function pointers of the receive and send callbacks are new arguments to the socket call. They are NULL, if no callback API is used. The `sb_threshold` specifies the amount of free space in the send socket buffer before the send function in the application is called. If a send callback function is specified and `sb_threshold` is 0, the function is called whenever there is room in the send socket buffer. + +On success `usrsctp_socket()` returns the pointer to the new socket in the `struct socket` data type. It will be needed in all other system calls. In case of a failure NULL is returned and errno is set to the appropriate error code. + +### usrsctp_close() + +The function prototype of `usrsctp_close()` is + +```c +void usrsctp_close(struct socket *so) + ``` +Thus the only difference is the absence of a return code. + +## Same Functionality as RFC 6458 + +The following functions have the same functionality as their kernel pendants. There prototypes +are described in the following subsections. For a detailed description please refer to [RFC 6458](http://tools.ietf.org/html/rfc6458). + +### usrsctp_bind() + +```c +int +usrsctp_bind(struct socket *so, + struct sockaddr *addr, + socklen_t addrlen) +``` + +* so: Pointer to the socket as returned by `usrsctp_socket()`. +* addr: The address structure (`struct sockaddr_in` for an IPv4 address or `struct sockaddr_in6` for an IPv6 address). +* addrlen: The size of the address structure. + +`usrsctp_bind()` returns 0 on success and -1 in case of an error. + +### usrsctp_listen() + +```c +int +usrsctp_listen(struct socket *so, + int backlog) +``` + +* so: Pointer to the socket as returned by `usrsctp_socket()`. +* backlog: If backlog is non-zero, enable listening, else disable listening. + +`usrsctp_listen()` returns 0 on success and -1 in case of an error. + +### usrsctp_accept() + +```c +struct socket * +usrsctp_accept(struct socket *so, + struct sockaddr * addr, + socklen_t * addrlen) +``` + +* so: Pointer to the socket as returned by `usrsctp_socket()`. +* addr: On return, the primary address of the peer (`struct sockaddr_in` for an IPv4 address or `struct sockaddr_in6` for an IPv6 address). +* addrlen: Size of the returned address structure. + +`usrsctp_accept()` returns the accepted socket on success and NULL in case of an error. + +### usrsctp_connect() + +```c +int +usrsctp_connect(struct socket *so, + struct sockaddr *name, + socklen_t addrlen) +``` + +* so: Pointer to the socket as returned by `usrsctp_socket()`. +* name: Address of the peer to connect to (`struct sockaddr_in` for an IPv4 address or `struct sockaddr_in6` for an IPv6 address). +* addrlen: Size of the peer's address. + +usrsctp_connect() returns 0 on success and -1 in case of an error. + +### usrsctp_shutdown() + +```c +int +usrsctp_shutdown(struct socket *so, int how) +``` + +* so: Pointer to the socket of the association to be closed +* how: Specifies the type of shutdown. The values are as follows: + * SHUT_RD: Disables further receive operations. No SCTP protocol action is taken. + * SHUT_WR: Disables further send operations, and initiates the SCTP shutdown sequence. + * SHUT_RDWR: Disables further send and receive operations, and initiates the SCTP shutdown sequence. + +`usrsctp_listen()` returns 0 on success and -1 in case of an error. + +## Sending and Receiving Data +Since the publication of [RFC 6458](http://tools.ietf.org/html/rfc6458) there is only one function for sending and one for receiving +that is not deprecated. Therefore, only these two are described here. + +### usrsctp_sendv() + +```c +ssize_t +usrsctp_sendv(struct socket *so, + const void *data, + size_t len, + struct sockaddr *addrs, + int addrcnt, + void *info, + socklen_t infolen, + unsigned int infotype, + int flags) +``` + +* so: The socket to send data on. +* data: As it is more convenient to send data in a buffer and not a `struct iovec` data structure, we chose to pass the data as a void pointer. +* len: Length of the data. +* addrs: In this version of usrsctp at most one destination address is supported. In the case of a connected socket, the parameter `addrs` can be set to NULL. +* addrcnt: Number of addresses. As at most one address is supported, addrcnt is 0 if addrs is NULL and 1 otherwise. +* info: Additional information for a message is stored in `void *info`. The data types `struct sctp_sndinfo`, `struct sctp_prinfo`, and `struct sctp_sendv_spa` are supported as defined in [RFC 6458](http://tools.ietf.org/html/rfc6458). Support for `struct sctp_authinfo` is not implemented yet, therefore, errno is set EINVAL and -1 will be returned, if it is used. +* infolen: Length of info in bytes. +* infotype: Identifies the type of the information provided in info. Possible values are + * SCTP_SENDV_NOINFO + * SCTP_SENDV_SNDINFO + * SCTP_SENDV_PRINFO + * SCTP_SENDV_SPA (For additional information please refer to [RFC 6458](http://tools.ietf.org/html/rfc6458).) +* flags: Flags as described in [RFC 6458](http://tools.ietf.org/html/rfc6458). + +`usrsctp_sendv()` returns the number of bytes sent, or -1 if an error occurred. The variable errno is then set appropriately. + +### usrsctp_recvv() + +```c +ssize_t +usrsctp_recvv(struct socket *so, + void *dbuf, + size_t len, + struct sockaddr *from, + socklen_t * fromlen, + void *info, + socklen_t *infolen, + unsigned int *infotype, + int *msg_flags) +``` + +* so: The socket to receive data on. +* dbuf: Analog to `usrsctp_sendv()` the data is returned in a buffer. +* len: Length of the buffer in bytes. +* from: A pointer to an address to be filled with the sender of the received message's address. +* fromlen: An in/out parameter describing the from length. +* info: A pointer to the buffer to hold the attributes of the received message. The structure type of info is determined by the infotype parameter. The attributes returned in `info` have to be handled in the same way as specified in [RFC 6458](http://tools.ietf.org/html/rfc6458). +* infolen: An in/out parameter describing the size of the info buffer. +* infotype: On return, `*infotype` is set to the type of the info buffer. The current defined values are + * SCTP_RECVV_NOINFO + * SCTP_RECVV_RCVINFO + * SCTP_RECVV_NXTINFO + * SCTP_RECVV_RN (A detailed description is given in [RFC 6458](http://tools.ietf.org/html/rfc6458)) +* flags: A pointer to an integer to be filled with any message flags (e.g., `MSG_NOTIFICATION`). Note that this field is an in/out parameter. Options for the receive may also be passed into the value (e.g., `MSG_EOR`). Returning from the call, the flags' value will differ from its original value. + +`usrsctp_recvv()` returns the number of bytes sent, or -1 if an error occurred. The variable errno is then set appropriately. + +## Socket Options +Socket options are used to change the default behavior of socket calls. +Their behavior is specified in [RFC 6458](http://tools.ietf.org/html/rfc6458). The functions to get or set them are + +```c +int +usrsctp_getsockopt(struct socket *so, + int level, + int optname, + void *optval, + socklen_t *optlen) +``` +and +```c +int +usrsctp_setsockopt(struct socket *so, + int level, + int optname, + const void *optval, + socklen_t optlen) +``` + +and the arguments are +* so: The socket of type struct socket. +* level: Set to IPPROTO_SCTP for all SCTP options. +* optname: The option name as specified in The Socket Options table below. +* optval: The buffer to store the value of the option as specified in the second column of Socket Options below. +* optlen: The size of the buffer (or the length of the option returned in case of `usrsctp_getsockopt`). + +These functions return 0 on success and -1 in case of an error. + +### Socket Options supported by usrsctp + +Option | Datatype | r/w +------ | -------- | ---- +SCTP_RTOINFO | struct sctp_rtoinfo | r/w +SCTP_ASSOCINFO | struct sctp_assocparams | r/w +SCTP_INITMSG | struct sctp_initmsg | r/w +SCTP_NODELAY | int | r/w +SCTP_AUTOCLOSE | int | r/w +SCTP_PRIMARY_ADDR | struct sctp_setprim | r/w +SCTP_ADAPTATION_LAYER | struct sctp_setadaptation | r/w +SCTP_DISABLE_FRAGMENTS | int | r/w +SCTP_PEER_ADDR_PARAMS | struct sctp_paddrparams | r/w +SCTP_I_WANT_MAPPED_V4_ADDR | int | r/w +SCTP_MAXSEG | struct sctp_assoc_value | r/w +SCTP_DELAYED_SACK | struct sctp_sack_info | r/w +SCTP_FRAGMENT_INTERLEAVE | int | r/w +SCTP_PARTIAL_DELIVERY_POINT | int | r/w +SCTP_HMAC_IDENT | struct sctp_hmacalgo | r/w +SCTP_AUTH_ACTIVE_KEY | struct sctp_authkeyid | r/w +SCTP_AUTO_ASCONF | int | r/w +SCTP_MAX_BURST | struct sctp_assoc_value | r/w +SCTP_CONTEXT | struct sctp_assoc_value | r/w +SCTP_EXPLICIT_EOR | int | r/w +SCTP_REUSE_PORT | int | r/w +SCTP_EVENT | struct sctp_event | r/w +SCTP_RECVRCVINFO | int | r/w +SCTP_RECVNXTINFO | int | r/w +SCTP_DEFAULT_SNDINFO | struct sctp_sndinfo | r/w +SCTP_DEFAULT_PRINFO | struct sctp_default_prinfo | r/w +SCTP_REMOTE_UDP_ENCAPS_PORT | int | r/w +SCTP_ENABLE_STREAM_RESET | struct sctp_assoc_value | r/w +SCTP_STATUS | struct sctp_status | r +SCTP_GET_PEER_ADDR_INFO | struct sctp_paddrinfo | r +SCTP_PEER_AUTH_CHUNKS | struct sctp_authchunks | r +SCTP_LOCAL_AUTH_CHUNKS | struct sctp_authchunks | r +SCTP_GET_ASSOC_NUMBER | uint32_t | r +SCTP_GET_ASSOC_ID_LIST | struct sctp_assoc_ids | r +SCTP_RESET_STREAMS | struct sctp_reset_streams | w +SCTP_RESET_ASSOC | struct sctp_assoc_t | w +SCTP_ADD_STREAMS | struct sctp_add_streams | w + +Further usage details are described in [RFC 6458](tools.ietf.org/html/rfc6458), [RFC 6525](tools.ietf.org/html/rfc6525), and [draft-ietf-tsvwg-sctp-udp-encaps-03](https://tools.ietf.org/html/draft-ietf-tsvwg-sctp-udp-encaps-03) (work in progress). + +## Sysctl variables + +In kernel implementations like for instance FreeBSD, it is possible to change parameters in the operating system. These parameters are called sysctl variables. + +In usrsctp applications can set or retrieve these variables with the functions +```c +void usrsctp_sysctl_set_ ## (uint32_t value) +``` +and +```c +uint32_t usrsctp_sysctl_get_ ## (void) +``` +respectively, where `##` stands for the name of the variable. + +In the following paragraphs a short description of the parameters will be given. + +## Manipulate Memory +#### usrsctp_sysctl_set_sctp_sendspace() +The space of the available send buffer can be changed from its default value of 262,144 bytes to a value between 0 and `2^32 - 1` bytes. + +#### usrsctp_sysctl_set_sctp_recvspace() +The space of the available receive buffer can be changed from its default value of 262,144 bytes to a value between 0 and `2^32 - 1` bytes. + +#### usrsctp_sysctl_set_sctp_hashtblsize() +The TCB (Thread Control Block) hash table sizes, i.e. the size of one TCB in the hash table, can be tuned between 1 and `2^32 - 1` bytes. The default value is 1,024 bytes. A TCB contains for instance pointers to the socket, the endpoint, information about the association and some statistic data. + +#### usrsctp_sysctl_set_sctp_pcbtblsize() +The PCB (Protocol Control Block) hash table sizes, i.e. the size of one PCB in the hash table, can be tuned between 1 and `2^32 - 1` bytes. The default value is 256 bytes. The PCB contains all variables that characterize an endpoint. + +#### usrsctp_sysctl_set_sctp_system_free_resc_limit() +This parameters tunes the maximum number of cached resources in the system. It can be set between 0 and `2^32 - 1`. The default value is 1000. + +#### usrsctp_sysctl_set_sctp_asoc_free_resc_limit() +This parameters tunes the maximum number of cached resources in an association. It can be set between 0 and `2^32 - 1`. The default value is 10. + +#### usrsctp_sysctl_set_sctp_mbuf_threshold_count() +Data is stored in mbufs. Several mbufs can be chained together. The maximum number of small mbufs in a chain can be set with this parameter, before an mbuf cluset is used. The default is 5. + +#### usrsctp_sysctl_set_sctp_add_more_threshold() +TBD +This parameter configures the threshold below which more space should be added to a socket send buffer. The default value is 1452 bytes. + + +## Configure RTO +The retransmission timeout (RTO), i.e. the time that controls the retransmission of messages, has several parameters, that can be changed, for example to shorten the time, before a message is retransmitted. The range of these parameters is between 0 and `2^32 - 1`ms. + +#### usrsctp_sysctl_set_sctp_rto_max_default() +The default value for the maximum retransmission timeout in ms is 60,000 (60secs). + +#### usrsctp_sysctl_set_sctp_rto_min_default() +The default value for the minimum retransmission timeout in ms is 1,000 (1sec). + +#### usrsctp_sysctl_set_sctp_rto_initial_default() +The default value for the initial retransmission timeout in ms is 3,000 (3sec). This value is only needed before the first calculation of a round trip time took place. + +#### usrsctp_sysctl_set_sctp_init_rto_max_default() +The default value for the maximum retransmission timeout for an INIT chunk in ms is 60,000 (60secs). + + +## Set Timers +#### usrsctp_sysctl_set_sctp_valid_cookie_life_default() +A cookie has a specified life time. If it expires the cookie is not valid any more and an ABORT is sent. The default value in ms is 60,000 (60secs). + +#### usrsctp_sysctl_set_sctp_heartbeat_interval_default() +Set the default time between two heartbeats. The default is 30,000ms. + +#### usrsctp_sysctl_set_sctp_shutdown_guard_time_default() +If a SHUTDOWN is not answered with a SHUTDOWN-ACK while the shutdown guard timer is still running, the association will be aborted after the default of 180secs. + +#### usrsctp_sysctl_set_sctp_pmtu_raise_time_default() +TBD +To set the size of the packets to the highest value possible, the maximum transfer unit (MTU) of the complete path has to be known. The default time interval for the path mtu discovery is 600secs. + +#### usrsctp_sysctl_set_sctp_secret_lifetime_default() +TBD +The default secret lifetime of a server is 3600secs. + +#### usrsctp_sysctl_set_sctp_vtag_time_wait() +TBD +Vtag time wait time, 0 disables it. Default: 60secs + + +## Set Failure Limits +Transmissions and retransmissions of messages might fail. To protect the system against too many retransmissions, limits have to be defined. + +#### usrsctp_sysctl_set_sctp_init_rtx_max_default() +The default maximum number of retransmissions of an INIT chunks is 8, before an ABORT is sent. + +#### usrsctp_sysctl_set_sctp_assoc_rtx_max_default() +This parameter sets the maximum number of failed retransmissions before the association is aborted. The default vaule is 10. + +#### usrsctp_sysctl_set_sctp_path_rtx_max_default() +This parameter sets the maximum number of path failures before the association is aborted. The default value is 5. Notice that the number of paths multiplied by this value should be equal to `sctp_assoc_rtx_max_default`. That means that the default configuration is good for two paths. + +#### usrsctp_sysctl_set_sctp_max_retran_chunk() +The parameter configures how many times an unlucky chunk can be retransmitted before the association aborts. The default is set to 30. + +#### usrsctp_sysctl_set_sctp_path_pf_threshold() +TBD +Default potentially failed threshold. Default: 65535 + +#### usrsctp_sysctl_set_sctp_abort_if_one_2_one_hits_limit() +TBD +When one-2-one hits qlimit abort. Default: 0 + + +## Control the Sending of SACKs +#### usrsctp_sysctl_set_sctp_sack_freq_default() +The SACK frequency defines the number of packets that are awaited, before a SACK is sent. The default value is 2. + +#### usrsctp_sysctl_set_sctp_delayed_sack_time_default() +As a SACK (Selective Acknowlegment) is sent after every other packet, a timer is set to send a SACK in case another packet does not arrive in due time. The default value for this timer is 200ms. + +#### usrsctp_sysctl_set_sctp_strict_sacks() +TBD +This is a flag to turn the controlling of the coherence of SACKs on or off. The default value is 1 (on). + +#### usrsctp_sysctl_set_sctp_nr_sack_on_off() +If a slow hosts receives data on a lossy link it is possible that its receiver window is full and new data can only be accepted if one chunk with a higher TSN (Transmission Sequence Number) that has previously been acknowledged is dropped. As a consequence the sender has to store data, even if they have been acknowledged in case they have to be retransmitted. If this behavior is not necessary, non-renegable SACKs can be turned on. By default the use of non-renegable SACKs is turned off. + +#### usrsctp_sysctl_set_sctp_enable_sack_immediately() +In some cases it is not desirable to wait for the SACK timer to expire before a SACK is sent. In these cases a bit called SACK-IMMEDIATELY (see [draft-tuexen-tsvwg-sctp-sack-immediately-09](https://tools.ietf.org/html/draft-tuexen-tsvwg-sctp-sack-immediately-09)) can be set to provoke the instant sending of a SACK. The default is to turn it off. + +#### usrsctp_sysctl_set_sctp_L2_abc_variable() +TBD +SCTP ABC max increase per SACK (L). Default: 1 + +## Change Max Burst +Max burst defines the maximum number of packets that may be sent in one flight. + +#### usrsctp_sysctl_set_sctp_max_burst_default() +The default value for max burst is 0, which means that the number of packets sent as a flight is not limited by this parameter, but may be by another one, see the next paragraph. + +#### usrsctp_sysctl_set_sctp_use_cwnd_based_maxburst() +The use of max burst is based on the size of the congestion window (cwnd). This parameter is set by default. + +#### usrsctp_sysctl_set_sctp_hb_maxburst() +Heartbeats are mostly used to verify a path. Their number can be limited. The default is 4. + +#### usrsctp_sysctl_set_sctp_fr_max_burst_default() +In the state of fast retransmission the number of packet bursts can be limited. The default value is 4. + + +## Handle Chunks +#### usrsctp_sysctl_set_sctp_peer_chunk_oh() +In order to keep track of the peer's advertised receiver window, the sender calculates the window by subtracting the amount of data sent. Yet, some OSs reduce the receiver window by the real space needed to store the data. This parameter sets the additional amount to debit the peer's receiver window per chunk sent. The default value is 256, which is the value needed by FreeBSD. + +#### usrsctp_sysctl_set_sctp_max_chunks_on_queue() +This parameter sets the maximum number of chunks that can be queued per association. The default value is 512. + +#### usrsctp_sysctl_set_sctp_min_split_point() +TBD +The minimum size when splitting a chunk is 2904 bytes by default. + +#### usrsctp_sysctl_set_sctp_chunkscale() +TBD +This parameter can be tuned for scaling of number of chunks and messages. The default is10. + +#### usrsctp_sysctl_set_sctp_min_residual() +TBD +This parameter configures the minimum size of the residual data chunk in the second part of the split. The default is 1452. + + +## Calculate RTT +The calculation of the round trip time (RTT) depends on several parameters. + +#### usrsctp_sysctl_set_sctp_rttvar_bw() +TBD +Shift amount for bw smoothing on rtt calc. Default: 4 + +#### usrsctp_sysctl_set_sctp_rttvar_rtt() +TBD +Shift amount for rtt smoothing on rtt calc. Default: 5 + +#### usrsctp_sysctl_set_sctp_rttvar_eqret() +TBD +What to return when rtt and bw are unchanged. Default: 0 + + +## Influence the Congestion Control +The congestion control should protect the network against fast senders. + +#### usrsctp_sysctl_set_sctp_ecn_enable +Explicit congestion notifications are turned on by default. + +#### usrsctp_sysctl_set_sctp_default_cc_module() +This parameter sets the default algorithm for the congestion control. Default is 0, i.e. the one specified in [RFC 4960](http://tools.ietf.org/html/rfc4960). + +#### usrsctp_sysctl_set_sctp_initial_cwnd() +Set the initial congestion window in MTUs. The default is 3. + +#### usrsctp_sysctl_set_sctp_use_dccc_ecn() +TBD +Enable for RTCC CC datacenter ECN. Default: 1 + +#### usrsctp_sysctl_set_sctp_steady_step() +TBD +How many the sames it takes to try step down of cwnd. Default: 20 + + +## Configure AUTH and ADD-IP +An important extension of SCTP is the dynamic address reconfiguration (see [RFC 5061](http://tools.ietf.org/html/rfc5061)), also known as ADD-IP, which allows the changing of addresses during the lifetime of an association. For this feature the AUTH extension (see [RFC 4895](http://tools.ietf.org/html/rfc4895)) is necessary. + +#### usrsctp_sysctl_set_sctp_auto_asconf() +If SCTP Auto-ASCONF is enabled, the peer is informed automatically when a new address +is added or removed. This feature is enabled by default. + +#### usrsctp_sysctl_set_sctp_multiple_asconfs() +By default the sending of multiple ASCONFs is disabled. + +#### usrsctp_sysctl_set_sctp_auth_disable() +The use of AUTH, which is normally turned on, can be disabled by setting this parameter to 1. + +#### usrsctp_sysctl_set_sctp_asconf_auth_nochk() +It is also possible to disable the requirement to use AUTH in conjunction with ADD-IP by setting this parameter +to 1. + + +## Concurrent Multipath Transfer (CMT) +A prominent feature of SCTP is the possibility to use several addresses for the same association. One is the primary path, and the others are needed in case of a path failure. Using CMT the data is sent on several paths to enhance the throughput. + +#### usrsctp_sysctl_set_sctp_cmt_on_off() +To turn CMT on, this parameter has to be set to 1. + +#### usrsctp_sysctl_set_sctp_cmt_use_dac() +To use delayed acknowledgments with CMT this parameter has to be set to 1. + +#### usrsctp_sysctl_set_sctp_buffer_splitting() +For CMT it makes sense to split the send and receive buffer to have shares for each path. By default buffer splitting is turned off. + + +## Network Address Translation (NAT) +To be able to pass NAT boxes, the boxes have to handle SCTP packets in a specific way. + +#### usrsctp_sysctl_set_sctp_nat_friendly() +SCTP NAT friendly operation. Default:1 + +#### usrsctp_sysctl_set_sctp_inits_include_nat_friendly() +Enable sending of the nat-friendly SCTP option on INITs. Default: 0 + +#### usrsctp_sysctl_set_sctp_udp_tunneling_port() +Set the SCTP/UDP tunneling port. Default: 9899 + +## SCTP Mobility +#### usrsctp_sysctl_set_sctp_mobility_base() +TBD +Enable SCTP base mobility. Default: 0 + + +#### usrsctp_sysctl_set_sctp_mobility_fasthandoff() +TBD +Enable SCTP fast handoff. default: 0 + + +## Miscellaneous +#### usrsctp_sysctl_set_sctp_no_csum_on_loopback() +Calculating the checksum for packets sent on loopback is turned off by default. To turn it on, set this parameter to 0. + +#### usrsctp_sysctl_set_sctp_nr_outgoing_streams_default() +The peer is notified about the number of outgoing streams in the INIT or INIT-ACK chunk. The default is 10. + +#### usrsctp_sysctl_set_sctp_do_drain() +Determines whether SCTP should respond to the drain calls. Default: 1 + +#### usrsctp_sysctl_set_sctp_strict_data_order() +TBD +Enforce strict data ordering, abort if control inside data. Default: 0 + +#### usrsctp_sysctl_set_sctp_default_ss_module() +Set the default stream scheduling module. Implemented modules are: +* SCTP_SS_DEFAULT +* SCTP_SS_ROUND_ROBIN +* SCTP_SS_ROUND_ROBIN_PACKET +* SCTP_SS_PRIORITY +* SCTP_SS_FAIR_BANDWITH +* SCTP_SS_FIRST_COME + +#### usrsctp_sysctl_set_sctp_default_frag_interleave() +TBD +Default fragment interleave level. Default: 1 + +#### usrsctp_sysctl_set_sctp_blackhole() +TBD +Enable SCTP blackholing. Default: 0 + +#### usrsctp_sysctl_set_sctp_logging_level() +Set the logging level. The default is 0. + +#### usrsctp_sysctl_set_sctp_debug_on() +Turn debug output on or off. It is disabled by default. To obtain debug output, `SCTP_DEBUG` has to be set as a compile flag. + + +### sysctl variables supported by usrsctp + +Parameter | Meaning | Default Value +--------- | ------- | ------------- +sctp_sendspace | Send buffer space | 1864135 +sctp_recvspace | Receive buffer space | 1864135 +sctp_hashtblsize | Tunable for TCB hash table sizes | 1024 +sctp_pcbtblsize | Tunable for PCB hash table sizes | 256 +sctp_system_free_resc_limit | Cached resources in the system | 1000 +sctp_asoc_free_resc_limit | Cashed resources in an association | 10 +sctp_rto_max_default | Default value for RTO_max | 60000ms +sctp_rto_min_default | Default value for RTO_min | 1000ms +sctp_rto_initial_default | Default value for RTO_initial | 3000ms +sctp_init_rto_max_default | Default value for the maximum RTO for sending an INIT | 60000ms +sctp_valid_cookie_life_default | Valid cookie life time | 60000ms +sctp_init_rtx_max_default | Maximum number of INIT retransmissions | 8 +sctp_assoc_rtx_max_default | Maximum number of failed retransmissions before the association is aborted | 10 +sctp_path_rtx_max_default | Maximum number of failed retransmissions before a path fails | 5 +sctp_ecn_enable | Enabling explicit congestion notifications | 1 +sctp_strict_sacks | Control the coherence of SACKs | 1 +sctp_delayed_sack_time_default | Default delayed SACK timer | 200ms +sctp_sack_freq_default | Default SACK frequency | 2 +sctp_nr_sack_on_off | Turn non-renegable SACKs on or off | 0 +sctp_enable_sack_immediately | Enable sending of the SACK-IMMEDIATELY bit | 0 +sctp_no_csum_on_loopback | Enable the compilation of the checksum on packets sent on loopback | 1 +sctp_peer_chunk_oh | Amount to debit peers rwnd per chunk sent | 256 +sctp_max_burst_default | Default max burst for SCTP endpoints | 0 +sctp_use_cwnd_based_maxburst | Use max burst based on the size of the congestion window | 1 +sctp_hb_maxburst | Confirmation Heartbeat max burst | 4 +sctp_max_chunks_on_queue | Default max chunks on queue per asoc | 512 +sctp_min_split_point | Minimum size when splitting a chunk | 2904 +sctp_chunkscale | Tunable for Scaling of number of chunks and messages | 10 +sctp_mbuf_threshold_count | Maximum number of small mbufs in a chain | 5 +sctp_heartbeat_interval_default | Deafult time between two Heartbeats | 30000ms +sctp_pmtu_raise_time_default | Default PMTU raise timer | 600secs +sctp_shutdown_guard_time_default | Default shutdown guard timer | 180secs +sctp_secret_lifetime_default | Default secret lifetime | 3600secs +sctp_add_more_threshold | Threshold when more space should be added to a socket send buffer | 1452 +sctp_nr_outgoing_streams_default | Default number of outgoing streams | 10 +sctp_cmt_on_off | Turn CMT on or off. | 0 +sctp_cmt_use_dac | Use delayed acknowledgment for CMT | 0 +sctp_fr_max_burst_default | Default max burst for SCTP endpoints when fast retransmitting | 4 +sctp_auto_asconf | Enable SCTP Auto-ASCONF | 1 +sctp_multiple_asconfs | Enable SCTP Muliple-ASCONFs | 0 +sctp_asconf_auth_nochk | Disable SCTP ASCONF AUTH requirement | 0 +sctp_auth_disable | Disable SCTP AUTH function | 0 +sctp_nat_friendly | SCTP NAT friendly operation | 1 +sctp_inits_include_nat_friendly | Enable sending of the nat-friendly SCTP option on INITs. | 0 +sctp_udp_tunneling_port | Set the SCTP/UDP tunneling port | 9899 +sctp_do_drain | Determines whether SCTP should respond to the drain calls | 1 +sctp_abort_if_one_2_one_hits_limit | When one-2-one hits qlimit abort | 0 +sctp_strict_data_order | Enforce strict data ordering, abort if control inside data | 0 +sctp_min_residual | Minimum residual data chunk in second part of split | 1452 +sctp_max_retran_chunk | Maximum times an unlucky chunk can be retransmitted before the association aborts | 30 +sctp_default_cc_module | Default congestion control module | 0 +sctp_default_ss_module | Default stream scheduling module | 0 +sctp_default_frag_interleave | Default fragment interleave level | 1 +sctp_mobility_base | Enable SCTP base mobility | 0 +sctp_mobility_fasthandoff | Enable SCTP fast handoff | 0 +sctp_L2_abc_variable | SCTP ABC max increase per SACK (L) | 1 +sctp_vtag_time_wait | Vtag time wait time, 0 disables it. | 60secs +sctp_blackhole | Enable SCTP blackholing | 0 +sctp_path_pf_threshold | Default potentially failed threshold | 65535 +sctp_rttvar_bw | Shift amount for bw smoothing on rtt calc | 4 +sctp_rttvar_rtt | Shift amount for rtt smoothing on rtt calc | 5 +sctp_rttvar_eqret | What to return when rtt and bw are unchanged | 0 +sctp_steady_step | How many the sames it takes to try step down of cwnd | 20 +sctp_use_dccc_ecn | Enable for RTCC CC datacenter ECN | 1 +sctp_buffer_splitting | Enable send/receive buffer splitting | 0 +sctp_initial_cwnd | Initial congestion window in MTUs | 3 +sctp_logging_level | Logging level | 0 +sctp_debug_on | Turns debug output on or off. | 0 + +## Examples + +See https://github.com/sctplab/usrsctp/tree/master/programs + + +## References + +#### SCTP +R. Stewart:</br> +`Stream Control Transmission Protocol`.</br> +[RFC 4960](http://tools.ietf.org/html/rfc4960), September 2007. + +#### auth +M. Tüxen, R. Stewart, P. Lei, and E. Rescorla:</br> +`Authenticated Chunks for the Stream Control Transmission Protocol (SCTP)`.</br> +[RFC 4895](http://tools.ietf.org/html/rfc4895), August 2007. + +#### addip +R. Stewart, Q. Xie, M. Tüxen, S. Maruyama, and M. Kozuka:</br> +`Stream Control Transmission Protocol (SCTP) Dynamic Address Reconfiguration`.</br> +[RFC 5061](http://tools.ietf.org/html/rfc5061), September 2007. + +#### socketAPI +R. Stewart, M. Tüxen, K. Poon, and V. Yasevich:</br> +`Sockets API Extensions for the Stream Control Transmission Protocol (SCTP)`.</br> +[RFC 6458](http://tools.ietf.org/html/rfc6458), Dezember 2011. + +#### streamReset +R. Stewart, M. Tüxen, and P. Lei:</br> +`Stream Control Transmission Protocol (SCTP) Stream Reconfiguration`.</br> +[RFC 6525](http://tools.ietf.org/html/rfc6525), February 2012. + +#### udpencaps +M. Tüxen and R. Stewart</br> +`UDP Encapsulation of Stream Control Transmission Protocol (SCTP) Packets for End-Host to End-Host Communication`</br> +[RFC 6951](https://tools.ietf.org/html/rfc6951), May 2013. + +#### sack-imm +M. Tüxen, I. Rüngeler, and R. Stewart:</br> +`SACK-IMMEDIATELY Extension for the Stream Control Transmission Protocol`</br> +[RFC 7053](https://tools.ietf.org/html/rfc7053), November 2013. diff --git a/chromium/third_party/usrsctp/usrsctplib/Manual.tex b/chromium/third_party/usrsctp/usrsctplib/Manual.tex new file mode 100644 index 00000000000..a5215939862 --- /dev/null +++ b/chromium/third_party/usrsctp/usrsctplib/Manual.tex @@ -0,0 +1,1330 @@ +% +% Copyright (C) 2012-2015 Irene Ruengeler +% Copyright (C) 2012-2015 Michael Tuexen +% +% All rights reserved. +% +% Redistribution and use in source and binary forms, with or without +% modification, are permitted provided that the following conditions +% are met: +% 1. Redistributions of source code must retain the above copyright +% notice, this list of conditions and the following disclaimer. +% 2. Redistributions in binary form must reproduce the above copyright +% notice, this list of conditions and the following disclaimer in the +% documentation and/or other materials provided with the distribution. +% 3. Neither the name of the project nor the names of its contributors +% may be used to endorse or promote products derived from this software +% without specific prior written permission. +% +% THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND +% ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +% ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE +% FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +% DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +% OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +% HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +% LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +% OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +% SUCH DAMAGE. +% +\documentclass[a4paper]{article} +% +\usepackage{longtable} +% +\title{Socket API for the SCTP User-land Implementation (usrsctp)} +\author{I.~R\"ungeler% + \thanks{M\"unster University of Applied Sciences, + Department of Electrical Engineering + and Computer Science, + Stegerwaldstr.~39, + D-48565 Steinfurt, + Germany, + \texttt{i.ruengeler@fh-muenster.de}.} + \and + M.~T\"uxen% + \thanks{M\"unster University of Applied Sciences, + Department of Electrical Engineering + and Computer Science, + Stegerwaldstr.~39, + D-48565 Steinfurt, + Germany, + \texttt{tuexen@fh-muenster.de}.} +} +% +\begin{document} +\setcounter{secnumdepth}{4} +\setcounter{tocdepth}{4} +\maketitle +\tableofcontents + +\section{Introduction} +In this manual the socket API for the SCTP User-land implementation will be described. +It is based on RFC 6458~\cite{socketAPI}. The main focus of this document is on pointing out + the differences to the SCTP Sockets API. For all aspects of the sockets API that are not + mentioned in this document, please refer to RFC~6458. Questions about SCTP can hopefully be + answered by RFC~4960~\cite{SCTP}. + +\section{Getting Started} +The User-land stack has been tested on FreeBSD 10.0, Ubuntu 11.10, Windows 7, Mac OS X 10.6, +and MAC OS X 10.7. +The current version of the User-land stack is provided on \textit{http://sctp.fh-muenster.de/sctp-user-land-stack.html}. +Download the tarball and untar it in a folder of your choice. +The tarball contains all the sources to build the libusrsctp, which has to be linked to the object file of an +example program. In addition there are two applications in the folder \textit{programs} that can be built and run. + +\subsection{Building the Library and the Applications} +\subsubsection{Unix-like Operating Systems} +In the folder \textit{usrsctp} type +\begin{verbatim} +./bootstrap +./configure +make +\end{verbatim} +Now, the library \textit{libusrsctp.la} has been built in the subdirectory \textit{usrsctplib}, and the example +programs are ready to run from the subdirectory \textit{programs}. + +If you have root privileges or are in the sudoer group, you can install the library in \textit{/usr/local/lib} +and copy the header file to \textit{/usr/include} with the command +\begin{verbatim} +sudo make install +\end{verbatim} + +\subsubsection{Windows} +On Windows you need a compiler like Microsoft Visual Studio. You can build the library and the +example programs with the command line tool of the compiler by typing +\begin{verbatim} +nmake -f Makefile.nmake +\end{verbatim} +in the directory \textit{usrsctp}. + +\subsection{Running the Test Programs} +There are two test programs included, a discard server and a client. You can run both to send data from the +client to the server. The client reads data from stdin and sends them to the server, which prints the message +in the terminal and discards it. The sources of the server are also provided in Section~\ref{server} and those +of the client in Section~\ref{client}. + +\subsubsection{Using UDP Encapsulation} +Both programs can either send data over SCTP directly or use UDP encapsulation, thus encapsulating the +SCTP packet in a UDP datagram. The first mode works on loopback or in a protected setup without any +NAT boxes involved. In all other cases it is better to use UDP encapsulation. + +The usage of the discard\_server is +\begin{verbatim} +discard_server [local_encaps_port remote_encaps_port] +\end{verbatim} +For UDP encapsulation the ports have to be specified. The local and remote encapsulation ports can be arbitrarily +set. +For example, you can call +\begin{verbatim} +./discard_server 11111 22222 +\end{verbatim} +on a Unix-like OS and +\begin{verbatim} +discard_server.exe 11111 22222 +\end{verbatim} +on Windows. + +The client needs two additional parameters, the server's address and its port. +Its usage is +\begin{verbatim} +client remote_addr remote_port [local_port local_encaps_port remote_encaps_port] +\end{verbatim} +The remote address is the server's address. If client and server are started on the same machine, +the loopback address 127.0.0.1 can be used for Unix-like OSs and the local address on Windows. +The discard port is 9, thus 9 has to be taken as remote port. The encapsulation ports have to +match those of the server, i.e. the server's local\_encaps\_port is the client's +remote\_encaps\_port and vice versa. Thus, the client can be started with +\begin{verbatim} +./client 127.0.0.1 9 0 22222 11111 +\end{verbatim} +on a Unix-like OS and +\begin{verbatim} +client.exe 192.168.0.1 9 0 22222 11111 +\end{verbatim} +on Windows provided your local IP address is 192.168.0.1. + +\subsubsection{Sending over SCTP} +To send data over SCTP directly you might need root privileges because raw sockets are used. +Thus instead of specifying the encapsulation ports you have to start the programs prepending +\texttt{sudo} or in case of Windows start the program from an administrator console. + +\subsubsection{Using the Callback API} +Instead of asking constantly for new data, a callback API can be used that is triggered by +SCTP. A callback function has to be registered that will be called whenever data is ready to +be delivered to the application. + +The discard\_server has a flag to switch between the two modi. If use\_cb is set to 1, the +callback API will be used. To change the setting, just set the flag and compile the program again. + + + + +\section{Basic Operations} +All system calls start with the prefix \textit{usrsctp\_} to distinguish them from the kernel variants. +Some of them are changed to account for the different demands in the userland environment. + +\subsection{Differences to RFC 6458} +\subsubsection{usrsctp\_init()} +Every application has to start with \textit{usrsctp\_init()}. This function calls \textit{sctp\_init()} and reserves +the memory necessary to administer the data transfer. +The function prototype is +\begin{verbatim} +void +usrsctp_init(uint16_t udp_port) +\end{verbatim} +As it is not always possible to send data directly over SCTP because not all NAT boxes can +process SCTP packets, the data can be sent over UDP. To encapsulate SCTP into UDP +a UDP port has to be specified, to which the datagrams can be sent. This local UDP port is set +with the parameter \texttt{udp\_port}. The default value is 9899, the standard UDP encapsulation port. +If UDP encapsulation is not necessary, the UDP port has to be set to 0. + +\subsubsection{usrsctp\_finish()} +At the end of the program \textit{usrsctp\_finish()} should be called to free all the memory that has been +allocated before. +The function prototype is +\begin{verbatim} +int +usrsctp_finish(void). +\end{verbatim} +The return code is 0 on success and -1 in case of an error. + +\subsubsection{usrsctp\_socket()} +A representation of an SCTP endpoint is a socket. Is it created with \textit{usrsctp\_socket()}. +The function prototype is +\begin{verbatim} +struct socket * +usrsctp_socket(int domain, + int type, + int protocol, + int (*receive_cb)(struct socket *sock, + union sctp_sockstore addr, + void *data, + size_t datalen, + struct sctp_rcvinfo, + int flags), + int (*send_cb)(struct socket *sock, + uint32_t sb_free), + uint32_t sb_threshold). +\end{verbatim} +and the arguments taken from RFC~6458 are +\begin{itemize} +\item domain: PF\_INET or PF\_INET6 can be used. +\item type: In case of a one-to-many style socket it is SOCK\_SEQPACKET, in case of a one-to-one style +socket it is SOCK\_STREAM. For an explanation of the differences between the socket types please +refer to RFC~6458. +\item protocol: Set IPPROTO\_SCTP. +\end{itemize} + +In usrsctp a callback API can be used. The function pointers of the receive and send callbacks +are new arguments to the socket call. They are NULL, if no callback API is used. The sb\_threshold +specifies the amount of free space in the send socket buffer before the send function in the +application is called. If a send callback function is specified and sb\_threshold is 0, the function is +called whenever there is room in the send socket buffer. + +On success \textit{usrsctp\_socket()} returns the pointer to the new socket in the \texttt{struct socket} data type. +It will be needed in all other system calls. In case of a failure NULL is returned and +errno is set to the appropriate error code. + +\subsubsection{usrsctp\_close()} + +The function prototype of \textit{usrsctp\_close()} is +\begin{verbatim} +void +usrsctp_close(struct socket *so). + \end{verbatim} +Thus the only difference is the absence of a return code. + +\subsection{Same Functionality as RFC 6458} +The following functions have the same functionality as their kernel pendants. There prototypes +are described in the following subsections. For a detailed description please refer to RFC~6458. + +\subsubsection{usrsctp\_bind()} +The function prototype of \textit{usrsctp\_bind()} is +\begin{verbatim} +int +usrsctp_bind(struct socket *so, + struct sockaddr *addr, + socklen_t addrlen). +\end{verbatim} +The arguments are +\begin{itemize} +\item so: Pointer to the socket as returned by \textit{usrsctp\_socket()}. +\item addr: The address structure (struct sockaddr\_in for an IPv4 address + or struct sockaddr\_in6 for an IPv6 address). +\item addrlen: The size of the address structure. +\end{itemize} +\textit{usrsctp\_bind()} returns 0 on success and -1 in case of an error. + +\subsubsection{usrsctp\_listen()} +The function prototype of \textit{usrsctp\_listen()} is +\begin{verbatim} +int +usrsctp_listen(struct socket *so, + int backlog). + \end{verbatim} +The arguments are +\begin{itemize} +\item so: Pointer to the socket as returned by \textit{usrsctp\_socket()}. +\item backlog: If backlog is non-zero, enable listening, else disable + listening. +\end{itemize} +\textit{usrsctp\_listen()} returns 0 on success and -1 in case of an error. + +\subsubsection{usrsctp\_accept()} +The function prototype of \textit{usrsctp\_accept()} is +\begin{verbatim} +struct socket * +usrsctp_accept(struct socket *so, + struct sockaddr * addr, + socklen_t * addrlen). + \end{verbatim} + The arguments are +\begin{itemize} +\item so: Pointer to the socket as returned by \textit{usrsctp\_socket()}. +\item addr: On return, the primary address of the peer (struct sockaddr\_in for an IPv4 address or + struct sockaddr\_in6 for an IPv6 address). +\item addrlen: Size of the returned address structure. +\end{itemize} +\textit{usrsctp\_accept()} returns the accepted socket on success and NULL in case of an error. + +\subsubsection{usrsctp\_connect()} +The function prototype of \textit{usrsctp\_connect()} is +\begin{verbatim} +int +usrsctp_connect(struct socket *so, + struct sockaddr *name, + socklen_t addrlen) + \end{verbatim} +The arguments are +\begin{itemize} +\item so: Pointer to the socket as returned by \textit{usrsctp\_socket()}. + \item name: Address of the peer to connect to (struct sockaddr\_in for an IPv4 address or + struct sockaddr\_in6 for an IPv6 address). +\item addrlen: Size of the peer's address. +\end{itemize} +\textit{usrsctp\_connect()} returns 0 on success and -1 in case of an error. + +\subsubsection{usrsctp\_shutdown()} +The function prototype of \textit{usrsctp\_shutdown()} is +\begin{verbatim} +int +usrsctp_shutdown(struct socket *so, int how). +\end{verbatim} +The arguments are +\begin{itemize} +\item so: Pointer to the socket of the association to be closed. +\item how: Specifies the type of shutdown. The values are as follows: +\begin{itemize} +\item SHUT\_RD: Disables further receive operations. No SCTP protocol + action is taken. +\item SHUT\_WR: Disables further send operations, and initiates the SCTP + shutdown sequence. +\item SHUT\_RDWR: Disables further send and receive operations, and + initiates the SCTP shutdown sequence. +\end{itemize} +\end{itemize} +\textit{usrsctp\_listen()} returns 0 on success and -1 in case of an error. + +\section{Sending and Receiving Data} +Since the publication of RFC~6458 there is only one function for sending and one for receiving +that is not deprecated. Therefore, only these two are described here. + +\subsection{usrsctp\_sendv()} +The function prototype is +\begin{verbatim} +ssize_t +usrsctp_sendv(struct socket *so, + const void *data, + size_t len, + struct sockaddr *addrs, + int addrcnt, + void *info, + socklen_t infolen, + unsigned int infotype, + int flags). +\end{verbatim} +The arguments are +\begin{itemize} +\item so: The socket to send data on. +\item data: As it is more convenient to send data in a buffer and not a \texttt{struct iovec} data structure, we +chose to pass the data as a void pointer. +\item len: Length of the data. +\item addrs: In this version of usrsctp at most one destination address is supported. In the case of a connected +socket, the parameter \texttt{addrs} can be set to NULL. +\item addrcnt: Number of addresses. As at most one address is supported, addrcnt is 0 if addrs is NULL and +1 otherwise. +\item info: Additional information for a message is stored in \texttt{void *info}. The data types \texttt{struct~sctp\_sndinfo}, +\texttt{struct~sctp\_prinfo}, and \texttt{struct} \linebreak \texttt{sctp\_sendv\_spa} are supported as defined in +RFC~6458. Support for \texttt{structsctp\_authinfo} is not implemented yet, therefore, errno is set EINVAL +and -1 will be returned, if it is used. +\item infolen: Length of info in bytes. +\item infotype: Identifies the type of the information provided in info. Possible values are +SCTP\_SENDV\_NOINFO, SCTP\_SENDV\_SNDINFO, \linebreak SCTP\_SENDV\_PRINFO, SCTP\_SENDV\_SPA. +For additional information please refer to RFC~6458. +\item flags: Flags as described in RFC~6458. +\end{itemize} + +\textit{usrsctp\_sendv()} returns the number of bytes sent, or -1 if an error +occurred. The variable errno is then set appropriately. + +\subsection{usrsctp\_recvv()} +The function prototype is +\begin{verbatim} +ssize_t +usrsctp_recvv(struct socket *so, + void *dbuf, + size_t len, + struct sockaddr *from, + socklen_t * fromlen, + void *info, + socklen_t *infolen, + unsigned int *infotype, + int *msg_flags). +\end{verbatim} +The arguments are +\begin{itemize} +\item so: The socket to receive data on. +\item dbuf: Analog to \textit{usrsctp\_sendv()} the data is returned in a buffer. +\item len: Length of the buffer in bytes. +\item from: A pointer to an address to be filled with the sender of the + received message's address. +\item fromlen: An in/out parameter describing the from length. +\item info: A pointer to the buffer to hold the attributes of the received + message. The structure type of info is determined by the + infotype parameter. The attributes returned in \texttt{info} have to be + handled in the same way as specified in RFC~6458. +\item infolen: An in/out parameter describing the size of the info buffer. +\item infotype: On return, *infotype is set to the type of the info + buffer. The current defined values are SCTP\_RECVV\_NOINFO, + SCTP\_RECVV\_RCVINFO, SCTP\_RECVV\_NXTINFO, and + SCTP\_RECVV\_RN. A detailed description is given in RFC~6458. +\item flags: A pointer to an integer to be filled with any message flags + (e.g., MSG\_NOTIFICATION). Note that this field is an in/out + parameter. Options for the receive may also be passed into the + value (e.g., MSG\_EOR). Returning from the call, the flags' value + will differ from its original value. +\end{itemize} + +\textit{usrsctp\_recvv()} returns the number of bytes sent, or -1 if an error +occurred. The variable errno is then set appropriately. + + + +\section{Socket Options} +Socket options are used to change the default behavior of socket calls. +Their behavior is specified in RFC~6458. The functions to get or set them are + +\begin{verbatim} +int +usrsctp_getsockopt(struct socket *so, + int level, + int optname, + void *optval, + socklen_t *optlen) +\end{verbatim} +and +\begin{verbatim} +int +usrsctp_setsockopt(struct socket *so, + int level, + int optname, + const void *optval, + socklen_t optlen). +\end{verbatim} + +and the arguments are +\begin{itemize} +\item so: The socket of type struct socket. +\item level: Set to IPPROTO\_SCTP for all SCTP options. +\item optname: The option name as specified in Table~\ref{options}. +\item optval: The buffer to store the value of the option as specified in the second column of Table~\ref{options}. +\item optlen: The size of the buffer (or the length of the option + returned in case of \textit{usrsctp\_getsockopt}). +\end{itemize} + +These functions return 0 on success and -1 in case of an error. + +\begin{longtable}{|l|l|c|} +\hline +{\bfseries Option}&{\bfseries Datatype} &{\bfseries r/w}\tabularnewline +\endhead +\hline +SCTP\_RTOINFO&struct sctp\_rtoinfo&r/w\tabularnewline \hline +SCTP\_ASSOCINFO&struct sctp\_assocparams&r/w\tabularnewline \hline +SCTP\_INITMSG&struct sctp\_initmsg&r/w\tabularnewline \hline +SCTP\_NODELAY&int&r/w\tabularnewline \hline +SCTP\_AUTOCLOSE&int&r/w\tabularnewline \hline +SCTP\_PRIMARY\_ADDR&struct sctp\_setprim&r/w\tabularnewline \hline +SCTP\_ADAPTATION\_LAYER&struct sctp\_setadaptation&r/w\tabularnewline \hline +SCTP\_DISABLE\_FRAGMENTS&int&r/w\tabularnewline \hline +SCTP\_PEER\_ADDR\_PARAMS&struct sctp\_paddrparams&r/w\tabularnewline \hline +SCTP\_I\_WANT\_MAPPED\_V4\_ADDR&int&r/w\tabularnewline \hline +SCTP\_MAXSEG&struct sctp\_assoc\_value&r/w\tabularnewline \hline +SCTP\_DELAYED\_SACK&struct sctp\_sack\_info&r/w\tabularnewline \hline +SCTP\_FRAGMENT\_INTERLEAVE&int&r/w\tabularnewline \hline +SCTP\_PARTIAL\_DELIVERY\_POINT&int&r/w\tabularnewline \hline +SCTP\_HMAC\_IDENT&struct sctp\_hmacalgo&r/w\tabularnewline \hline +SCTP\_AUTH\_ACTIVE\_KEY&struct sctp\_authkeyid&r/w\tabularnewline \hline +SCTP\_AUTO\_ASCONF&int&r/w\tabularnewline \hline +SCTP\_MAX\_BURST&struct sctp\_assoc\_value&r/w\tabularnewline \hline +SCTP\_CONTEXT&struct sctp\_assoc\_value&r/w\tabularnewline \hline +SCTP\_EXPLICIT\_EOR&int&r/w\tabularnewline \hline +SCTP\_REUSE\_PORT&int&r/w\tabularnewline \hline +SCTP\_EVENT&struct sctp\_event&r/w\tabularnewline \hline +SCTP\_RECVRCVINFO&int&r/w\tabularnewline \hline +SCTP\_RECVNXTINFO&int&r/w\tabularnewline \hline +SCTP\_DEFAULT\_SNDINFO&struct sctp\_sndinfo&r/w\tabularnewline \hline +SCTP\_DEFAULT\_PRINFO&struct sctp\_default\_prinfo&r/w\tabularnewline \hline +SCTP\_REMOTE\_UDP\_ENCAPS\_PORT&int&r/w\tabularnewline \hline +SCTP\_ENABLE\_STREAM\_RESET&struct sctp\_assoc\_value&r/w\tabularnewline \hline +SCTP\_STATUS&struct sctp\_status&r\tabularnewline \hline +SCTP\_GET\_PEER\_ADDR\_INFO&struct sctp\_paddrinfo&r\tabularnewline \hline +SCTP\_PEER\_AUTH\_CHUNKS&struct sctp\_authchunks&r\tabularnewline \hline +SCTP\_LOCAL\_AUTH\_CHUNKS&struct sctp\_authchunks&r\tabularnewline \hline +SCTP\_GET\_ASSOC\_NUMBER&uint32\_t&r\tabularnewline \hline +SCTP\_GET\_ASSOC\_ID\_LIST&struct sctp\_assoc\_ids&r\tabularnewline \hline +SCTP\_RESET\_STREAMS&struct sctp\_reset\_streams&w\tabularnewline \hline +SCTP\_RESET\_ASSOC&struct sctp\_assoc\_t&w\tabularnewline \hline +SCTP\_ADD\_STREAMS&struct sctp\_add\_streams&w\tabularnewline \hline +\caption{Socket Options supported by usrsctp} +\label{options} +\end{longtable} +An overview of the supported options is given in Table~\ref{options}. Their use is described in RFC~6458~\cite{socketAPI}, RFC~6525~\cite{streamReset}, and~\cite{udpencaps}. + +\section{Sysctl variables} + +In kernel implementations like for instance FreeBSD, it is possible to change parameters +in the operating system. These parameters are called sysctl variables. + +In usrsctp applications can set or retrieve these variables with the functions +\begin{verbatim} +void +usrsctp_sysctl_set_ ## (uint32_t value) +\end{verbatim} +and +\begin{verbatim} +uint32_t +usrsctp_sysctl_get_ ## (void) +\end{verbatim} +respectively, where \#\# stands for the name of the variable. + +In the following paragraphs a short description of the parameters will be given. + +\subsection{Manipulate Memory} +\subsubsection{usrsctp\_sysctl\_set\_sctp\_sendspace()} +The space of the available send buffer can be changed from its default value of 262,144 bytes +to a value between 0 and $2^{32}-1$ bytes. + +\subsubsection{usrsctp\_sysctl\_set\_sctp\_recvspace()} +The space of the available receive buffer can be changed from its default value of 262,144 bytes +to a value between 0 and $2^{32}-1$ bytes. + +\subsubsection{usrsctp\_sysctl\_set\_sctp\_hashtblsize()} +The TCB (Thread Control Block) hash table sizes, i.e. the size of one TCB in the hash table, can be tuned between +1 and $2^{32}-1$ bytes. The default value is 1,024 bytes. A TCB contains for instance pointers to the socket, the +endpoint, information about the association and some statistic data. + +\subsubsection{usrsctp\_sysctl\_set\_sctp\_pcbtblsize()} +The PCB (Protocol Control Block) hash table sizes, i.e. the size of one PCB in the hash table, can be tuned between +1 and $2^{32}-1$ bytes. The default value is 256 bytes. The PCB contains all variables that characterize an endpoint. + +\subsubsection{usrsctp\_sysctl\_set\_sctp\_system\_free\_resc\_limit()} +This parameters tunes the maximum number of cached resources in the system. It can be set between +0 and $2^{32}-1$. The default value is 1000. + +\subsubsection{usrsctp\_sysctl\_set\_sctp\_asoc\_free\_resc\_limit()} +This parameters tunes the maximum number of cached resources in an association. It can be set between +0 and $2^{32}-1$. The default value is 10. + +\subsubsection{usrsctp\_sysctl\_set\_sctp\_mbuf\_threshold\_count()} +Data is stored in mbufs. Several mbufs can be chained together. The maximum number of small mbufs in a chain +can be set with this parameter, before an mbuf cluset is used. The default is 5. + +\subsubsection{usrsctp\_sysctl\_set\_sctp\_add\_more\_threshold()} +TBD +This parameter configures the threshold below which more space should be added to a socket send buffer. +The default value is 1452 bytes. + + +\subsection{Configure RTO} +The retransmission timeout (RTO), i.e. the time that controls the retransmission of messages, has +several parameters, that can be changed, for example to shorten the time, before a message is +retransmitted. The range of these parameters is between 0 and $2^{32}-1$~ms. + +\subsubsection{usrsctp\_sysctl\_set\_sctp\_rto\_max\_default()} +The default value for the maximum retransmission timeout in ms is 60,000 (60~secs). + +\subsubsection{usrsctp\_sysctl\_set\_sctp\_rto\_min\_default()} +The default value for the minimum retransmission timeout in ms is 1,000 (1~sec). + +\subsubsection{usrsctp\_sysctl\_set\_sctp\_rto\_initial\_default()} +The default value for the initial retransmission timeout in ms is 3,000 (3~sec). This value is only +needed before the first calculation of a round trip time took place. + +\subsubsection{usrsctp\_sysctl\_set\_sctp\_init\_rto\_max\_default()} +The default value for the maximum retransmission timeout for an INIT chunk in ms is 60,000 (60~secs). + + +\subsection{Set Timers} +\subsubsection{usrsctp\_sysctl\_set\_sctp\_valid\_cookie\_life\_default()} +A cookie has a specified life time. If it expires the cookie is not valid any more and an ABORT is sent. +The default value in ms is 60,000 (60~secs). + +\subsubsection{usrsctp\_sysctl\_set\_sctp\_heartbeat\_interval\_default()} +Set the default time between two heartbeats. The default is 30,000~ms. + +\subsubsection{usrsctp\_sysctl\_set\_sctp\_shutdown\_guard\_time\_default()} +If a SHUTDOWN is not answered with a SHUTDOWN-ACK while the shutdown guard timer is still +running, the association will be aborted after the default of 180~secs. + +\subsubsection{usrsctp\_sysctl\_set\_sctp\_pmtu\_raise\_time\_default()} +TBD +To set the size of the packets to the highest value possible, the maximum transfer unit (MTU) +of the complete path has to be known. The default time interval for the path mtu discovery +is 600~secs. + +\subsubsection{usrsctp\_sysctl\_set\_sctp\_secret\_lifetime\_default()} +TBD +The default secret lifetime of a server is 3600~secs. + +\subsubsection{usrsctp\_sysctl\_set\_sctp\_vtag\_time\_wait()} +TBD +Vtag time wait time, 0 disables it. Default: 60~secs + + +\subsection{Set Failure Limits} +Transmissions and retransmissions of messages might fail. To protect the system against too many +retransmissions, limits have to be defined. + +\subsubsection{usrsctp\_sysctl\_set\_sctp\_init\_rtx\_max\_default()} +The default maximum number of retransmissions of an INIT chunks is 8, before an ABORT is sent. + +\subsubsection{usrsctp\_sysctl\_set\_sctp\_assoc\_rtx\_max\_default()} +This parameter sets the maximum number of failed retransmissions before the association is aborted. +The default vaule is 10. + +\subsubsection{usrsctp\_sysctl\_set\_sctp\_path\_rtx\_max\_default()} +This parameter sets the maximum number of path failures before the association is aborted. +The default value is 5. Notice that the number of paths multiplied by this value should be +equal to sctp\_assoc\_rtx\_max\_default. That means that the default configuration is good for two +paths. + +\subsubsection{usrsctp\_sysctl\_set\_sctp\_max\_retran\_chunk()} +The parameter configures how many times an unlucky chunk can be retransmitted before the +association aborts. The default is set to 30. + +\subsubsection{usrsctp\_sysctl\_set\_sctp\_path\_pf\_threshold()} +TBD +Default potentially failed threshold. Default: 65535 + +\subsubsection{usrsctp\_sysctl\_set\_sctp\_abort\_if\_one\_2\_one\_hits\_limit()} +TBD +When one-2-one hits qlimit abort. Default: 0 + + +\subsection{Control the Sending of SACKs} +\subsubsection{usrsctp\_sysctl\_set\_sctp\_sack\_freq\_default()} +The SACK frequency defines the number of packets that are awaited, before a SACK is sent. +The default value is 2. + +\subsubsection{usrsctp\_sysctl\_set\_sctp\_delayed\_sack\_time\_default()} +As a SACK (Selective Acknowlegment) is sent after every other packet, a timer is set to send a +SACK in case another packet does not arrive in due time. The default value for this timer is +200~ms. + +\subsubsection{usrsctp\_sysctl\_set\_sctp\_strict\_sacks()} +TBD +This is a flag to turn the controlling of the coherence of SACKs on or off. The default value is +1 (on). + +\subsubsection{usrsctp\_sysctl\_set\_sctp\_nr\_sack\_on\_off()} +If a slow hosts receives data on a lossy link it is possible that its receiver window is full and new +data can only be accepted if one chunk with a higher TSN (Transmission Sequence Number) that has +previously been acknowledged is dropped. As a consequence the sender has to store data, even if +they have been acknowledged in case they have to be retransmitted. If this behavior is not necessary, +non-renegable SACKs can be turned on. +By default the use of non-renegable SACKs is turned off. + +\subsubsection{usrsctp\_sysctl\_set\_sctp\_enable\_sack\_immediately()} +In some cases it is not desirable to wait for the SACK timer to expire before a SACK is sent. In these +cases a bit called SACK-IMMEDIATELY~\cite{sack-imm} can be set to provoke the instant sending of a SACK. +The default is to turn it off. + +\subsubsection{usrsctp\_sysctl\_set\_sctp\_L2\_abc\_variable()} +TBD +SCTP ABC max increase per SACK (L). Default: 1 + +\subsection{Change Max Burst} +Max burst defines the maximum number of packets that may be sent in one flight. + +\subsubsection{usrsctp\_sysctl\_set\_sctp\_max\_burst\_default()} +The default value for max burst is 0, which means that the number of packets sent as a flight +is not limited by this parameter, but may be by another one, see the next paragraph. + +\subsubsection{usrsctp\_sysctl\_set\_sctp\_use\_cwnd\_based\_maxburst()} +The use of max burst is based on the size of the congestion window (cwnd). +This parameter is set by default. + +\subsubsection{usrsctp\_sysctl\_set\_sctp\_hb\_maxburst()} +Heartbeats are mostly used to verify a path. Their number can be limited. The default is 4. + +\subsubsection{usrsctp\_sysctl\_set\_sctp\_fr\_max\_burst\_default()} +In the state of fast retransmission the number of packet bursts can be limited. The default +value is 4. + + +\subsection{Handle Chunks} +\subsubsection{usrsctp\_sysctl\_set\_sctp\_peer\_chunk\_oh()} +In order to keep track of the peer's advertised receiver window, the sender calculates the window by +subtracting the amount of data sent. Yet, some OSs reduce the receiver window by the real space needed +to store the data. This parameter sets the additional amount to debit the peer's receiver window per +chunk sent. The default value is 256, which is the value needed by FreeBSD. + +\subsubsection{usrsctp\_sysctl\_set\_sctp\_max\_chunks\_on\_queue()} +This parameter sets the maximum number of chunks that can be queued per association. The default +value is 512. + +\subsubsection{usrsctp\_sysctl\_set\_sctp\_min\_split\_point()} +TBD +The minimum size when splitting a chunk is 2904 bytes by default. + +\subsubsection{usrsctp\_sysctl\_set\_sctp\_chunkscale()} +TBD +This parameter can be tuned for scaling of number of chunks and messages. The default is10. + +\subsubsection{usrsctp\_sysctl\_set\_sctp\_min\_residual()} +TBD +This parameter configures the minimum size of the residual data chunk in the second +part of the split. The default is 1452. + + +\subsection{Calculate RTT} +The calculation of the round trip time (RTT) depends on several parameters. + +\subsubsection{usrsctp\_sysctl\_set\_sctp\_rttvar\_bw()} +TBD +Shift amount for bw smoothing on rtt calc. Default: 4 + +\subsubsection{usrsctp\_sysctl\_set\_sctp\_rttvar\_rtt()} +TBD +Shift amount for rtt smoothing on rtt calc. Default: 5 + +\subsubsection{usrsctp\_sysctl\_set\_sctp\_rttvar\_eqret()} +TBD +What to return when rtt and bw are unchanged. Default: 0 + + +\subsection{Influence the Congestion Control} +The congestion control should protect the network against fast senders. + +\subsubsection{usrsctp\_sysctl\_set\_sctp\_ecn\_enable} +Explicit congestion notifications are turned on by default. + +\subsubsection{usrsctp\_sysctl\_set\_sctp\_default\_cc\_module()} +This parameter sets the default algorithm for the congestion control. +Default is 0, i.e. the one specified in RFC~4960. + +\subsubsection{usrsctp\_sysctl\_set\_sctp\_initial\_cwnd()} +Set the initial congestion window in MTUs. The default is 3. + +\subsubsection{usrsctp\_sysctl\_set\_sctp\_use\_dccc\_ecn()} +TBD +Enable for RTCC CC datacenter ECN. Default: 1 + +\subsubsection{usrsctp\_sysctl\_set\_sctp\_steady\_step()} +TBD +How many the sames it takes to try step down of cwnd. Default: 20 + + +\subsection{Configure AUTH and ADD-IP} +An important extension of SCTP is the dynamic address reconfiguration~\cite{addip}, also known as +ADD-IP, which allows the changing of addresses during the lifetime of an association. +For this feature the AUTH extension~\cite{auth} is necessary. + +\subsubsection{usrsctp\_sysctl\_set\_sctp\_auto\_asconf()} +If SCTP Auto-ASCONF is enabled, the peer is informed automatically when a new address +is added or removed. This feature is enabled by default. + +\subsubsection{usrsctp\_sysctl\_set\_sctp\_multiple\_asconfs()} +By default the sending of multiple ASCONFs is disabled. + +\subsubsection{usrsctp\_sysctl\_set\_sctp\_auth\_disable()} +The use of AUTH, which is normally turned on, can be disabled by setting this parameter to 1. + +\subsubsection{usrsctp\_sysctl\_set\_sctp\_asconf\_auth\_nochk()} +It is also possible to disable the requirement to use AUTH in conjunction with ADD-IP by setting this parameter +to 1. + + +\subsection{Concurrent Multipath Transfer (CMT)} +A prominent feature of SCTP is the possibility to use several addresses for the same association. +One is the primary path, and the others are needed in case of a path failure. Using CMT the data is sent +on several paths to enhance the throughput. + +\subsubsection{usrsctp\_sysctl\_set\_sctp\_cmt\_on\_off()} +To turn CMT on, this parameter has to be set to 1. + +\subsubsection{usrsctp\_sysctl\_set\_sctp\_cmt\_use\_dac()} +To use delayed acknowledgments with CMT this parameter has to be set to 1. + +\subsubsection{usrsctp\_sysctl\_set\_sctp\_buffer\_splitting()} +For CMT it makes sense to split the send and receive buffer to have shares for each path. +By default buffer splitting is turned off. + + +\subsection{Network Address Translation (NAT)} +To be able to pass NAT boxes, the boxes have to handle SCTP packets in a specific way. + +\subsubsection{usrsctp\_sysctl\_set\_sctp\_nat\_friendly()} +SCTP NAT friendly operation. Default:1 + +\subsubsection{usrsctp\_sysctl\_set\_sctp\_inits\_include\_nat\_friendly()} +Enable sending of the nat-friendly SCTP option on INITs. Default: 0 + +\subsubsection{usrsctp\_sysctl\_set\_sctp\_udp\_tunneling\_port()} +Set the SCTP/UDP tunneling port. Default: 9899 + +\subsection{SCTP Mobility} +\subsubsection{usrsctp\_sysctl\_set\_sctp\_mobility\_base()} +TBD +Enable SCTP base mobility. Default: 0 + + +\subsubsection{usrsctp\_sysctl\_set\_sctp\_mobility\_fasthandoff()} +TBD +Enable SCTP fast handoff. default: 0 + + +\subsection{Miscellaneous} +\subsubsection{usrsctp\_sysctl\_set\_sctp\_no\_csum\_on\_loopback()} +Calculating the checksum for packets sent on loopback is turned off by default. +To turn it on, set this parameter to 0. + +\subsubsection{usrsctp\_sysctl\_set\_sctp\_nr\_outgoing\_streams\_default()} +The peer is notified about the number of outgoing streams in the INIT or INIT-ACK chunk. +The default is 10. + +\subsubsection{usrsctp\_sysctl\_set\_sctp\_do\_drain()} +Determines whether SCTP should respond to the drain calls. Default: 1 + +\subsubsection{usrsctp\_sysctl\_set\_sctp\_strict\_data\_order()} +TBD +Enforce strict data ordering, abort if control inside data. Default: 0 + +\subsubsection{usrsctp\_sysctl\_set\_sctp\_default\_ss\_module()} +Set the default stream scheduling module. Implemented modules are: +SCTP\_SS\_DEFAULT, SCTP\_SS\_ROUND\_ROBIN, SCTP\_SS\_ROUND\_ROBIN\_PACKET, +SCTP\_SS\_PRIORITY, SCTP\_SS\_FAIR\_BANDWITH, and SCTP\_SS\_FIRST\_COME. + +\subsubsection{usrsctp\_sysctl\_set\_sctp\_default\_frag\_interleave()} +TBD +Default fragment interleave level. Default: 1 + +\subsubsection{usrsctp\_sysctl\_set\_sctp\_blackhole()} +TBD +Enable SCTP blackholing. Default: 0 + +\subsubsection{usrsctp\_sysctl\_set\_sctp\_logging\_level()} +Set the logging level. The default is 0. + + +\subsubsection{usrsctp\_sysctl\_set\_sctp\_debug\_on()} +Turn debug output on or off. It is disabled by default. To obtain debug output, +SCTP\_DEBUG has to be set as a compile flag. + + +%The following variables are supported: +%\begin{longtable}{|l|l|c|} +%\hline +%{\bfseries Parameter}&{\bfseries Meaning}&{\bfseries Default Value} \tabularnewline +%\endhead +%\hline +%sctp\_sendspace&Send buffer space&1864135\tabularnewline \hline +%sctp\_recvspace&Receive buffer space&1864135 \tabularnewline \hline +%sctp\_hashtblsize&Tunable for TCB hash table sizes&1024 \tabularnewline \hline +%sctp\_pcbtblsize&Tunable for PCB hash table sizes&256 \tabularnewline \hline +%sctp\_system\_free\_resc\_limit&Cached resources in the system&1000 \tabularnewline \hline +%sctp\_asoc\_free\_resc\_limit&Cashed resources in an association&10 \tabularnewline \hline +%sctp\_rto\_max\_default&Default value for RTO\_max&60000~ms \tabularnewline \hline +%sctp\_rto\_min\_default&Default value for RTO\_min&1000~ms \tabularnewline \hline +%sctp\_rto\_initial\_default&Default value for RTO\_initial&3000~ms \tabularnewline \hline +%sctp\_init\_rto\_max\_default&Default value for the maximum RTO&60000~ms \tabularnewline + % &for sending an INIT& \tabularnewline \hline +%sctp\_valid\_cookie\_life\_default&Valid cookie life time&60000~ms \tabularnewline \hline +%sctp\_init\_rtx\_max\_default&Maximum number of INIT retransmissions&8 \tabularnewline \hline +%sctp\_assoc\_rtx\_max\_default&Maximum number of failed retransmissions&10\tabularnewline +% & before the association is aborted&\tabularnewline \hline +%sctp\_path\_rtx\_max\_default&Maximum number of failed retransmissions&5\tabularnewline +% &before a path fails&\tabularnewline \hline +%sctp\_ecn\_enable&Enabling explicit congestion notifications&1\tabularnewline \hline +%sctp\_strict\_sacks&Control the coherence of SACKs&1 \tabularnewline \hline +%sctp\_delayed\_sack\_time\_default&Default delayed SACK timer&200~ms\tabularnewline \hline +%sctp\_sack\_freq\_default&Default SACK frequency&2 \tabularnewline \hline +%sctp\_nr\_sack\_on\_off&Turn non-renegable SACKs on or off&0 \tabularnewline \hline +%sctp\_enable\_sack\_immediately&Enable sending of the SACK-&0 \tabularnewline &IMMEDIATELY bit.&\tabularnewline \hline +%sctp\_no\_csum\_on\_loopback&Enable the compilation of the checksum on&1 \tabularnewline +% &packets sent on loopback&\tabularnewline \hline +%sctp\_peer\_chunk\_oh&Amount to debit peers rwnd per chunk sent&256 \tabularnewline \hline +%sctp\_max\_burst\_default&Default max burst for SCTP endpoints&0 \tabularnewline \hline +%sctp\_use\_cwnd\_based\_maxburst&Use max burst based on the size of &1\tabularnewline % &the congestion window&\tabularnewline \hline +%sctp\_hb\_maxburst&Confirmation Heartbeat max burst&4 \tabularnewline \hline +%sctp\_max\_chunks\_on\_queue&Default max chunks on queue per asoc&512 \tabularnewline \hline +%sctp\_min\_split\_point&Minimum size when splitting a chunk&2904 \tabularnewline \hline +%sctp\_chunkscale&Tunable for Scaling of number of chunks and&10\tabularnewline +% &messages&\tabularnewline \hline +%sctp\_mbuf\_threshold\_count&Maximum number of small mbufs in a chain&5\tabularnewline \hline +%sctp\_heartbeat\_interval\_default&Deafult time between two Heartbeats&30000~ms\tabularnewline \hline +%sctp\_pmtu\_raise\_time\_default&Default PMTU raise timer&600~secs\tabularnewline \hline +%sctp\_shutdown\_guard\_time\_default&Default shutdown guard timer&180~secs\tabularnewline \hline +%sctp\_secret\_lifetime\_default&Default secret lifetime&3600~secs \tabularnewline \hline +%sctp\_add\_more\_threshold&Threshold when more space should &1452\tabularnewline +% &be added to a socket send buffer&\tabularnewline \hline +%sctp\_nr\_outgoing\_streams\_default&Default number of outgoing streams&10\tabularnewline \hline +%sctp\_cmt\_on\_off&Turn CMT on or off.&0\tabularnewline \hline +%sctp\_cmt\_use\_dac&Use delayed acknowledgment for CMT&0\tabularnewline \hline +%sctp\_fr\_max\_burst\_default&Default max burst for SCTP endpoints when &4\tabularnewline +% &fast retransmitting&\tabularnewline \hline +%sctp\_auto\_asconf&Enable SCTP Auto-ASCONF&1\tabularnewline \hline +%sctp\_multiple\_asconfs&Enable SCTP Muliple-ASCONFs&0 \tabularnewline \hline +%sctp\_asconf\_auth\_nochk&Disable SCTP ASCONF AUTH requirement&0\tabularnewline \hline +%sctp\_auth\_disable&Disable SCTP AUTH function&0\tabularnewline \hline +%sctp\_nat\_friendly&SCTP NAT friendly operation&1\tabularnewline \hline +%sctp\_inits\_include\_nat\_friendly&Enable sending of the nat-friendly &0\tabularnewline +% &SCTP option on INITs.&\tabularnewline \hline +%sctp\_udp\_tunneling\_port&Set the SCTP/UDP tunneling port&9899\tabularnewline \hline +%sctp\_do\_drain&Determines whether SCTP should respond&1\tabularnewline +% &to the drain calls&\tabularnewline \hline +%sctp\_abort\_if\_one\_2\_one\_hits\_limit&When one-2-one hits qlimit abort&0 \tabularnewline \hline +%sctp\_strict\_data\_order&Enforce strict data ordering, abort if control&0\tabularnewline +% &inside data&\tabularnewline \hline +%sctp\_min\_residual&Minimum residual data chunk in second&1452\tabularnewline +% &part of split&\tabularnewline \hline +%sctp\_max\_retran\_chunk&Maximum times an unlucky chunk can be&30\tabularnewline +% & retransmitted before the association aborts&\tabularnewline \hline +%sctp\_default\_cc\_module&Default congestion control module&0\tabularnewline \hline +%sctp\_default\_ss\_module&Default stream scheduling module&0 \tabularnewline \hline +%sctp\_default\_frag\_interleave&Default fragment interleave level&1\tabularnewline \hline +%sctp\_mobility\_base&Enable SCTP base mobility&0\tabularnewline \hline +%sctp\_mobility\_fasthandoff&Enable SCTP fast handoff&0\tabularnewline \hline +%sctp\_L2\_abc\_variable&SCTP ABC max increase per SACK (L)&1\tabularnewline \hline +%sctp\_vtag\_time\_wait&Vtag time wait time, 0 disables it.&60~secs\tabularnewline \hline +%sctp\_blackhole&Enable SCTP blackholing&0\tabularnewline \hline +%sctp\_path\_pf\_threshold&Default potentially failed threshold&65535\tabularnewline \hline +%sctp\_rttvar\_bw&Shift amount for bw smoothing on rtt calc&4 \tabularnewline \hline +%sctp\_rttvar\_rtt&Shift amount for rtt smoothing on rtt calc&5 \tabularnewline \hline +%sctp\_rttvar\_eqret &What to return when rtt and bw are&0\tabularnewline +% &unchanged&\tabularnewline \hline +%sctp\_steady\_step&How many the sames it takes to try step&20\tabularnewline +% &down of cwnd&\tabularnewline \hline +%sctp\_use\_dccc\_ecn&Enable for RTCC CC datacenter ECN&1 \tabularnewline \hline +%sctp\_buffer\_splitting&Enable send/receive buffer splitting&0 \tabularnewline \hline +%sctp\_initial\_cwnd&Initial congestion window in MTUs&3\tabularnewline \hline +%sctp\_logging\_level&Logging level&0 \tabularnewline \hline +%sctp\_debug\_on&Turns debug output on or off.&0 \tabularnewline \hline + +%\caption{Sysctl variables supported by usrsctp} +%\end{longtable} + +\section{Examples} +\subsection{Discard Server}\label{server} +\begin{verbatim} +/* + * Copyright (C) 2011-2012 Michael Tuexen + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Usage: discard_server [local_encaps_port] [remote_encaps_port] + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#if !defined(__Userspace_os_Windows) +#include <unistd.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#endif +#include <usrsctp.h> + +#define BUFFER_SIZE 10240 + +const int use_cb = 0; + +static int +receive_cb(struct socket *sock, union sctp_sockstore addr, void *data, + size_t datalen, struct sctp_rcvinfo rcv, int flags) +{ + char name[INET6_ADDRSTRLEN]; + + if (data) { + if (flags & MSG_NOTIFICATION) { + printf("Notification of length %d received.\n", (int)datalen); + } else { + printf("Msg of length %d received from %s:%u on stream %d with " + "SSN %u and TSN %u, PPID %d, context %u.\n", + (int)datalen, + addr.sa.sa_family == AF_INET ? + inet_ntop(AF_INET, &addr.sin.sin_addr, name, + INET6_ADDRSTRLEN): + inet_ntop(AF_INET6, &addr.sin6.sin6_addr, name, + INET6_ADDRSTRLEN), + ntohs(addr.sin.sin_port), + rcv.rcv_sid, + rcv.rcv_ssn, + rcv.rcv_tsn, + ntohl(rcv.rcv_ppid), + rcv.rcv_context); + } + free(data); + } + return 1; +} + +int +main(int argc, char *argv[]) +{ + struct socket *sock; + struct sockaddr_in6 addr; + struct sctp_udpencaps encaps; + struct sctp_event event; + uint16_t event_types[] = {SCTP_ASSOC_CHANGE, + SCTP_PEER_ADDR_CHANGE, + SCTP_REMOTE_ERROR, + SCTP_SHUTDOWN_EVENT, + SCTP_ADAPTATION_INDICATION, + SCTP_PARTIAL_DELIVERY_EVENT}; + unsigned int i; + struct sctp_assoc_value av; + const int on = 1; + int n, flags; + socklen_t from_len; + char buffer[BUFFER_SIZE]; + char name[INET6_ADDRSTRLEN]; + struct sctp_recvv_rn rn; + socklen_t infolen = sizeof(struct sctp_recvv_rn); + struct sctp_rcvinfo rcv; + struct sctp_nxtinfo nxt; + unsigned int infotype = 0; + + if (argc > 1) { + usrsctp_init(atoi(argv[1])); + } else { + usrsctp_init(9899); + } + usrsctp_sysctl_set_sctp_debug_on(0); + usrsctp_sysctl_set_sctp_blackhole(2); + + if ((sock = usrsctp_socket(AF_INET6, SOCK_SEQPACKET, IPPROTO_SCTP, + use_cb?receive_cb:NULL, NULL, 0)) == NULL) { + perror("userspace_socket"); + } + if (usrsctp_setsockopt(sock, IPPROTO_SCTP, SCTP_I_WANT_MAPPED_V4_ADDR, + (const void*)&on, (socklen_t)sizeof(int)) < 0) { + perror("setsockopt"); + } + memset(&av, 0, sizeof(struct sctp_assoc_value)); + av.assoc_id = SCTP_ALL_ASSOC; + av.assoc_value = 47; + + if (usrsctp_setsockopt(sock, IPPROTO_SCTP, SCTP_CONTEXT, (const void*)&av, + (socklen_t)sizeof(struct sctp_assoc_value)) < 0) { + perror("setsockopt"); + } + if (argc > 2) { + memset(&encaps, 0, sizeof(struct sctp_udpencaps)); + encaps.sue_address.ss_family = AF_INET6; + encaps.sue_port = htons(atoi(argv[2])); + if (usrsctp_setsockopt(sock, IPPROTO_SCTP, SCTP_REMOTE_UDP_ENCAPS_PORT, + (const void*)&encaps, + (socklen_t)sizeof(struct sctp_udpencaps)) < 0) { + perror("setsockopt"); + } + } + memset(&event, 0, sizeof(event)); + event.se_assoc_id = SCTP_FUTURE_ASSOC; + event.se_on = 1; + for (i = 0; i < (unsigned int)(sizeof(event_types)/sizeof(uint16_t)); i++) { + event.se_type = event_types[i]; + if (usrsctp_setsockopt(sock, IPPROTO_SCTP, SCTP_EVENT, &event, + sizeof(struct sctp_event)) < 0) { + perror("userspace_setsockopt"); + } + } + memset((void *)&addr, 0, sizeof(struct sockaddr_in6)); +#ifdef HAVE_SIN_LEN + addr.sin6_len = sizeof(struct sockaddr_in6); +#endif + addr.sin6_family = AF_INET6; + addr.sin6_port = htons(9); + addr.sin6_addr = in6addr_any; + if (usrsctp_bind(sock, (struct sockaddr *)&addr, + sizeof(struct sockaddr_in6)) < 0) { + perror("userspace_bind"); + } + if (usrsctp_listen(sock, 1) < 0) { + perror("userspace_listen"); + } + while (1) { + if (use_cb) { +#if defined (__Userspace_os_Windows) + Sleep(1*1000); +#else + sleep(1); +#endif + } else { + from_len = (socklen_t)sizeof(struct sockaddr_in6); + flags = 0; + rn.recvv_rcvinfo = rcv; + rn.recvv_nxtinfo = nxt; + n = usrsctp_recvv(sock, (void*)buffer, BUFFER_SIZE, + (struct sockaddr *) &addr, &from_len, (void *)&rn, + &infolen, &infotype, &flags); + if (n > 0) { + if (flags & MSG_NOTIFICATION) { + printf("Notification of length %d received.\n", n); + } else { + printf("Msg of length %d received from %s:%u on stream " + "%d with SSN %u and TSN %u, PPID %d, context %u, " + "complete %d.\n", + n, + inet_ntop(AF_INET6, &addr.sin6_addr, name, + INET6_ADDRSTRLEN), ntohs(addr.sin6_port), + rn.recvv_rcvinfo.rcv_sid, + rn.recvv_rcvinfo.rcv_ssn, + rn.recvv_rcvinfo.rcv_tsn, + ntohl(rn.recvv_rcvinfo.rcv_ppid), + rn.recvv_rcvinfo.rcv_context, + (flags & MSG_EOR) ? 1 : 0); + } + } + } + } + usrsctp_close(sock); + while (usrsctp_finish() != 0) { +#if defined (__Userspace_os_Windows) + Sleep(1000); +#else + sleep(1); +#endif + } + return (0); +} + +\end{verbatim} + +\subsection{Client}\label{client} +\begin{verbatim} +/* + * Copyright (C) 2011-2012 Michael Tuexen + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Usage: client remote_addr remote_port [local_encaps_port remote_encaps_port] + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#if !defined(__Userspace_os_Windows) +#include <unistd.h> +#endif +#include <sys/types.h> +#if !defined(__Userspace_os_Windows) +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#endif +#include <usrsctp.h> + +int done = 0; + +static int +receive_cb(struct socket *sock, union sctp_sockstore addr, void *data, + size_t datalen, struct sctp_rcvinfo rcv, int flags) +{ + if (data == NULL) { + done = 1; + usrsctp_close(sock); + } else { + write(fileno(stdout), data, datalen); + free(data); + } + return 1; +} + +int +main(int argc, char *argv[]) +{ + struct socket *sock; + struct sockaddr_in addr4; + struct sockaddr_in6 addr6; + struct sctp_udpencaps encaps; + char buffer[80]; + + if (argc > 3) { + usrsctp_init(atoi(argv[3])); + } else { + usrsctp_init(9899); + } + usrsctp_sysctl_set_sctp_debug_on(0); + usrsctp_sysctl_set_sctp_blackhole(2); + if ((sock = usrsctp_socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP, + receive_cb, NULL, 0)) == NULL) { + perror("userspace_socket ipv6"); + } + if (argc > 4) { + memset(&encaps, 0, sizeof(struct sctp_udpencaps)); + encaps.sue_address.ss_family = AF_INET6; + encaps.sue_port = htons(atoi(argv[4])); + if (usrsctp_setsockopt(sock, IPPROTO_SCTP, SCTP_REMOTE_UDP_ENCAPS_PORT, + (const void*)&encaps, + (socklen_t)sizeof(struct sctp_udpencaps)) < 0) { + perror("setsockopt"); + } + } + memset((void *)&addr4, 0, sizeof(struct sockaddr_in)); + memset((void *)&addr6, 0, sizeof(struct sockaddr_in6)); +#if !defined(__Userspace_os_Linux) && !defined(__Userspace_os_Windows) + addr4.sin_len = sizeof(struct sockaddr_in); + addr6.sin6_len = sizeof(struct sockaddr_in6); +#endif + addr4.sin_family = AF_INET; + addr6.sin6_family = AF_INET6; + addr4.sin_port = htons(atoi(argv[2])); + addr6.sin6_port = htons(atoi(argv[2])); + if (inet_pton(AF_INET6, argv[1], &addr6.sin6_addr) == 1) { + if (usrsctp_connect(sock, (struct sockaddr *)&addr6, + sizeof(struct sockaddr_in6)) < 0) { + perror("userspace_connect"); + } + } else if (inet_pton(AF_INET, argv[1], &addr4.sin_addr) == 1) { + if (usrsctp_connect(sock, (struct sockaddr *)&addr4, + sizeof(struct sockaddr_in)) < 0) { + perror("userspace_connect"); + } + } else { + printf("Illegal destination address.\n"); + } + while ((fgets(buffer, sizeof(buffer), stdin) != NULL) && !done) { + usrsctp_sendv(sock, buffer, strlen(buffer), NULL, 0, + NULL, 0, SCTP_SENDV_NOINFO, 0); + } + if (!done) { + usrsctp_shutdown(sock, SHUT_WR); + } + while (!done) { +#if defined (__Userspace_os_Windows) + Sleep(1*1000); +#else + sleep(1); +#endif + } + while (usrsctp_finish() != 0) { +#if defined (__Userspace_os_Windows) + Sleep(1000); +#else + sleep(1); +#endif + } + return(0); +} + +\end{verbatim} +\bibliographystyle{plain} +% +\begin{thebibliography}{99} + +\bibitem{socketAPI} +R.~Stewart, M.~T\"uxen, K.~Poon, and V.~Yasevich: +\textit{Sockets API Extensions for the Stream Control Transmission Protocol (SCTP)}. +RFC~6458, Dezember~2011. + +\bibitem{SCTP} +R.~Stewart: +\textit{Stream Control Transmission Protocol}. +RFC~4960, September~2007. + + +\bibitem{auth} +M.~T\"uxen, R.~Stewart, P.~Lei, and E.~Rescorla: +\textit{Authenticated Chunks for the Stream Control Transmission Protocol (SCTP)}. +RFC~4895, August~2007. + +\bibitem{streamReset} +R.~Stewart, M.~T\"uxen, and P.~Lei: +\textit{Stream Control Transmission Protocol (SCTP) Stream Reconfiguration}. +RFC~6525, February~2012. + + +\bibitem{addip} +R.~Stewart, Q.~Xie, M.~T\"uxen, S.~Maruyama, and M.~Kozuka: +\textit{Stream Control Transmission Protocol (SCTP) Dynamic Address Reconfiguration}. +RFC~5061, September~2007. + +\bibitem{sack-imm} +M.~T\"uxen, I.~R\"ungeler, and R.~Stewart: +\textit{SACK-IMMEDIATELY Extension for the Stream Control Transmission Protocol}. +draft-tuexen-tsvwg-sctp-sack-immediately-09 (work in progress), April~2012. + +\bibitem{udpencaps} +M.~T\"uxen and R.~Stewart +\textit{UDP Encapsulation of SCTP Packetsl}. +draft-ietf-tsvwg-sctp-udp-encaps-03 (work in progress), March~2012. + +\end{thebibliography} +\end{document} diff --git a/chromium/third_party/usrsctp/usrsctplib/README.md b/chromium/third_party/usrsctp/usrsctplib/README.md new file mode 100644 index 00000000000..c49ab631711 --- /dev/null +++ b/chromium/third_party/usrsctp/usrsctplib/README.md @@ -0,0 +1,7 @@ +# usrsctp + +This is a userland SCTP stack supporting FreeBSD, Linux, Mac OS X and Windows. + +See [manual](Manual.md) for more information. + +The status of continous integration testing is available from [grid](http://212.201.121.77:18010/grid) and [waterfall](http://212.201.121.77:18010/waterfall). diff --git a/chromium/third_party/usrsctp/usrsctplib/bootstrap b/chromium/third_party/usrsctp/usrsctplib/bootstrap new file mode 100755 index 00000000000..0f543bc56c4 --- /dev/null +++ b/chromium/third_party/usrsctp/usrsctplib/bootstrap @@ -0,0 +1,51 @@ +#! /bin/sh +# +# Copyright (C) 2011-2012 Michael Tuexen +# +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the project nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# + +if [ -e /usr/bin/glibtoolize ] ; then + glibtoolize --force +elif [ -e /usr/bin/libtoolize ] ; then + libtoolize --force +elif [ -e /usr/local/bin/libtoolize ] ; then + libtoolize --force +elif [ -e /usr/local/bin/glibtoolize ] ; then + glibtoolize --force +else + echo "ERROR: I cannot find libtoolize or glibtoolize!" + exit 1 +fi + +if [ -e /usr/local/share/aclocal ] ; then + aclocal -I /usr/local/share/aclocal +else + aclocal -I /usr/share/aclocal +fi +autoconf +automake --foreign --add-missing --copy diff --git a/chromium/third_party/usrsctp/usrsctplib/configure.ac b/chromium/third_party/usrsctp/usrsctplib/configure.ac new file mode 100644 index 00000000000..f3375cc46cb --- /dev/null +++ b/chromium/third_party/usrsctp/usrsctplib/configure.ac @@ -0,0 +1,177 @@ +dnl +dnl Copyright (C) 2011-2012 Michael Tuexen +dnl +dnl All rights reserved. +dnl +dnl Redistribution and use in source and binary forms, with or without +dnl modification, are permitted provided that the following conditions +dnl are met: +dnl 1. Redistributions of source code must retain the above copyright +dnl notice, this list of conditions and the following disclaimer. +dnl 2. Redistributions in binary form must reproduce the above copyright +dnl notice, this list of conditions and the following disclaimer in the +dnl documentation and/or other materials provided with the distribution. +dnl 3. Neither the name of the project nor the names of its contributors +dnl may be used to endorse or promote products derived from this software +dnl without specific prior written permission. +dnl +dnl THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND +dnl ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +dnl IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +dnl ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE +dnl FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +dnl DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +dnl OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +dnl HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +dnl LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +dnl OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +dnl SUCH DAMAGE. +dnl + +AC_INIT([libusrsctp], [0.9.2.1]) +AM_INIT_AUTOMAKE + +AC_PROG_CC +AC_PROG_LIBTOOL +AC_CANONICAL_HOST +AC_CONFIG_MACRO_DIR([m4]) + +LIBCFLAGS="-DSCTP_PROCESS_LEVEL_LOCKS -DSCTP_SIMPLE_ALLOCATOR -D__Userspace__" +case $host_os in +darwin*) + CFLAGS="$CFLAGS -std=c99 -D__APPLE_USE_RFC_2292" + LIBCFLAGS="$LIBCFLAGS -U__APPLE__ -D__Userspace_os_Darwin" + ;; +dragonfly*) + CFLAGS="$CFLAGS -std=c99 -pthread" + LIBCFLAGS="$LIBCFLAGS -U__DragonFly__ -D__Userspace_os_DragonFly" + ;; +freebsd*) + CFLAGS="$CFLAGS -std=c99 -pthread" + if $CC --version | grep -q clang; then + LDFLAGS="$LDFLAGS -Qunused-arguments" + fi + LIBCFLAGS="$LIBCFLAGS -U__FreeBSD__ -D__Userspace_os_FreeBSD" + ;; +linux*) + CFLAGS="$CFLAGS -std=c99 -pthread -D_GNU_SOURCE" + LIBCFLAGS="$LIBCFLAGS -D__Userspace_os_Linux" + ;; +netbsd*) + CFLAGS="$CFLAGS -std=c99 -pthread" + LIBCFLAGS="$LIBCFLAGS -U__NetBSD__ -D__Userspace_os_NetBSD" + ;; +openbsd*) + CFLAGS="$CFLAGS -std=c99 -pthread" + LIBCFLAGS="$LIBCFLAGS -U__OpenBSD__ -D__Userspace_os_OpenBSD" + ;; +solaris*) + CFLAGS="$CFLAGS -D_XPG4_2" + ;; +esac + +if test "x$GCC" = "xyes" -o "x$CC" = "xclang" ; then + ac_supports_gcc_flags=yes +fi + +if test "x$ac_supports_gcc_flags" = "xyes" ; then + CFLAGS="$CFLAGS -pedantic -Wall" +fi + +AC_MSG_CHECKING(whether we should treat compiler warnings as errors) +AC_ARG_ENABLE(warnings-as-errors, + AC_HELP_STRING( [--enable-warnings-as-errors], + [treat warnings as errors (only for GCC or clang) @<:@default=yes@:>@]), + enable_warnings_as_errors=$enableval,enable_warnings_as_errors=yes) +if test "x$ac_supports_gcc_flags" = "xyes" -a x$enable_warnings_as_errors = xyes; then + AC_MSG_RESULT(yes) + CFLAGS="$CFLAGS -Werror" +else + AC_MSG_RESULT(no) +fi + +LIBCFLAGS="$CFLAGS $LIBCFLAGS" + +AC_ARG_ENABLE(invariants, + AC_HELP_STRING( [--enable-invariants], + [add additional runtime checks @<:@default=no@:>@]), + enable_invariants=$enableval,enable_invariants=no) +if test x$enable_invariants = xyes; then + AC_DEFINE(INVARIANTS, 1, [Add additional runtime checks]) +fi + +AC_ARG_ENABLE(debug, + AC_HELP_STRING( [--enable-debug], + [provide debug information @<:@default=yes@:>@]), + enable_debug=$enableval,enable_debug=yes) +if test x$enable_debug = xyes; then + AC_DEFINE(SCTP_DEBUG, 1, [Provide debug information]) + CFLAGS="$CFLAGS -g -O0" +fi + +AC_ARG_ENABLE(inet, + AC_HELP_STRING( [--enable-inet], + [Support IPv4 @<:@default=yes@:>@]), + enable_inet=$enableval,enable_inet=yes) +if test x$enable_inet = xyes; then + AC_DEFINE(INET, 1, [Support IPv4]) +fi + +AC_ARG_ENABLE(inet6, + AC_HELP_STRING( [--enable-inet6], + [Support IPv6 @<:@default=yes@:>@]), + enable_inet6=$enableval,enable_inet6=yes) +if test x$enable_inet6 = xyes; then + AC_DEFINE(INET6, 1, [Support IPv6]) +fi + +AC_CHECK_TYPE(size_t) +AC_CHECK_TYPE(ssize_t) + +AC_CHECK_FUNCS(socket, , AC_CHECK_LIB(socket, socket)) +AC_CHECK_FUNCS(inet_addr, , AC_CHECK_LIB(nsl, inet_addr)) + +AC_CHECK_HEADERS(sys/queue.h) +AC_CHECK_HEADERS(linux/if_addr.h, [], [], [#include <sys/socket.h>]) +AC_CHECK_HEADERS(linux/rtnetlink.h, [], [], [#include <sys/socket.h>]) +AC_CHECK_HEADERS(netinet/ip_icmp.h, [], [], [#include <netinet/ip.h>]) + +AC_CHECK_MEMBER(struct sockaddr.sa_len, + AC_DEFINE(HAVE_SA_LEN, 1, [Define this if your stack has sa_len in sockaddr struct.]),, + [#ifdef HAVE_SYS_TYPES_H + #include <sys/types.h> + #endif + #include <sys/socket.h>]) + +AC_CHECK_MEMBER(struct sockaddr_in.sin_len, + AC_DEFINE(HAVE_SIN_LEN, 1, [Define this if your IPv4 has sin_len in sockaddr_in struct.]),, + [#ifdef HAVE_SYS_TYPES_H + #include <sys/types.h> + #endif + #include <netinet/in.h>]) + +AC_CHECK_MEMBER(struct sockaddr_in6.sin6_len, + AC_DEFINE(HAVE_SIN6_LEN, 1, [Define this if your IPv6 has sin6_len in sockaddr_in6 struct.]),, + [#ifdef HAVE_SYS_TYPES_H + #include <sys/types.h> + #endif + #include <netinet/in.h>]) + +AC_CHECK_MEMBER(struct sockaddr_conn.sconn_len, + AC_DEFINE(HAVE_SCONN_LEN, 1, [Define this if your userland stack has sconn_len in sockaddr_conn struct.]),, + [#include "usrsctplib/usrsctp.h"]) + +AC_MSG_CHECKING(for socklen_t) +AC_TRY_COMPILE([#ifdef HAVE_SYS_TYPES_H + #include <sys/types.h> + #endif + #include <sys/socket.h>], + [socklen_t x; x = 1; return ((int)x);], + [AC_MSG_RESULT(yes)], + [AC_MSG_RESULT(int) + AC_DEFINE(socklen_t, int, [Define a type for socklen_t.])]) + +AC_C_BIGENDIAN + +AC_SUBST([LIBCFLAGS]) +AC_OUTPUT(Makefile usrsctplib/Makefile programs/Makefile) diff --git a/chromium/third_party/usrsctp/usrsctplib/programs/CMakeLists.txt b/chromium/third_party/usrsctp/usrsctplib/programs/CMakeLists.txt new file mode 100644 index 00000000000..f4f549d1e24 --- /dev/null +++ b/chromium/third_party/usrsctp/usrsctplib/programs/CMakeLists.txt @@ -0,0 +1,205 @@ +# +# Copyright (C) 2015-2015 Oleg Alexeenkov +# Copyright (C) 2015-2015 Felix Weinrank +# +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the project nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +message(">> WARNINING: CMAKE SUPPORT IS EXPERIMENTAL <<") + +cmake_minimum_required(VERSION 2.6) +include_directories(../usrsctplib) + + +################################################# +# INCLUDE MODULES +################################################# + +include(CheckFunctionExists) +include(CheckStructHasMember) +include(CheckIncludeFile) +include(CMakePushCheckState) +include(CheckTypeSize) + + +################################################# +# CHECK FOR TYPES AND FUNCTIONS +################################################# + +# xxx warum machen wir die checks? +check_type_size("size_t" HAVE_SIZE_T) +check_type_size("ssize_t" HAVE_SSIZE_T) + +check_function_exists("socket" HAVE_SOCKET) +check_function_exists("inet_addr" HAVE_INET_ADDR) + + +################################################# +# CHECK INCLUDES +################################################# + +check_include_file(sys/socket.h HAVE_SYS_SOCKET_H) +check_include_file(sys/types.h HAVE_SYS_TYPES_H) +check_include_file(sys/queue.h HAVE_SYS_QUEUE_H) +check_include_file(linux/if_addr.h HAVE_LINUX_IF_ADDR_H) +check_include_file(linux/rtnetlink.h HAVE_LINUX_RTNETLINK_H) +check_include_file(netinet/ip_icmp.h HAVE_NETINET_IP_ICMP_H) +check_include_file(usrsctp.h HAVE_USRSCTP_H) + + +################################################# +# CHECK STRUCT MEMBERS +################################################# + +check_struct_has_member("struct sockaddr" "sa_len" "sys/types.h;sys/socket.h" HAVE_SA_LEN) +if(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) + 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) + add_definitions(-DHAVE_SIN6_LEN) +endif() + + +################################################# +# CHECK OPTIONS +################################################# + +option(SCTP_DEBUG "Provide debug information" 0) +if (SCTP_DEBUG) + add_definitions(-DSCTP_DEBUG) +endif() + +option(INET "Support IPv4 " 1) +if (INET) + add_definitions(-DINET) +endif() + +option(INET6 "Support IPv6 " 1) +if (INET6) + add_definitions(-DINET6) +endif() + +option(LINK_STATIC "Link static" 0) +# xxx enable W32 support for shared lib ... +if (LINK_STATIC OR WIN32) + set(LINK_STATIC "usrsctp-static") +else() + set(LINK_STATIC "usrsctp") +endif() + +option(WERROR "Warning as error" ON) + +################################################# +# OS DEPENDENT +################################################# + +if (${CMAKE_SYSTEM_NAME} MATCHES "Linux") + add_definitions(-D_GNU_SOURCE) +endif() + +if (${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") + add_definitions(-DHAVE_SCONN_LEN) +endif() + +if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + add_definitions(-DHAVE_SCONN_LEN) + add_definitions(-D__APPLE_USE_RFC_2292) +endif() + +if (${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD") + add_definitions(-DHAVE_SCONN_LEN) +endif() + + +################################################# +# MISC +################################################# + +FIND_PACKAGE(Threads) + + +################################################# +# PROGRAMS +################################################# + +SET (check_PROGRAMS + client.c + datachan_serv.c + daytime_server.c + discard_server.c + echo_server.c + ekr_client.c + ekr_loop.c + ekr_peer.c + ekr_server.c + rtcweb.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} + ) + + TARGET_LINK_LIBRARIES (${source_file_we} + ${LINK_STATIC} + ${CMAKE_THREAD_LIBS_INIT} + ) + + ADD_TEST (${source_file_we} ${source_file_we}) + + IF ("x${CMAKE_C_COMPILER_ID}" STREQUAL "xClang" OR "x${CMAKE_C_COMPILER_ID}" STREQUAL "xGNU") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -pedantic -Wall -std=c99") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -pedantic -Wall -std=c99") + if (WERROR) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror") + endif() + ENDIF () + + 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 (WERROR) + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /WX") + ENDIF() + + + ENDIF () +ENDFOREACH () diff --git a/chromium/third_party/usrsctp/usrsctplib/programs/Makefile.am b/chromium/third_party/usrsctp/usrsctplib/programs/Makefile.am new file mode 100644 index 00000000000..c1759f12b90 --- /dev/null +++ b/chromium/third_party/usrsctp/usrsctplib/programs/Makefile.am @@ -0,0 +1,54 @@ +# +# Copyright (C) 2011-2012 Michael Tuexen +# +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the project nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# + +AM_CPPFLAGS = -I$(srcdir)/../usrsctplib +EXTRA_DIST = Makefile.nmake tsctp.c daytime_server.c discard_server.c echo_server.c client.c rtcweb.c ekr_client.c ekr_server.c ekr_loop.c +noinst_PROGRAMS = tsctp daytime_server discard_server echo_server client rtcweb ekr_client ekr_server ekr_peer ekr_loop +tsctp_SOURCES = tsctp.c +tsctp_LDADD = ../usrsctplib/libusrsctp.la +daytime_server_SOURCES = daytime_server.c +daytime_server_LDADD = ../usrsctplib/libusrsctp.la +discard_server_SOURCES = discard_server.c +discard_server_LDADD = ../usrsctplib/libusrsctp.la +echo_server_SOURCES = echo_server.c +echo_server_LDADD = ../usrsctplib/libusrsctp.la +client_SOURCES = client.c +client_LDADD = ../usrsctplib/libusrsctp.la +rtcweb_SOURCES = rtcweb.c +rtcweb_LDADD = ../usrsctplib/libusrsctp.la +ekr_server_SOURCES = ekr_server.c +ekr_server_LDADD = ../usrsctplib/libusrsctp.la +ekr_client_SOURCES = ekr_client.c +ekr_client_LDADD = ../usrsctplib/libusrsctp.la +ekr_peer_SOURCES = ekr_peer.c +ekr_peer_LDADD = ../usrsctplib/libusrsctp.la +ekr_loop_SOURCES = ekr_loop.c +ekr_loop_LDADD = ../usrsctplib/libusrsctp.la + diff --git a/chromium/third_party/usrsctp/usrsctplib/programs/Makefile.nmake b/chromium/third_party/usrsctp/usrsctplib/programs/Makefile.nmake new file mode 100644 index 00000000000..9fe03bc4d9b --- /dev/null +++ b/chromium/third_party/usrsctp/usrsctplib/programs/Makefile.nmake @@ -0,0 +1,112 @@ +# +# Copyright (C) 2011-2012 Michael Tuexen +# +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the project nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# + +CFLAGS=/W3 /WX /I..\usrsctplib + +CVARSDLL=-DINET -DINET6 + +LINKFLAGS=/LIBPATH:..\usrsctplib usrsctp.lib + +.c.obj:: + $(CC) $(CVARSDLL) $(CFLAGS) -Fd.\ -c $< + +all: \ + client \ + daytime_server \ + discard_server \ + echo_server \ + tsctp \ + rtcweb \ + ekr_client \ + ekr_server \ + ekr_peer \ + ekr_loop + +client: + $(CC) $(CFLAGS) $(CVARSDLL) -c client.c + link -out:client.exe client.obj $(LINKFLAGS) + +daytime_server: + $(CC) $(CFLAGS) $(CVARSDLL) -c daytime_server.c + link -out:daytime_server.exe daytime_server.obj $(LINKFLAGS) + +discard_server: + $(CC) $(CFLAGS) $(CVARSDLL) -c discard_server.c + link -out:discard_server.exe discard_server.obj $(LINKFLAGS) + +echo_server: + $(CC) $(CFLAGS) $(CVARSDLL) -c echo_server.c + link -out:echo_server.exe echo_server.obj $(LINKFLAGS) + +tsctp: + $(CC) $(CFLAGS) $(CVARSDLL) -c tsctp.c + link -out:tsctp.exe tsctp.obj $(LINKFLAGS) + +rtcweb: + $(CC) $(CFLAGS) $(CVARSDLL) -c rtcweb.c + link -out:rtcweb.exe rtcweb.obj $(LINKFLAGS) + +ekr_client: + $(CC) $(CFLAGS) $(CVARSDLL) -c ekr_client.c + link -out:ekr_client.exe ekr_client.obj $(LINKFLAGS) + +ekr_server: + $(CC) $(CFLAGS) $(CVARSDLL) -c ekr_server.c + link -out:ekr_server.exe ekr_server.obj $(LINKFLAGS) + +ekr_peer: + $(CC) $(CFLAGS) $(CVARSDLL) -c ekr_peer.c + link -out:ekr_peer.exe ekr_peer.obj $(LINKFLAGS) + +ekr_loop: + $(CC) $(CFLAGS) $(CVARSDLL) -c ekr_loop.c + link -out:ekr_loop.exe ekr_loop.obj $(LINKFLAGS) + +clean: + del /F client.exe + del /F client.obj + del /F daytime_server.exe + del /F daytime_server.obj + del /F discard_server.exe + del /F discard_server.obj + del /F echo_server.exe + del /F echo_server.obj + del /F tsctp.exe + del /F tsctp.obj + del /F rtcweb.exe + del /F rtcweb.obj + del /F ekr_client.exe + del /F ekr_client.obj + del /F ekr_server.exe + del /F ekr_server.obj + del /F ekr_peer.exe + del /F ekr_peer.obj + del /F ekr_loop.exe + del /F ekr_loop.obj diff --git a/chromium/third_party/usrsctp/usrsctplib/programs/client.c b/chromium/third_party/usrsctp/usrsctplib/programs/client.c new file mode 100644 index 00000000000..02d20b97498 --- /dev/null +++ b/chromium/third_party/usrsctp/usrsctplib/programs/client.c @@ -0,0 +1,277 @@ +/* + * Copyright (C) 2011-2013 Michael Tuexen + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Usage: client remote_addr remote_port [local_port] [local_encaps_port] [remote_encaps_port] + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> +#ifndef _WIN32 +#include <unistd.h> +#endif +#include <sys/types.h> +#ifndef _WIN32 +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#else +#include <io.h> +#endif +#include <usrsctp.h> + +int done = 0; + +#ifdef _WIN32 +typedef char* caddr_t; +#endif + +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) +{ + if (data == NULL) { + done = 1; + usrsctp_close(sock); + } else { +#ifdef _WIN32 + _write(_fileno(stdout), data, datalen); +#else + if (write(fileno(stdout), data, datalen) < 0) { + perror("write"); + } +#endif + free(data); + } + return (1); +} + +void +debug_printf(const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + vprintf(format, ap); + va_end(ap); +} + +int +main(int argc, char *argv[]) +{ + struct socket *sock; + struct sockaddr *addr, *addrs; + struct sockaddr_in addr4; + struct sockaddr_in6 addr6; + struct sctp_udpencaps encaps; + struct sctpstat stat; + char buffer[80]; + int i, n; + + if (argc > 4) { + usrsctp_init(atoi(argv[4]), NULL, debug_printf); + } else { + usrsctp_init(9899, NULL, debug_printf); + } +#ifdef SCTP_DEBUG + usrsctp_sysctl_set_sctp_debug_on(SCTP_DEBUG_NONE); +#endif + usrsctp_sysctl_set_sctp_blackhole(2); + if ((sock = usrsctp_socket(AF_INET6, SOCK_STREAM, IPPROTO_SCTP, receive_cb, NULL, 0, NULL)) == NULL) { + perror("usrsctp_socket"); + } + if (argc > 3) { + memset((void *)&addr6, 0, sizeof(struct sockaddr_in6)); +#ifdef HAVE_SIN6_LEN + addr6.sin6_len = sizeof(struct sockaddr_in6); +#endif + addr6.sin6_family = AF_INET6; + addr6.sin6_port = htons(atoi(argv[3])); + addr6.sin6_addr = in6addr_any; + if (usrsctp_bind(sock, (struct sockaddr *)&addr6, sizeof(struct sockaddr_in6)) < 0) { + perror("bind"); + } + } + if (argc > 5) { + memset(&encaps, 0, sizeof(struct sctp_udpencaps)); + encaps.sue_address.ss_family = AF_INET6; + encaps.sue_port = htons(atoi(argv[5])); + if (usrsctp_setsockopt(sock, IPPROTO_SCTP, SCTP_REMOTE_UDP_ENCAPS_PORT, (const void*)&encaps, (socklen_t)sizeof(struct sctp_udpencaps)) < 0) { + perror("setsockopt"); + } + } + memset((void *)&addr4, 0, sizeof(struct sockaddr_in)); + memset((void *)&addr6, 0, sizeof(struct sockaddr_in6)); +#ifdef HAVE_SIN_LEN + addr4.sin_len = sizeof(struct sockaddr_in); +#endif +#ifdef HAVE_SIN6_LEN + addr6.sin6_len = sizeof(struct sockaddr_in6); +#endif + addr4.sin_family = AF_INET; + addr6.sin6_family = AF_INET6; + addr4.sin_port = htons(atoi(argv[2])); + addr6.sin6_port = htons(atoi(argv[2])); + if (inet_pton(AF_INET6, argv[1], &addr6.sin6_addr) == 1) { + if (usrsctp_connect(sock, (struct sockaddr *)&addr6, sizeof(struct sockaddr_in6)) < 0) { + perror("usrsctp_connect"); + } + } else if (inet_pton(AF_INET, argv[1], &addr4.sin_addr) == 1) { + if (usrsctp_connect(sock, (struct sockaddr *)&addr4, sizeof(struct sockaddr_in)) < 0) { + perror("usrsctp_connect"); + } + } else { + printf("Illegal destination address.\n"); + } + if ((n = usrsctp_getladdrs(sock, 0, &addrs)) < 0) { + perror("usrsctp_getladdrs"); + } else { + addr = addrs; + printf("Local addresses: "); + for (i = 0; i < n; i++) { + if (i > 0) { + printf("%s", ", "); + } + switch (addr->sa_family) { + case AF_INET: + { + struct sockaddr_in *sin; + char buf[INET_ADDRSTRLEN]; + const char *name; + + sin = (struct sockaddr_in *)addr; + name = inet_ntop(AF_INET, &sin->sin_addr, buf, INET_ADDRSTRLEN); + printf("%s", name); +#ifndef HAVE_SA_LEN + addr = (struct sockaddr *)((caddr_t)addr + sizeof(struct sockaddr_in)); +#endif + break; + } + case AF_INET6: + { + struct sockaddr_in6 *sin6; + char buf[INET6_ADDRSTRLEN]; + const char *name; + + sin6 = (struct sockaddr_in6 *)addr; + name = inet_ntop(AF_INET6, &sin6->sin6_addr, buf, INET6_ADDRSTRLEN); + printf("%s", name); +#ifndef HAVE_SA_LEN + addr = (struct sockaddr *)((caddr_t)addr + sizeof(struct sockaddr_in6)); +#endif + break; + } + default: + break; + } +#ifdef HAVE_SA_LEN + addr = (struct sockaddr *)((caddr_t)addr + addr->sa_len); +#endif + } + printf(".\n"); + usrsctp_freeladdrs(addrs); + } + if ((n = usrsctp_getpaddrs(sock, 0, &addrs)) < 0) { + perror("usrsctp_getpaddrs"); + } else { + addr = addrs; + printf("Peer addresses: "); + for (i = 0; i < n; i++) { + if (i > 0) { + printf("%s", ", "); + } + switch (addr->sa_family) { + case AF_INET: + { + struct sockaddr_in *sin; + char buf[INET_ADDRSTRLEN]; + const char *name; + + sin = (struct sockaddr_in *)addr; + name = inet_ntop(AF_INET, &sin->sin_addr, buf, INET_ADDRSTRLEN); + printf("%s", name); +#ifndef HAVE_SA_LEN + addr = (struct sockaddr *)((caddr_t)addr + sizeof(struct sockaddr_in)); +#endif + break; + } + case AF_INET6: + { + struct sockaddr_in6 *sin6; + char buf[INET6_ADDRSTRLEN]; + const char *name; + + sin6 = (struct sockaddr_in6 *)addr; + name = inet_ntop(AF_INET6, &sin6->sin6_addr, buf, INET6_ADDRSTRLEN); + printf("%s", name); +#ifndef HAVE_SA_LEN + addr = (struct sockaddr *)((caddr_t)addr + sizeof(struct sockaddr_in6)); +#endif + break; + } + default: + break; + } +#ifdef HAVE_SA_LEN + addr = (struct sockaddr *)((caddr_t)addr + addr->sa_len); +#endif + } + printf(".\n"); + usrsctp_freepaddrs(addrs); + } + while ((fgets(buffer, sizeof(buffer), stdin) != NULL) && !done) { + usrsctp_sendv(sock, buffer, strlen(buffer), NULL, 0, NULL, 0, SCTP_SENDV_NOINFO, 0); + } + if (!done) { + if (usrsctp_shutdown(sock, SHUT_WR) < 0) { + perror("usrsctp_shutdown"); + } + } + while (!done) { +#ifdef _WIN32 + Sleep(1*1000); +#else + sleep(1); +#endif + } + usrsctp_get_stat(&stat); + printf("Number of packets (sent/received): (%u/%u).\n", + stat.sctps_outpackets, stat.sctps_inpackets); + while (usrsctp_finish() != 0) { +#ifdef _WIN32 + Sleep(1000); +#else + sleep(1); +#endif + } + return(0); +} diff --git a/chromium/third_party/usrsctp/usrsctplib/programs/datachan.h b/chromium/third_party/usrsctp/usrsctplib/programs/datachan.h new file mode 100644 index 00000000000..c3bfbf7071b --- /dev/null +++ b/chromium/third_party/usrsctp/usrsctplib/programs/datachan.h @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2012-2015 Michael Tuexen + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef DATACHAN_H + +#define DATA_CHANNEL_PPID_CONTROL 1 +#define DATA_CHANNEL_PPID_DOMSTRING 2 +#define DATA_CHANNEL_PPID_BINARY 3 + +struct rtcweb_datachannel_msg { + uint8_t msg_type; + uint8_t channel_type; + uint16_t flags; + uint16_t reverse_stream; + uint16_t reliability_params; + /* msg_type_data follows */ +} SCTP_PACKED; + +/* msg_type values: */ +#define DATA_CHANNEL_OPEN 0 +#define DATA_CHANNEL_OPEN_RESPONSE 1 + +/* channel_type values: */ +#define DATA_CHANNEL_RELIABLE 0 +#define DATA_CHANNEL_RELIABLE_STREAM 1 +#define DATA_CHANNEL_UNRELIABLE 2 +#define DATA_CHANNEL_PARTIAL_RELIABLE_REXMIT 3 +#define DATA_CHANNEL_PARTIAL_RELIABLE_TIMED 4 + +/* flags values: */ +#define DATA_CHANNEL_FLAG_OUT_OF_ORDER_ALLOWED 0x0001 +/* all other bits reserved and should be set to 0 */ + +/* msg_type_data contains: */ +/* + for DATA_CHANNEL_OPEN: + a DOMString label for the data channel + for DATA_CHANNEL_OPEN_RESPONSE: + a 16-bit value for errors or 0 for no error +*/ + +#define ERR_DATA_CHANNEL_ALREADY_OPEN 0 +#define ERR_DATA_CHANNEL_NONE_AVAILABLE 1 + +#endif diff --git a/chromium/third_party/usrsctp/usrsctplib/programs/datachan_serv.c b/chromium/third_party/usrsctp/usrsctplib/programs/datachan_serv.c new file mode 100644 index 00000000000..3bd2a578197 --- /dev/null +++ b/chromium/third_party/usrsctp/usrsctplib/programs/datachan_serv.c @@ -0,0 +1,531 @@ +/* + * Copyright (C) 2012-2013 Michael Tuexen + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Usage: daytime_server [local_encaps_port] [remote_encaps_port] + */ + +#ifdef _WIN32 +#define _CRT_SECURE_NO_WARNINGS +#endif +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> +#include <sys/types.h> +#ifndef _WIN32 +#include <unistd.h> +#include <time.h> +#include <sys/socket.h> +#include <sys/select.h> +#include <sys/errno.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#endif +#include <usrsctp.h> + +#include "datachan.h" + +#define SIZEOF_ARRAY(x) (sizeof(x)/sizeof((x)[0])) + +#define MAX_INPUT_LINE 1024 +#define MAX_CHANNELS 100 +#define INVALID_STREAM 0xFFFF + +struct { + int8_t pending; + uint8_t channel_type; + uint16_t flags; + uint16_t reverse; + uint16_t reliability_params; + /* FIX! label */ +} channels_out[MAX_CHANNELS]; + +struct { + uint8_t in_use; +} channels_in[MAX_CHANNELS]; + +int num_channels = 0; + +void +send_error_response(struct socket* sock, + struct rtcweb_datachannel_msg *msg, + struct sctp_rcvinfo *rcv, + uint16_t error) +{ + struct sctp_sndinfo sndinfo; + struct rtcweb_datachannel_msg response[2]; // need extra space for error value + + /* ok, send a response */ + response[0] = *msg; + response[0].msg_type = DATA_CHANNEL_OPEN_RESPONSE; + response[0].reverse_stream = rcv->rcv_sid; + *((uint16_t *) &((&msg->reliability_params)[1])) = htons(error); + + sndinfo.snd_sid = rcv->rcv_sid; + sndinfo.snd_flags = 0; + sndinfo.snd_ppid = DATA_CHANNEL_PPID_CONTROL; + sndinfo.snd_context = 0; + sndinfo.snd_assoc_id = 0; + + if (usrsctp_sendv(sock, &response[0], sizeof(response[0])+sizeof(uint16_t), NULL, 0, + (void *)&sndinfo, (socklen_t)sizeof(struct sctp_sndinfo), + SCTP_SENDV_SNDINFO, 0) < 0) { + printf("error %d sending response\n", errno); + /* hard to send an error here... */ + } +} + +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) +{ + struct sctp_sndinfo sndinfo; + + if (data == NULL) { + /* done = 1;*/ /* XXX? */ + usrsctp_close(sock); + } else { + struct rtcweb_datachannel_msg *msg; + uint16_t forward,reverse; + uint16_t error; + int i; + + switch (rcv.rcv_ppid) + { + case DATA_CHANNEL_PPID_CONTROL: + msg = (struct rtcweb_datachannel_msg *)data; + printf("rtcweb_datachannel_msg = \n" + " type\t\t\t%u\n" + " channel_type\t\t%u\n" + " flags\t\t\t0x%04x\n" + " reverse_stream\t%u\n" + " reliability\t\t0x%04x\n" + " label\t\t\t%s\n", + msg->msg_type, msg->channel_type, msg->flags, + msg->reverse_stream, msg->reliability_params, + (char *) &((&msg->reliability_params)[1])); + + switch (msg->msg_type) + { + case DATA_CHANNEL_OPEN: + if (channels_in[rcv.rcv_sid].in_use) + { + printf("error, channel %u in use\n",rcv.rcv_sid); + send_error_response(sock, msg, &rcv, ERR_DATA_CHANNEL_ALREADY_OPEN); + break; + } + reverse = rcv.rcv_sid; + if (channels_out[reverse].reverse == INVALID_STREAM && + !channels_out[reverse].pending) + { + channels_in[reverse].in_use = 1; + channels_out[reverse].reverse = reverse; + forward = reverse; + } + else + { + /* some sort of glare, find a spare channel */ + for (i = 0; i < SIZEOF_ARRAY(channels_out); i++) + { + if (!(channels_out[i].reverse != INVALID_STREAM && + !channels_out[i].pending)) + { + break; + } + } + if (i >= SIZEOF_ARRAY(channels_out)) + { + printf("no reverse channel available!\n"); + channels_in[reverse].in_use = 0; + send_error_response(sock, msg, &rcv ,ERR_DATA_CHANNEL_NONE_AVAILABLE); + break; + } + forward = i; + channels_out[forward].reverse = reverse; + channels_in[reverse].in_use = 1; + } + + /* channels_out[reverse].pending = 0; */ + channels_out[forward].channel_type = msg->channel_type; + channels_out[forward].flags = msg->flags; + channels_out[forward].reliability_params = msg->reliability_params; + + /* Label is in msg_type_data */ + /* FIX! */ + + { + struct rtcweb_datachannel_msg response[2]; // need extra space for error value + /* ok, send a response */ + response[0] = *msg; + response[0].msg_type = DATA_CHANNEL_OPEN_RESPONSE; + response[0].reverse_stream = reverse; + *((uint16_t *) &((&msg->reliability_params)[1])) = /*htons*/(0); /* no error */ + *((char *) &((&msg->reliability_params)[1])) = /*htons*/(0); + + sndinfo.snd_sid = forward; + sndinfo.snd_flags = 0; + sndinfo.snd_ppid = DATA_CHANNEL_PPID_CONTROL; + sndinfo.snd_context = 0; + sndinfo.snd_assoc_id = 0; + + if (usrsctp_sendv(sock, &response[0], sizeof(response[0])+sizeof(uint16_t), NULL, 0, + (void *)&sndinfo, (socklen_t)sizeof(struct sctp_sndinfo), + SCTP_SENDV_SNDINFO, 0) < 0) { + printf("error %d sending response\n",errno); + channels_out[forward].reverse = INVALID_STREAM; + channels_in[reverse].in_use = 0; + /* hard to send an error here... */ + break; + } + } + num_channels++; + printf("successful open of in: %u, out: %u, total channels %d\n", + reverse, forward, num_channels); + /* XXX Notify ondatachannel */ + break; + + case DATA_CHANNEL_OPEN_RESPONSE: + if (!channels_out[msg->reverse_stream].pending) + { + printf("Error: open_response for non-pending channel %u (on %u)\n", + msg->reverse_stream, rcv.rcv_sid); + break; + } + error = ntohs(*((uint16_t *) &((&msg->reliability_params)[1]))); + if (error) + { + printf("Error: open_response for %u returned error %u\n", + msg->reverse_stream, error); + break; + } + channels_out[msg->reverse_stream].pending = 0; + channels_in[rcv.rcv_sid].in_use = 1; + channels_out[msg->reverse_stream].reverse = rcv.rcv_sid; + num_channels++; + printf("successful open of in: %u, out: %u, total channels %d\n", + rcv.rcv_sid, msg->reverse_stream, num_channels); + /* XXX Notify onopened */ + break; + + default: + printf("Error: Unknown message received: %u\n",msg->msg_type); + break; + } + break; + + case DATA_CHANNEL_PPID_DOMSTRING: + printf("Received DOMString, len %d\n", (int)datalen); + printf("%s\n", (char *)data); + /* XXX Notify onmessage */ + break; + + case DATA_CHANNEL_PPID_BINARY: + printf("Received binary, len %d\n", (int)datalen); + { + char *buffer = (char *)data; + printf("0000: %02x %02x %02x %02x %02x %02x %02x %02x \n", + buffer[0],buffer[1],buffer[2],buffer[3], + buffer[4],buffer[5],buffer[6],buffer[7]); + } + /* XXX Notify onmessage */ + break; + + default: + printf("Error: Unknown ppid %u\n", rcv.rcv_ppid); + break; + } /* switch ppid */ + + free(data); + } + return (1); +} + +void +debug_printf(const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + vprintf(format, ap); + va_end(ap); +} + +int +main(int argc, char *argv[]) +{ + struct socket *sock, *conn_sock; + struct sockaddr_in addr; + struct sockaddr_in addr4; + struct sockaddr_in6 addr6; + struct sctp_udpencaps encaps; + socklen_t addr_len; + fd_set fds; + int i; + struct sctp_sndinfo sndinfo; + struct sctp_prinfo prinfo; + struct sctp_sendv_spa spa; + + for (i = 0; i < SIZEOF_ARRAY(channels_out); i++) + { + channels_out[i].reverse = INVALID_STREAM; + channels_out[i].pending = 0; + channels_in[i].in_use = 0; + } + + if (argc > 1) { + usrsctp_init(atoi(argv[1]), NULL, debug_printf); + } else { + usrsctp_init(9899, NULL, debug_printf); + } +#ifdef SCTP_DEBUG + usrsctp_sysctl_set_sctp_debug_on(SCTP_DEBUG_NONE); +#endif + usrsctp_sysctl_set_sctp_blackhole(2); + + if ((sock = usrsctp_socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP, receive_cb, NULL, 0, NULL)) == NULL) { + perror("usrsctp_socket"); + } + if (argc > 2) { + memset(&encaps, 0, sizeof(struct sctp_udpencaps)); + encaps.sue_address.ss_family = AF_INET; + encaps.sue_port = htons(atoi(argv[2])); + if (usrsctp_setsockopt(sock, IPPROTO_SCTP, SCTP_REMOTE_UDP_ENCAPS_PORT, (const void*)&encaps, (socklen_t)sizeof(struct sctp_udpencaps)) < 0) { + perror("setsockopt"); + } + } + + if (argc > 4) + { + /* Acting as the connector */ + printf("Connecting to %s %s\n",argv[3],argv[4]); + memset((void *)&addr4, 0, sizeof(struct sockaddr_in)); + memset((void *)&addr6, 0, sizeof(struct sockaddr_in6)); +#ifdef HAVE_SIN_LEN + addr4.sin_len = sizeof(struct sockaddr_in); +#endif +#ifdef HAVE_SIN6_LEN + addr6.sin6_len = sizeof(struct sockaddr_in6); +#endif + addr4.sin_family = AF_INET; + addr6.sin6_family = AF_INET6; + addr4.sin_port = htons(atoi(argv[4])); + addr6.sin6_port = htons(atoi(argv[4])); + if (inet_pton(AF_INET6, argv[3], &addr6.sin6_addr) == 1) { + if (usrsctp_connect(sock, (struct sockaddr *)&addr6, sizeof(struct sockaddr_in6)) < 0) { + perror("usrsctp_connect"); + } + } else if (inet_pton(AF_INET, argv[3], &addr4.sin_addr) == 1) { + if (usrsctp_connect(sock, (struct sockaddr *)&addr4, sizeof(struct sockaddr_in)) < 0) { + perror("usrsctp_connect"); + } + } else { + printf("Illegal destination address.\n"); + } + + } + else + { + /* Acting as the 'server' */ + memset((void *)&addr, 0, sizeof(struct sockaddr_in)); +#ifdef HAVE_SIN_LEN + addr.sin_len = sizeof(struct sockaddr_in); +#endif + addr.sin_family = AF_INET; + addr.sin_port = htons(13); + addr.sin_addr.s_addr = htonl(INADDR_ANY); + printf("Waiting for connections on port %d\n",ntohs(addr.sin_port)); + if (usrsctp_bind(sock, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0) { + perror("usrsctp_bind"); + } + if (usrsctp_listen(sock, 1) < 0) { + perror("usrsctp_listen"); + } + } + + while (sock) { + if (argc > 4) + { + conn_sock = sock; + sock = NULL; + printf("connect() succeeded! Entering connected mode\n"); + } + else + { + addr_len = 0; + if ((conn_sock = usrsctp_accept(sock, NULL, &addr_len)) == NULL) { + continue; + } + printf("Accepting incoming connection. Entering connected mode\n"); + } + + + /* control loop and sending */ + FD_ZERO(&fds); + for(;;){ + /* + int nr; + + FD_SET(fileno(stdin), &fds); + if ((nr = select(fileno(stdin)+1, &fds, NULL, NULL, NULL)) < 0) + { + if (errno == EINTR) + continue; + else + { + printf("select error\n"); + exit(1); + } + } + if (FD_ISSET(fileno(stdin), &fds) ) + { + */ + { + char inputline[MAX_INPUT_LINE]; + if (fgets(inputline, MAX_INPUT_LINE, stdin) == NULL) { + /* exit on ^d */ + printf("exiting..\n"); + exit(0); + } + else { + struct rtcweb_datachannel_msg msg[4]; /* cheat to get space for label */ + int stream, reliable; + int len; + uint32_t timeout; + uint32_t flags; + + if (sscanf(inputline,"open %d %d:",&stream,&reliable) == 2) + { + if (stream < 0 || stream >= SIZEOF_ARRAY(channels_out)) + { + printf("stream number %d out of range!\n",stream); + continue; + } + if (reliable < 0 || reliable > DATA_CHANNEL_PARTIAL_RELIABLE_TIMED) + { + printf("reliability type %d invalid!\n",reliable); + continue; + } + if (channels_out[stream].reverse != INVALID_STREAM || + channels_out[stream].pending != 0) + { + printf("channel %d already in use!\n",stream); + continue; + } + + channels_out[stream].pending = 1; + channels_out[stream].channel_type = reliable; + channels_out[stream].flags = 0; /* XXX */ + channels_out[stream].reverse = INVALID_STREAM; + channels_out[stream].reliability_params = 0; + + msg[0].msg_type = DATA_CHANNEL_OPEN; + msg[0].channel_type = reliable; + msg[0].flags = 0; /* XXX */ + msg[0].reverse_stream = INVALID_STREAM; + msg[0].reliability_params = 0; + sprintf((char *) &((&msg[0].reliability_params)[1]),"chan %d",stream); + len = sizeof(msg) + strlen((char *) &((&msg[0].reliability_params)[1])); + + timeout = channels_out[stream].reliability_params; + switch(channels_out[stream].channel_type) + { + case DATA_CHANNEL_RELIABLE: + flags = 0; + prinfo.pr_policy = 0; + break; + case DATA_CHANNEL_UNRELIABLE: + case DATA_CHANNEL_PARTIAL_RELIABLE_REXMIT: + flags = SCTP_UNORDERED; + prinfo.pr_policy = SCTP_PR_SCTP_RTX; + break; + case DATA_CHANNEL_PARTIAL_RELIABLE_TIMED: + flags = SCTP_UNORDERED; + prinfo.pr_policy = SCTP_PR_SCTP_TTL; + break; + } + sndinfo.snd_sid = stream; + sndinfo.snd_flags = flags; + sndinfo.snd_ppid = DATA_CHANNEL_PPID_CONTROL; + sndinfo.snd_context = 0; + sndinfo.snd_assoc_id = 0; + + prinfo.pr_value = timeout; + + spa.sendv_sndinfo = sndinfo; + spa.sendv_prinfo = prinfo; + spa.sendv_flags = SCTP_SEND_SNDINFO_VALID | SCTP_SEND_PRINFO_VALID; + if (usrsctp_sendv(conn_sock, &msg[0], len, NULL, 0, + (void *)&spa, (socklen_t)sizeof(struct sctp_sendv_spa), SCTP_SENDV_SPA, + flags) < 0) { + printf("error %d sending open\n",errno); + channels_out[stream].pending = 0; + } + } + else if (sscanf(inputline,"send %d:",&stream) == 1) + { + char *str = strchr(inputline,':'); + if (!str) /* should be impossible */ + exit(1); + str++; + sndinfo.snd_sid = stream; + sndinfo.snd_flags = 0; + sndinfo.snd_ppid = DATA_CHANNEL_PPID_DOMSTRING; + sndinfo.snd_context = 0; + sndinfo.snd_assoc_id = 0; + + if (usrsctp_sendv(conn_sock, str, strlen(str), NULL, 0, + (void *)&sndinfo, (socklen_t)sizeof(struct sctp_sndinfo), + SCTP_SENDV_SNDINFO, 0) < 0) { + printf("error %d sending string\n",errno); + } + } + else if (sscanf(inputline,"close %d:",&stream) == 1) + { + } + else + { + printf("unknown command '%s'\n",inputline); + } + } + } /* if FDSET */ + } + usrsctp_close(conn_sock); + } + usrsctp_close(sock); + while (usrsctp_finish() != 0) { +#ifdef _WIN32 + Sleep(1000); +#else + sleep(1); +#endif + } + return (0); +} diff --git a/chromium/third_party/usrsctp/usrsctplib/programs/daytime_server.c b/chromium/third_party/usrsctp/usrsctplib/programs/daytime_server.c new file mode 100644 index 00000000000..18a0fcb46d2 --- /dev/null +++ b/chromium/third_party/usrsctp/usrsctplib/programs/daytime_server.c @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2012-2013 Michael Tuexen + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Usage: daytime_server [local_encaps_port] [remote_encaps_port] + */ + +#ifdef _WIN32 +#define _CRT_SECURE_NO_WARNINGS +#endif +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> +#include <sys/types.h> +#include <time.h> +#ifndef _WIN32 +#include <unistd.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#endif +#include <usrsctp.h> + +void +debug_printf(const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + vprintf(format, ap); + va_end(ap); +} + +#define DAYTIME_PPID 40 +int +main(int argc, char *argv[]) +{ + struct socket *sock, *conn_sock; + struct sockaddr_in addr; + struct sctp_udpencaps encaps; + socklen_t addr_len; + char buffer[80]; + time_t now; + struct sctp_sndinfo sndinfo; + + if (argc > 1) { + usrsctp_init(atoi(argv[1]), NULL, debug_printf); + } else { + usrsctp_init(9899, NULL, debug_printf); + } +#ifdef SCTP_DEBUG + usrsctp_sysctl_set_sctp_debug_on(SCTP_DEBUG_NONE); +#endif + usrsctp_sysctl_set_sctp_blackhole(2); + + if ((sock = usrsctp_socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP, NULL, NULL, 0, NULL)) == NULL) { + perror("usrsctp_socket"); + } + if (argc > 2) { + memset(&encaps, 0, sizeof(struct sctp_udpencaps)); + encaps.sue_address.ss_family = AF_INET; + encaps.sue_port = htons(atoi(argv[2])); + if (usrsctp_setsockopt(sock, IPPROTO_SCTP, SCTP_REMOTE_UDP_ENCAPS_PORT, (const void*)&encaps, (socklen_t)sizeof(struct sctp_udpencaps)) < 0) { + perror("setsockopt"); + } + } + memset((void *)&addr, 0, sizeof(struct sockaddr_in)); +#ifdef HAVE_SIN_LEN + addr.sin_len = sizeof(struct sockaddr_in); +#endif + addr.sin_family = AF_INET; + addr.sin_port = htons(13); + addr.sin_addr.s_addr = htonl(INADDR_ANY); + if (usrsctp_bind(sock, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0) { + perror("usrsctp_bind"); + } + if (usrsctp_listen(sock, 1) < 0) { + perror("usrsctp_listen"); + } + while (1) { + addr_len = 0; + if ((conn_sock = usrsctp_accept(sock, NULL, &addr_len)) == NULL) { + continue; + } + time(&now); +#ifdef _WIN32 + _snprintf(buffer, sizeof(buffer), "%s", ctime(&now)); +#else + snprintf(buffer, sizeof(buffer), "%s", ctime(&now)); +#endif + sndinfo.snd_sid = 0; + sndinfo.snd_flags = 0; + 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); + usrsctp_close(conn_sock); + } + usrsctp_close(sock); + while (usrsctp_finish() != 0) { +#ifdef _WIN32 + Sleep(1000); +#else + sleep(1); +#endif + } + return (0); +} diff --git a/chromium/third_party/usrsctp/usrsctplib/programs/discard_server.c b/chromium/third_party/usrsctp/usrsctplib/programs/discard_server.c new file mode 100644 index 00000000000..2a50d6fd75a --- /dev/null +++ b/chromium/third_party/usrsctp/usrsctplib/programs/discard_server.c @@ -0,0 +1,248 @@ +/* + * Copyright (C) 2011-2013 Michael Tuexen + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Usage: discard_server [local_encaps_port] [remote_encaps_port] + */ + +#ifdef _WIN32 +#define _CRT_SECURE_NO_WARNINGS +#endif +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> +#include <sys/types.h> +#ifndef _WIN32 +#include <unistd.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#endif +#include <usrsctp.h> + +#define BUFFER_SIZE 10240 + +const int use_cb = 0; + +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) +{ + char namebuf[INET6_ADDRSTRLEN]; + const char *name; + uint16_t port; + + if (data) { + if (flags & MSG_NOTIFICATION) { + printf("Notification of length %d received.\n", (int)datalen); + } else { + switch (addr.sa.sa_family) { +#ifdef INET + case AF_INET: + name = inet_ntop(AF_INET, &addr.sin.sin_addr, namebuf, INET_ADDRSTRLEN); + port = ntohs(addr.sin.sin_port); + break; +#endif +#ifdef INET6 + case AF_INET6: + name = inet_ntop(AF_INET6, &addr.sin6.sin6_addr, namebuf, INET6_ADDRSTRLEN), + port = ntohs(addr.sin6.sin6_port); + break; +#endif + case AF_CONN: +#ifdef _WIN32 + _snprintf(namebuf, INET6_ADDRSTRLEN, "%p", addr.sconn.sconn_addr); +#else + snprintf(namebuf, INET6_ADDRSTRLEN, "%p", addr.sconn.sconn_addr); +#endif + name = namebuf; + port = ntohs(addr.sconn.sconn_port); + break; + default: + name = NULL; + port = 0; + break; + } + printf("Msg of length %d received from %s:%u on stream %d with SSN %u and TSN %u, PPID %d, context %u.\n", + (int)datalen, + name, + port, + rcv.rcv_sid, + rcv.rcv_ssn, + rcv.rcv_tsn, + ntohl(rcv.rcv_ppid), + rcv.rcv_context); + } + free(data); + } + return (1); +} + +void +debug_printf(const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + vprintf(format, ap); + va_end(ap); +} + +int +main(int argc, char *argv[]) +{ + struct socket *sock; + struct sockaddr_in6 addr; + struct sctp_udpencaps encaps; + struct sctp_event event; + uint16_t event_types[] = {SCTP_ASSOC_CHANGE, + SCTP_PEER_ADDR_CHANGE, + SCTP_REMOTE_ERROR, + SCTP_SHUTDOWN_EVENT, + SCTP_ADAPTATION_INDICATION, + SCTP_PARTIAL_DELIVERY_EVENT}; + unsigned int i; + struct sctp_assoc_value av; + const int on = 1; + ssize_t n; + int flags; + socklen_t from_len; + char buffer[BUFFER_SIZE]; + char name[INET6_ADDRSTRLEN]; + socklen_t infolen; + struct sctp_rcvinfo rcv_info; + unsigned int infotype; + + if (argc > 1) { + usrsctp_init(atoi(argv[1]), NULL, debug_printf); + } else { + usrsctp_init(9899, NULL, debug_printf); + } +#ifdef SCTP_DEBUG + usrsctp_sysctl_set_sctp_debug_on(SCTP_DEBUG_NONE); +#endif + usrsctp_sysctl_set_sctp_blackhole(2); + + if ((sock = usrsctp_socket(AF_INET6, SOCK_SEQPACKET, IPPROTO_SCTP, use_cb?receive_cb:NULL, NULL, 0, NULL)) == NULL) { + perror("usrsctp_socket"); + } + if (usrsctp_setsockopt(sock, IPPROTO_SCTP, SCTP_I_WANT_MAPPED_V4_ADDR, (const void*)&on, (socklen_t)sizeof(int)) < 0) { + perror("usrsctp_setsockopt SCTP_I_WANT_MAPPED_V4_ADDR"); + } + memset(&av, 0, sizeof(struct sctp_assoc_value)); + av.assoc_id = SCTP_ALL_ASSOC; + av.assoc_value = 47; + + if (usrsctp_setsockopt(sock, IPPROTO_SCTP, SCTP_CONTEXT, (const void*)&av, (socklen_t)sizeof(struct sctp_assoc_value)) < 0) { + perror("usrsctp_setsockopt SCTP_CONTEXT"); + } + if (usrsctp_setsockopt(sock, IPPROTO_SCTP, SCTP_RECVRCVINFO, &on, sizeof(int)) < 0) { + perror("usrsctp_setsockopt SCTP_RECVRCVINFO"); + } + if (argc > 2) { + memset(&encaps, 0, sizeof(struct sctp_udpencaps)); + encaps.sue_address.ss_family = AF_INET6; + encaps.sue_port = htons(atoi(argv[2])); + if (usrsctp_setsockopt(sock, IPPROTO_SCTP, SCTP_REMOTE_UDP_ENCAPS_PORT, (const void*)&encaps, (socklen_t)sizeof(struct sctp_udpencaps)) < 0) { + perror("usrsctp_setsockopt SCTP_REMOTE_UDP_ENCAPS_PORT"); + } + } + memset(&event, 0, sizeof(event)); + event.se_assoc_id = SCTP_FUTURE_ASSOC; + event.se_on = 1; + for (i = 0; i < (unsigned int)(sizeof(event_types)/sizeof(uint16_t)); i++) { + event.se_type = event_types[i]; + if (usrsctp_setsockopt(sock, IPPROTO_SCTP, SCTP_EVENT, &event, sizeof(struct sctp_event)) < 0) { + perror("usrsctp_setsockopt SCTP_EVENT"); + } + } + memset((void *)&addr, 0, sizeof(struct sockaddr_in6)); +#ifdef HAVE_SIN6_LEN + addr.sin6_len = sizeof(struct sockaddr_in6); +#endif + addr.sin6_family = AF_INET6; + addr.sin6_port = htons(9); + addr.sin6_addr = in6addr_any; + if (usrsctp_bind(sock, (struct sockaddr *)&addr, sizeof(struct sockaddr_in6)) < 0) { + perror("usrsctp_bind"); + } + if (usrsctp_listen(sock, 1) < 0) { + perror("usrsctp_listen"); + } + while (1) { + if (use_cb) { +#ifdef _WIN32 + Sleep(1*1000); +#else + sleep(1); +#endif + } else { + from_len = (socklen_t)sizeof(struct sockaddr_in6); + flags = 0; + infolen = (socklen_t)sizeof(struct sctp_rcvinfo); + n = usrsctp_recvv(sock, (void*)buffer, BUFFER_SIZE, (struct sockaddr *) &addr, &from_len, (void *)&rcv_info, + &infolen, &infotype, &flags); + if (n > 0) { + if (flags & MSG_NOTIFICATION) { + printf("Notification of length %llu received.\n", (unsigned long long)n); + } else { + if (infotype == SCTP_RECVV_RCVINFO) { + printf("Msg of length %llu received from %s:%u on stream %d with SSN %u and TSN %u, PPID %d, context %u, complete %d.\n", + (unsigned long long)n, + inet_ntop(AF_INET6, &addr.sin6_addr, name, INET6_ADDRSTRLEN), ntohs(addr.sin6_port), + rcv_info.rcv_sid, + rcv_info.rcv_ssn, + rcv_info.rcv_tsn, + ntohl(rcv_info.rcv_ppid), + rcv_info.rcv_context, + (flags & MSG_EOR) ? 1 : 0); + } else { + printf("Msg of length %llu received from %s:%u, complete %d.\n", + (unsigned long long)n, + inet_ntop(AF_INET6, &addr.sin6_addr, name, INET6_ADDRSTRLEN), ntohs(addr.sin6_port), + (flags & MSG_EOR) ? 1 : 0); + } + } + } else { + break; + } + } + } + usrsctp_close(sock); + while (usrsctp_finish() != 0) { +#ifdef _WIN32 + Sleep(1000); +#else + sleep(1); +#endif + } + return (0); +} diff --git a/chromium/third_party/usrsctp/usrsctplib/programs/echo_server.c b/chromium/third_party/usrsctp/usrsctplib/programs/echo_server.c new file mode 100644 index 00000000000..ae507b7b18b --- /dev/null +++ b/chromium/third_party/usrsctp/usrsctplib/programs/echo_server.c @@ -0,0 +1,278 @@ +/* + * Copyright (C) 2011-2013 Michael Tuexen + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Usage: discard_server [local_encaps_port] [remote_encaps_port] + */ + +#ifdef _WIN32 +#define _CRT_SECURE_NO_WARNINGS +#endif +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> +#include <sys/types.h> +#ifndef _WIN32 +#include <unistd.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#endif +#include <usrsctp.h> + +#define BUFFER_SIZE 10240 + +const int use_cb = 0; + +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) +{ + char namebuf[INET6_ADDRSTRLEN]; + const char *name; + uint16_t port; + + if (data) { + if (flags & MSG_NOTIFICATION) { + printf("Notification of length %d received.\n", (int)datalen); + } else { + switch (addr.sa.sa_family) { +#ifdef INET + case AF_INET: + name = inet_ntop(AF_INET, &addr.sin.sin_addr, namebuf, INET_ADDRSTRLEN); + port = ntohs(addr.sin.sin_port); + break; +#endif +#ifdef INET6 + case AF_INET6: + name = inet_ntop(AF_INET6, &addr.sin6.sin6_addr, namebuf, INET6_ADDRSTRLEN), + port = ntohs(addr.sin6.sin6_port); + break; +#endif + case AF_CONN: +#ifdef _WIN32 + _snprintf(namebuf, INET6_ADDRSTRLEN, "%p", addr.sconn.sconn_addr); +#else + snprintf(namebuf, INET6_ADDRSTRLEN, "%p", addr.sconn.sconn_addr); +#endif + name = namebuf; + port = ntohs(addr.sconn.sconn_port); + break; + default: + name = NULL; + port = 0; + break; + } + printf("Msg of length %d received from %s:%u on stream %d with SSN %u and TSN %u, PPID %d, context %u.\n", + (int)datalen, + name, + port, + rcv.rcv_sid, + rcv.rcv_ssn, + rcv.rcv_tsn, + ntohl(rcv.rcv_ppid), + rcv.rcv_context); + if (flags & MSG_EOR) { + struct sctp_sndinfo snd_info; + + snd_info.snd_sid = rcv.rcv_sid; + snd_info.snd_flags = 0; + if (rcv.rcv_flags & SCTP_UNORDERED) { + snd_info.snd_flags |= SCTP_UNORDERED; + } + snd_info.snd_ppid = rcv.rcv_ppid; + snd_info.snd_context = 0; + snd_info.snd_assoc_id = rcv.rcv_assoc_id; + if (usrsctp_sendv(sock, data, datalen, NULL, 0, &snd_info, sizeof(struct sctp_sndinfo), SCTP_SENDV_SNDINFO, 0) < 0) { + perror("sctp_sendv"); + } + } + } + free(data); + } + return (1); +} + +void +debug_printf(const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + vprintf(format, ap); + va_end(ap); +} + +int +main(int argc, char *argv[]) +{ + struct socket *sock; + struct sockaddr_in6 addr; + struct sctp_udpencaps encaps; + struct sctp_event event; + uint16_t event_types[] = {SCTP_ASSOC_CHANGE, + SCTP_PEER_ADDR_CHANGE, + SCTP_REMOTE_ERROR, + SCTP_SHUTDOWN_EVENT, + SCTP_ADAPTATION_INDICATION, + SCTP_PARTIAL_DELIVERY_EVENT}; + unsigned int i; + struct sctp_assoc_value av; + const int on = 1; + ssize_t n; + int flags; + socklen_t from_len; + char buffer[BUFFER_SIZE]; + char name[INET6_ADDRSTRLEN]; + socklen_t infolen; + struct sctp_rcvinfo rcv_info; + unsigned int infotype; + + if (argc > 1) { + usrsctp_init(atoi(argv[1]), NULL, debug_printf); + } else { + usrsctp_init(9899, NULL, debug_printf); + } +#ifdef SCTP_DEBUG + usrsctp_sysctl_set_sctp_debug_on(SCTP_DEBUG_NONE); +#endif + usrsctp_sysctl_set_sctp_blackhole(2); + + if ((sock = usrsctp_socket(AF_INET6, SOCK_SEQPACKET, IPPROTO_SCTP, use_cb?receive_cb:NULL, NULL, 0, NULL)) == NULL) { + perror("usrsctp_socket"); + } + if (usrsctp_setsockopt(sock, IPPROTO_SCTP, SCTP_I_WANT_MAPPED_V4_ADDR, (const void*)&on, (socklen_t)sizeof(int)) < 0) { + perror("usrsctp_setsockopt SCTP_I_WANT_MAPPED_V4_ADDR"); + } + memset(&av, 0, sizeof(struct sctp_assoc_value)); + av.assoc_id = SCTP_ALL_ASSOC; + av.assoc_value = 47; + + if (usrsctp_setsockopt(sock, IPPROTO_SCTP, SCTP_CONTEXT, (const void*)&av, (socklen_t)sizeof(struct sctp_assoc_value)) < 0) { + perror("usrsctp_setsockopt SCTP_CONTEXT"); + } + if (usrsctp_setsockopt(sock, IPPROTO_SCTP, SCTP_RECVRCVINFO, &on, sizeof(int)) < 0) { + perror("usrsctp_setsockopt SCTP_RECVRCVINFO"); + } + if (argc > 2) { + memset(&encaps, 0, sizeof(struct sctp_udpencaps)); + encaps.sue_address.ss_family = AF_INET6; + encaps.sue_port = htons(atoi(argv[2])); + if (usrsctp_setsockopt(sock, IPPROTO_SCTP, SCTP_REMOTE_UDP_ENCAPS_PORT, (const void*)&encaps, (socklen_t)sizeof(struct sctp_udpencaps)) < 0) { + perror("usrsctp_setsockopt SCTP_REMOTE_UDP_ENCAPS_PORT"); + } + } + memset(&event, 0, sizeof(event)); + event.se_assoc_id = SCTP_FUTURE_ASSOC; + event.se_on = 1; + for (i = 0; i < (unsigned int)(sizeof(event_types)/sizeof(uint16_t)); i++) { + event.se_type = event_types[i]; + if (usrsctp_setsockopt(sock, IPPROTO_SCTP, SCTP_EVENT, &event, sizeof(struct sctp_event)) < 0) { + perror("usrsctp_setsockopt SCTP_EVENT"); + } + } + memset((void *)&addr, 0, sizeof(struct sockaddr_in6)); +#ifdef HAVE_SIN6_LEN + addr.sin6_len = sizeof(struct sockaddr_in6); +#endif + addr.sin6_family = AF_INET6; + addr.sin6_port = htons(7); + addr.sin6_addr = in6addr_any; + if (usrsctp_bind(sock, (struct sockaddr *)&addr, sizeof(struct sockaddr_in6)) < 0) { + perror("usrsctp_bind"); + } + if (usrsctp_listen(sock, 1) < 0) { + perror("usrsctp_listen"); + } + while (1) { + if (use_cb) { +#ifdef _WIN32 + Sleep(1*1000); +#else + sleep(1); +#endif + } else { + from_len = (socklen_t)sizeof(struct sockaddr_in6); + flags = 0; + infolen = (socklen_t)sizeof(struct sctp_rcvinfo); + n = usrsctp_recvv(sock, (void*)buffer, BUFFER_SIZE, (struct sockaddr *) &addr, &from_len, (void *)&rcv_info, + &infolen, &infotype, &flags); + if (n > 0) { + if (flags & MSG_NOTIFICATION) { + printf("Notification of length %llu received.\n", (unsigned long long)n); + } else { + if (infotype == SCTP_RECVV_RCVINFO) { + printf("Msg of length %llu received from %s:%u on stream %d with SSN %u and TSN %u, PPID %d, context %u, complete %d.\n", + (unsigned long long)n, + inet_ntop(AF_INET6, &addr.sin6_addr, name, INET6_ADDRSTRLEN), ntohs(addr.sin6_port), + rcv_info.rcv_sid, + rcv_info.rcv_ssn, + rcv_info.rcv_tsn, + ntohl(rcv_info.rcv_ppid), + rcv_info.rcv_context, + (flags & MSG_EOR) ? 1 : 0); + if (flags & MSG_EOR) { + struct sctp_sndinfo snd_info; + + snd_info.snd_sid = rcv_info.rcv_sid; + snd_info.snd_flags = 0; + if (rcv_info.rcv_flags & SCTP_UNORDERED) { + snd_info.snd_flags |= SCTP_UNORDERED; + } + snd_info.snd_ppid = rcv_info.rcv_ppid; + snd_info.snd_context = 0; + snd_info.snd_assoc_id = rcv_info.rcv_assoc_id; + if (usrsctp_sendv(sock, buffer, (size_t)n, NULL, 0, &snd_info, (socklen_t)sizeof(struct sctp_sndinfo), SCTP_SENDV_SNDINFO, 0) < 0) { + perror("sctp_sendv"); + } + } + } else { + printf("Msg of length %llu received from %s:%u, complete %d.\n", + (unsigned long long)n, + inet_ntop(AF_INET6, &addr.sin6_addr, name, INET6_ADDRSTRLEN), ntohs(addr.sin6_port), + (flags & MSG_EOR) ? 1 : 0); + } + } + } else { + break; + } + } + } + usrsctp_close(sock); + while (usrsctp_finish() != 0) { +#ifdef _WIN32 + Sleep(1000); +#else + sleep(1); +#endif + } + return (0); +} diff --git a/chromium/third_party/usrsctp/usrsctplib/programs/ekr_client.c b/chromium/third_party/usrsctp/usrsctplib/programs/ekr_client.c new file mode 100644 index 00000000000..8e745c608c3 --- /dev/null +++ b/chromium/third_party/usrsctp/usrsctplib/programs/ekr_client.c @@ -0,0 +1,313 @@ +/* + * Copyright (C) 2011-2013 Michael Tuexen + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef _WIN32 +#define _CRT_SECURE_NO_WARNINGS +#endif +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> +#include <sys/types.h> +#ifndef _WIN32 +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <errno.h> +#include <pthread.h> +#include <unistd.h> +#else +#include <winsock2.h> +#include <ws2tcpip.h> +#endif +#include <usrsctp.h> + +#define MAX_PACKET_SIZE (1<<16) +#define BUFFER_SIZE 80 +#define DISCARD_PPID 39 + +#ifdef _WIN32 +static DWORD WINAPI +#else +static void * +#endif +handle_packets(void *arg) +{ +#ifdef _WIN32 + SOCKET *fdp; +#else + int *fdp; +#endif + char *dump_buf; + ssize_t length; + char buf[MAX_PACKET_SIZE]; + +#ifdef _WIN32 + fdp = (SOCKET *)arg; +#else + fdp = (int *)arg; +#endif + for (;;) { + length = recv(*fdp, buf, MAX_PACKET_SIZE, 0); + if (length > 0) { + if ((dump_buf = usrsctp_dumppacket(buf, (size_t)length, SCTP_DUMP_INBOUND)) != NULL) { + fprintf(stderr, "%s", dump_buf); + usrsctp_freedumpbuffer(dump_buf); + } + usrsctp_conninput(fdp, buf, (size_t)length, 0); + } + } +#ifdef _WIN32 + return 0; +#else + return (NULL); +#endif +} + +static int +conn_output(void *addr, void *buf, size_t length, uint8_t tos, uint8_t set_df) +{ + char *dump_buf; +#ifdef _WIN32 + SOCKET *fdp; +#else + int *fdp; +#endif + +#ifdef _WIN32 + fdp = (SOCKET *)addr; +#else + fdp = (int *)addr; +#endif + if ((dump_buf = usrsctp_dumppacket(buf, length, SCTP_DUMP_OUTBOUND)) != NULL) { + fprintf(stderr, "%s", dump_buf); + usrsctp_freedumpbuffer(dump_buf); + } +#ifdef _WIN32 + if (send(*fdp, buf, length, 0) == SOCKET_ERROR) { + return (WSAGetLastError()); +#else + if (send(*fdp, buf, length, 0) < 0) { + return (errno); +#endif + } else { + return (0); + } +} + +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) +{ + + if (data) { + if (flags & MSG_NOTIFICATION) { + printf("Notification of length %d received.\n", (int)datalen); + } else { + printf("Msg of length %d received via %p:%u on stream %d with SSN %u and TSN %u, PPID %d, context %u.\n", + (int)datalen, + addr.sconn.sconn_addr, + ntohs(addr.sconn.sconn_port), + rcv.rcv_sid, + rcv.rcv_ssn, + rcv.rcv_tsn, + ntohl(rcv.rcv_ppid), + rcv.rcv_context); + } + free(data); + } else { + usrsctp_deregister_address(ulp_info); + usrsctp_close(sock); + } + return (1); +} + +void +debug_printf(const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + vprintf(format, ap); + va_end(ap); +} + +int +main(int argc, char *argv[]) +{ + struct sockaddr_in sin; + struct sockaddr_conn sconn; +#ifdef _WIN32 + SOCKET fd; +#else + int fd; +#endif + struct socket *s; +#ifdef _WIN32 + HANDLE tid; +#else + pthread_t tid; +#endif + struct sctp_sndinfo sndinfo; + char buffer[BUFFER_SIZE]; +#ifdef _WIN32 + WSADATA wsaData; +#endif + + if (argc < 4) { + printf("error: this program requires 4 arguments!\n"); + exit(EXIT_FAILURE); + } + +#ifdef _WIN32 + if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) { + printf("WSAStartup failed\n"); + exit (EXIT_FAILURE); + } +#endif + usrsctp_init(0, conn_output, debug_printf); + /* set up a connected UDP socket */ +#ifdef _WIN32 + if ((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) { + printf("socket() failed with error: %ld\n", WSAGetLastError()); + } +#else + if ((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { + perror("socket"); + } +#endif + memset(&sin, 0, sizeof(struct sockaddr_in)); + sin.sin_family = AF_INET; +#ifdef HAVE_SIN_LEN + sin.sin_len = sizeof(struct sockaddr_in); +#endif + 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); + } +#ifdef _WIN32 + if (bind(fd, (struct sockaddr *)&sin, sizeof(struct sockaddr_in)) == SOCKET_ERROR) { + printf("bind() failed with error: %ld\n", WSAGetLastError()); + } +#else + if (bind(fd, (struct sockaddr *)&sin, sizeof(struct sockaddr_in)) < 0) { + perror("bind"); + } +#endif + memset(&sin, 0, sizeof(struct sockaddr_in)); + sin.sin_family = AF_INET; +#ifdef HAVE_SIN_LEN + sin.sin_len = sizeof(struct sockaddr_in); +#endif + 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); + } +#ifdef _WIN32 + if (connect(fd, (struct sockaddr *)&sin, sizeof(struct sockaddr_in)) == SOCKET_ERROR) { + printf("connect() failed with error: %ld\n", WSAGetLastError()); + } +#else + if (connect(fd, (struct sockaddr *)&sin, sizeof(struct sockaddr_in)) < 0) { + perror("connect"); + } +#endif +#ifdef SCTP_DEBUG + usrsctp_sysctl_set_sctp_debug_on(SCTP_DEBUG_NONE); +#endif + usrsctp_sysctl_set_sctp_ecn_enable(0); + usrsctp_register_address((void *)&fd); +#ifdef _WIN32 + tid = CreateThread(NULL, 0, &handle_packets, (void *)&fd, 0, NULL); +#else + pthread_create(&tid, NULL, &handle_packets, (void *)&fd); +#endif + if ((s = usrsctp_socket(AF_CONN, SOCK_STREAM, IPPROTO_SCTP, receive_cb, NULL, 0, &fd)) == NULL) { + perror("usrsctp_socket"); + } + + memset(&sconn, 0, sizeof(struct sockaddr_conn)); + sconn.sconn_family = AF_CONN; +#ifdef HAVE_SCONN_LEN + sconn.sconn_len = sizeof(struct sockaddr_conn); +#endif + sconn.sconn_port = htons(0); + sconn.sconn_addr = NULL; + if (usrsctp_bind(s, (struct sockaddr *)&sconn, sizeof(struct sockaddr_conn)) < 0) { + perror("usrsctp_bind"); + } + + memset(&sconn, 0, sizeof(struct sockaddr_conn)); + sconn.sconn_family = AF_CONN; +#ifdef HAVE_SCONN_LEN + sconn.sconn_len = sizeof(struct sockaddr_conn); +#endif + sconn.sconn_port = htons(5001); + sconn.sconn_addr = &fd; + if (usrsctp_connect(s, (struct sockaddr *)&sconn, sizeof(struct sockaddr_conn)) < 0) { + perror("usrsctp_connect"); + } + memset(buffer, 'A', BUFFER_SIZE); + sndinfo.snd_sid = 1; + sndinfo.snd_flags = 0; + sndinfo.snd_ppid = htonl(DISCARD_PPID); + sndinfo.snd_context = 0; + sndinfo.snd_assoc_id = 0; + if (usrsctp_sendv(s, buffer, BUFFER_SIZE, NULL, 0, (void *)&sndinfo, + (socklen_t)sizeof(struct sctp_sndinfo), SCTP_SENDV_SNDINFO, 0) < 0) { + perror("usrsctp_sendv"); + } + + usrsctp_shutdown(s, SHUT_WR); + while (usrsctp_finish() != 0) { +#ifdef _WIN32 + Sleep(1000); +#else + sleep(1); +#endif + } +#ifdef _WIN32 + TerminateThread(tid, 0); + WaitForSingleObject(tid, INFINITE); + if (closesocket(fd) == SOCKET_ERROR) { + printf("closesocket() failed with error: %ld\n", WSAGetLastError()); + } + WSACleanup(); +#else + pthread_cancel(tid); + pthread_join(tid, NULL); + if (close(fd) < 0) { + perror("close"); + } +#endif + return (0); +} diff --git a/chromium/third_party/usrsctp/usrsctplib/programs/ekr_loop.c b/chromium/third_party/usrsctp/usrsctplib/programs/ekr_loop.c new file mode 100644 index 00000000000..b7c4dcb3f10 --- /dev/null +++ b/chromium/third_party/usrsctp/usrsctplib/programs/ekr_loop.c @@ -0,0 +1,534 @@ +/* + * Copyright (C) 2011-2013 Michael Tuexen + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef _WIN32 +#define _CRT_SECURE_NO_WARNINGS +#endif +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> +#include <sys/types.h> +#ifndef _WIN32 +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <errno.h> +#include <pthread.h> +#include <unistd.h> +#else +#include <winsock2.h> +#include <ws2tcpip.h> +#endif +#include <usrsctp.h> + +#define MAX_PACKET_SIZE (1<<16) +#define LINE_LENGTH (1<<20) +#define DISCARD_PPID 39 + +#ifdef _WIN32 +static DWORD WINAPI +#else +static void * +#endif +handle_packets(void *arg) +{ +#ifdef _WIN32 + SOCKET *fdp; +#else + int *fdp; +#endif + char *dump_buf; + ssize_t length; + char buf[MAX_PACKET_SIZE]; + +#ifdef _WIN32 + fdp = (SOCKET *)arg; +#else + fdp = (int *)arg; +#endif + for (;;) { + length = recv(*fdp, buf, MAX_PACKET_SIZE, 0); + if (length > 0) { + if ((dump_buf = usrsctp_dumppacket(buf, (size_t)length, SCTP_DUMP_INBOUND)) != NULL) { + //fprintf(stderr, "%s", dump_buf); + usrsctp_freedumpbuffer(dump_buf); + } + usrsctp_conninput(fdp, buf, (size_t)length, 0); + } + } +#ifdef _WIN32 + return 0; +#else + return (NULL); +#endif +} + +static int +conn_output(void *addr, void *buf, size_t length, uint8_t tos, uint8_t set_df) +{ + char *dump_buf; +#ifdef _WIN32 + SOCKET *fdp; +#else + int *fdp; +#endif + +#ifdef _WIN32 + fdp = (SOCKET *)addr; +#else + fdp = (int *)addr; +#endif + if ((dump_buf = usrsctp_dumppacket(buf, length, SCTP_DUMP_OUTBOUND)) != NULL) { + //fprintf(stderr, "%s", dump_buf); + usrsctp_freedumpbuffer(dump_buf); + } +#ifdef _WIN32 + if (send(*fdp, buf, length, 0) == SOCKET_ERROR) { + return (WSAGetLastError()); +#else + if (send(*fdp, buf, length, 0) < 0) { + return (errno); +#endif + } else { + return (0); + } +} + +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) +{ + printf("Message %p received on sock = %p.\n", data, (void *)sock); + if (data) { + if ((flags & MSG_NOTIFICATION) == 0) { + printf("Messsage of length %d received via %p:%u on stream %d with SSN %u and TSN %u, PPID %d, context %u, flags %x.\n", + (int)datalen, + addr.sconn.sconn_addr, + ntohs(addr.sconn.sconn_port), + rcv.rcv_sid, + rcv.rcv_ssn, + rcv.rcv_tsn, + ntohl(rcv.rcv_ppid), + rcv.rcv_context, + flags); + } + free(data); + } else { + usrsctp_deregister_address(ulp_info); + usrsctp_close(sock); + } + return (1); +} + +#if 0 +static void +print_addresses(struct socket *sock) +{ + int i, n; + struct sockaddr *addrs, *addr; + + n = usrsctp_getladdrs(sock, 0, &addrs); + addr = addrs; + for (i = 0; i < n; i++) { + switch (addr->sa_family) { + case AF_INET: + { + struct sockaddr_in *sin; + char buf[INET_ADDRSTRLEN]; + const char *name; + + sin = (struct sockaddr_in *)addr; + name = inet_ntop(AF_INET, &sin->sin_addr, buf, INET_ADDRSTRLEN); + printf("%s:%d", name, ntohs(sin->sin_port)); + break; + } + case AF_INET6: + { + struct sockaddr_in6 *sin6; + char buf[INET6_ADDRSTRLEN]; + const char *name; + + sin6 = (struct sockaddr_in6 *)addr; + name = inet_ntop(AF_INET6, &sin6->sin6_addr, buf, INET6_ADDRSTRLEN); + printf("%s:%d", name, ntohs(sin6->sin6_port)); + break; + } + case AF_CONN: + { + struct sockaddr_conn *sconn; + + sconn = (struct sockaddr_conn *)addr; + printf("%p:%d", sconn->sconn_addr, ntohs(sconn->sconn_port)); + break; + } + default: + printf("Unknown family: %d", addr->sa_family); + break; + } + addr = (struct sockaddr *)((caddr_t)addr + addr->sa_len); + if (i != n - 1) { + printf(","); + } + } + if (n > 0) { + usrsctp_freeladdrs(addrs); + } + printf("<->"); + n = usrsctp_getpaddrs(sock, 0, &addrs); + addr = addrs; + for (i = 0; i < n; i++) { + switch (addr->sa_family) { + case AF_INET: + { + struct sockaddr_in *sin; + char buf[INET_ADDRSTRLEN]; + const char *name; + + sin = (struct sockaddr_in *)addr; + name = inet_ntop(AF_INET, &sin->sin_addr, buf, INET_ADDRSTRLEN); + printf("%s:%d", name, ntohs(sin->sin_port)); + break; + } + case AF_INET6: + { + struct sockaddr_in6 *sin6; + char buf[INET6_ADDRSTRLEN]; + const char *name; + + sin6 = (struct sockaddr_in6 *)addr; + name = inet_ntop(AF_INET6, &sin6->sin6_addr, buf, INET6_ADDRSTRLEN); + printf("%s:%d", name, ntohs(sin6->sin6_port)); + break; + } + case AF_CONN: + { + struct sockaddr_conn *sconn; + + sconn = (struct sockaddr_conn *)addr; + printf("%p:%d", sconn->sconn_addr, ntohs(sconn->sconn_port)); + break; + } + default: + printf("Unknown family: %d", addr->sa_family); + break; + } + addr = (struct sockaddr *)((caddr_t)addr + addr->sa_len); + if (i != n - 1) { + printf(","); + } + } + if (n > 0) { + usrsctp_freepaddrs(addrs); + } + printf("\n"); +} +#endif + +void +debug_printf(const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + vprintf(format, ap); + va_end(ap); +} + +int +main(void) +{ + struct sockaddr_in sin_s, sin_c; + struct sockaddr_conn sconn; +#ifdef _WIN32 + SOCKET fd_c, fd_s; +#else + int fd_c, fd_s; +#endif + struct socket *s_c, *s_s, *s_l; +#ifdef _WIN32 + HANDLE tid_c, tid_s; +#else + pthread_t tid_c, tid_s; +#endif + int cur_buf_size, snd_buf_size, rcv_buf_size; + socklen_t opt_len; + struct sctp_sndinfo sndinfo; + char *line; +#ifdef _WIN32 + WSADATA wsaData; +#endif + +#ifdef _WIN32 + if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) { + printf("WSAStartup failed\n"); + exit (EXIT_FAILURE); + } +#endif + usrsctp_init(0, conn_output, debug_printf); + /* set up a connected UDP socket */ +#ifdef _WIN32 + if ((fd_c = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) { + printf("socket() failed with error: %ld\n", WSAGetLastError()); + exit(EXIT_FAILURE); + } + if ((fd_s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) { + printf("socket() failed with error: %ld\n", WSAGetLastError()); + exit(EXIT_FAILURE); + } +#else + if ((fd_c = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { + perror("socket"); + exit(EXIT_FAILURE); + } + if ((fd_s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { + perror("socket"); + exit(EXIT_FAILURE); + } +#endif + memset(&sin_c, 0, sizeof(struct sockaddr_in)); + sin_c.sin_family = AF_INET; +#ifdef HAVE_SIN_LEN + sin_c.sin_len = sizeof(struct sockaddr_in); +#endif + sin_c.sin_port = htons(9900); + sin_c.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + memset(&sin_s, 0, sizeof(struct sockaddr_in)); + sin_s.sin_family = AF_INET; +#ifdef HAVE_SIN_LEN + sin_s.sin_len = sizeof(struct sockaddr_in); +#endif + sin_s.sin_port = htons(9899); + sin_s.sin_addr.s_addr = htonl(INADDR_LOOPBACK); +#ifdef _WIN32 + if (bind(fd_c, (struct sockaddr *)&sin_c, sizeof(struct sockaddr_in)) == SOCKET_ERROR) { + printf("bind() failed with error: %ld\n", WSAGetLastError()); + exit(EXIT_FAILURE); + } + if (bind(fd_s, (struct sockaddr *)&sin_s, sizeof(struct sockaddr_in)) == SOCKET_ERROR) { + printf("bind() failed with error: %ld\n", WSAGetLastError()); + exit(EXIT_FAILURE); + } +#else + if (bind(fd_c, (struct sockaddr *)&sin_c, sizeof(struct sockaddr_in)) < 0) { + perror("bind"); + exit(EXIT_FAILURE); + } + if (bind(fd_s, (struct sockaddr *)&sin_s, sizeof(struct sockaddr_in)) < 0) { + perror("bind"); + exit(EXIT_FAILURE); + } +#endif +#ifdef _WIN32 + if (connect(fd_c, (struct sockaddr *)&sin_s, sizeof(struct sockaddr_in)) == SOCKET_ERROR) { + printf("connect() failed with error: %ld\n", WSAGetLastError()); + exit(EXIT_FAILURE); + } + if (connect(fd_s, (struct sockaddr *)&sin_c, sizeof(struct sockaddr_in)) == SOCKET_ERROR) { + printf("connect() failed with error: %ld\n", WSAGetLastError()); + exit(EXIT_FAILURE); + } +#else + if (connect(fd_c, (struct sockaddr *)&sin_s, sizeof(struct sockaddr_in)) < 0) { + perror("connect"); + exit(EXIT_FAILURE); + } + if (connect(fd_s, (struct sockaddr *)&sin_c, sizeof(struct sockaddr_in)) < 0) { + perror("connect"); + exit(EXIT_FAILURE); + } +#endif +#ifdef _WIN32 + tid_c = CreateThread(NULL, 0, &handle_packets, (void *)&fd_c, 0, NULL); + tid_s = CreateThread(NULL, 0, &handle_packets, (void *)&fd_s, 0, NULL); +#else + if (pthread_create(&tid_c, NULL, &handle_packets, (void *)&fd_c)) { + perror("pthread_create tid_c"); + exit(EXIT_FAILURE); + } + + if (pthread_create(&tid_s, NULL, &handle_packets, (void *)&fd_s)) { + perror("pthread_create tid_s"); + exit(EXIT_FAILURE); + }; +#endif +#ifdef SCTP_DEBUG + usrsctp_sysctl_set_sctp_debug_on(SCTP_DEBUG_NONE); +#endif + usrsctp_sysctl_set_sctp_ecn_enable(0); + usrsctp_register_address((void *)&fd_c); + usrsctp_register_address((void *)&fd_s); + if ((s_c = usrsctp_socket(AF_CONN, SOCK_STREAM, IPPROTO_SCTP, receive_cb, NULL, 0, &fd_c)) == NULL) { + perror("usrsctp_socket"); + exit(EXIT_FAILURE); + } + opt_len = (socklen_t)sizeof(int); + cur_buf_size = 0; + if (usrsctp_getsockopt(s_c, SOL_SOCKET, SO_SNDBUF, &cur_buf_size, &opt_len) < 0) { + perror("usrsctp_getsockopt"); + exit(EXIT_FAILURE); + } + printf("Change send socket buffer size from %d ", cur_buf_size); + snd_buf_size = 1<<20; /* 1 MB */ + if (usrsctp_setsockopt(s_c, SOL_SOCKET, SO_SNDBUF, &snd_buf_size, sizeof(int)) < 0) { + perror("usrsctp_setsockopt"); + exit(EXIT_FAILURE); + } + opt_len = (socklen_t)sizeof(int); + cur_buf_size = 0; + if (usrsctp_getsockopt(s_c, SOL_SOCKET, SO_SNDBUF, &cur_buf_size, &opt_len) < 0) { + perror("usrsctp_getsockopt"); + exit(EXIT_FAILURE); + } + printf("to %d.\n", cur_buf_size); + if ((s_l = usrsctp_socket(AF_CONN, SOCK_STREAM, IPPROTO_SCTP, receive_cb, NULL, 0, &fd_s)) == NULL) { + perror("usrsctp_socket"); + exit(EXIT_FAILURE); + } + opt_len = (socklen_t)sizeof(int); + cur_buf_size = 0; + if (usrsctp_getsockopt(s_l, SOL_SOCKET, SO_RCVBUF, &cur_buf_size, &opt_len) < 0) { + perror("usrsctp_getsockopt"); + exit(EXIT_FAILURE); + } + printf("Change receive socket buffer size from %d ", cur_buf_size); + rcv_buf_size = 1<<16; /* 64 KB */ + if (usrsctp_setsockopt(s_l, SOL_SOCKET, SO_RCVBUF, &rcv_buf_size, sizeof(int)) < 0) { + perror("usrsctp_setsockopt"); + exit(EXIT_FAILURE); + } + opt_len = (socklen_t)sizeof(int); + cur_buf_size = 0; + if (usrsctp_getsockopt(s_l, SOL_SOCKET, SO_RCVBUF, &cur_buf_size, &opt_len) < 0) { + perror("usrsctp_getsockopt"); + exit(EXIT_FAILURE); + } + printf("to %d.\n", cur_buf_size); + /* Bind the client side. */ + memset(&sconn, 0, sizeof(struct sockaddr_conn)); + sconn.sconn_family = AF_CONN; +#ifdef HAVE_SCONN_LEN + sconn.sconn_len = sizeof(struct sockaddr_conn); +#endif + sconn.sconn_port = htons(5001); + sconn.sconn_addr = &fd_c; + if (usrsctp_bind(s_c, (struct sockaddr *)&sconn, sizeof(struct sockaddr_conn)) < 0) { + perror("usrsctp_bind"); + exit(EXIT_FAILURE); + } + /* Bind the server side. */ + memset(&sconn, 0, sizeof(struct sockaddr_conn)); + sconn.sconn_family = AF_CONN; +#ifdef HAVE_SCONN_LEN + sconn.sconn_len = sizeof(struct sockaddr_conn); +#endif + sconn.sconn_port = htons(5001); + sconn.sconn_addr = &fd_s; + if (usrsctp_bind(s_l, (struct sockaddr *)&sconn, sizeof(struct sockaddr_conn)) < 0) { + perror("usrsctp_bind"); + exit(EXIT_FAILURE); + } + /* Make server side passive... */ + if (usrsctp_listen(s_l, 1) < 0) { + perror("usrsctp_listen"); + exit(EXIT_FAILURE); + } + /* Initiate the handshake */ + memset(&sconn, 0, sizeof(struct sockaddr_conn)); + sconn.sconn_family = AF_CONN; +#ifdef HAVE_SCONN_LEN + sconn.sconn_len = sizeof(struct sockaddr_conn); +#endif + sconn.sconn_port = htons(5001); + sconn.sconn_addr = &fd_c; + if (usrsctp_connect(s_c, (struct sockaddr *)&sconn, sizeof(struct sockaddr_conn)) < 0) { + perror("usrsctp_connect"); + exit(EXIT_FAILURE); + } + if ((s_s = usrsctp_accept(s_l, NULL, NULL)) == NULL) { + perror("usrsctp_accept"); + exit(EXIT_FAILURE); + } + usrsctp_close(s_l); + if ((line = malloc(LINE_LENGTH)) == NULL) { + exit(EXIT_FAILURE); + } + memset(line, 'A', LINE_LENGTH); + sndinfo.snd_sid = 1; + sndinfo.snd_flags = 0; + sndinfo.snd_ppid = htonl(DISCARD_PPID); + sndinfo.snd_context = 0; + sndinfo.snd_assoc_id = 0; + /* Send a 1 MB 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); + } + free(line); + usrsctp_shutdown(s_c, SHUT_WR); + + while (usrsctp_finish() != 0) { +#ifdef _WIN32 + Sleep(1000); +#else + sleep(1); +#endif + } +#ifdef _WIN32 + TerminateThread(tid_c, 0); + WaitForSingleObject(tid_c, INFINITE); + TerminateThread(tid_s, 0); + WaitForSingleObject(tid_s, INFINITE); + if (closesocket(fd_c) == SOCKET_ERROR) { + printf("closesocket() failed with error: %ld\n", WSAGetLastError()); + exit(EXIT_FAILURE); + } + if (closesocket(fd_s) == SOCKET_ERROR) { + printf("closesocket() failed with error: %ld\n", WSAGetLastError()); + exit(EXIT_FAILURE); + } + WSACleanup(); +#else + pthread_cancel(tid_c); + pthread_join(tid_c, NULL); + pthread_cancel(tid_s); + pthread_join(tid_s, NULL); + if (close(fd_c) < 0) { + perror("close"); + exit(EXIT_FAILURE); + } + if (close(fd_s) < 0) { + perror("close"); + exit(EXIT_FAILURE); + } +#endif + return (0); +} diff --git a/chromium/third_party/usrsctp/usrsctplib/programs/ekr_peer.c b/chromium/third_party/usrsctp/usrsctplib/programs/ekr_peer.c new file mode 100644 index 00000000000..4c583e40d86 --- /dev/null +++ b/chromium/third_party/usrsctp/usrsctplib/programs/ekr_peer.c @@ -0,0 +1,535 @@ +/* + * Copyright (C) 2011-2013 Michael Tuexen + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef _WIN32 +#define _CRT_SECURE_NO_WARNINGS +#endif +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> +#include <sys/types.h> +#ifndef _WIN32 +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <errno.h> +#include <pthread.h> +#include <unistd.h> +#else +#include <winsock2.h> +#include <ws2tcpip.h> +#endif +#include <usrsctp.h> + +#define MAX_PACKET_SIZE (1<<16) +#define LINE_LENGTH 80 +#define DISCARD_PPID 39 + +#ifdef _WIN32 +static DWORD WINAPI +#else +static void * +#endif +handle_packets(void *arg) +{ +#ifdef _WIN32 + SOCKET *fdp; +#else + int *fdp; +#endif + ssize_t length; + char buf[MAX_PACKET_SIZE]; + +#ifdef _WIN32 + fdp = (SOCKET *)arg; +#else + fdp = (int *)arg; +#endif + for (;;) { + length = recv(*fdp, buf, MAX_PACKET_SIZE, 0); + if (length > 0) { + usrsctp_conninput(fdp, buf, (size_t)length, 0); + } + } +#ifdef _WIN32 + return 0; +#else + return (NULL); +#endif +} + +static int +conn_output(void *addr, void *buffer, size_t length, uint8_t tos, uint8_t set_df) +{ +#ifdef _WIN32 + SOCKET *fdp; +#else + int *fdp; +#endif + +#ifdef _WIN32 + fdp = (SOCKET *)addr; +#else + fdp = (int *)addr; +#endif +#ifdef _WIN32 + if (send(*fdp, buffer, length, 0) == SOCKET_ERROR) { + return (WSAGetLastError()); +#else + if (send(*fdp, buffer, length, 0) < 0) { + return (errno); +#endif + } else { + return (0); + } +} + +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 = %d, SID = %d, 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) +{ + if (data) { + if (flags & MSG_NOTIFICATION) { + handle_notification((union sctp_notification *)data, datalen); + } else { + printf("Msg of length %d received via %p:%u on stream %d with SSN %u and TSN %u, PPID %d, context %u.\n", + (int)datalen, + addr.sconn.sconn_addr, + ntohs(addr.sconn.sconn_port), + rcv.rcv_sid, + rcv.rcv_ssn, + rcv.rcv_tsn, + ntohl(rcv.rcv_ppid), + rcv.rcv_context); + } + free(data); + } else { + usrsctp_deregister_address(ulp_info); + usrsctp_close(sock); + } + return (1); +} + +void +debug_printf(const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + vprintf(format, ap); + va_end(ap); +} + +int +main(int argc, char *argv[]) +{ + struct sockaddr_in sin; + struct sockaddr_conn sconn; + struct sctp_event event; + uint16_t event_types[] = {SCTP_ASSOC_CHANGE, + SCTP_PEER_ADDR_CHANGE, + SCTP_SEND_FAILED_EVENT}; + unsigned int i; +#ifdef _WIN32 + SOCKET fd; +#else + int fd; +#endif + struct socket *s; +#ifdef _WIN32 + HANDLE tid; +#else + pthread_t tid; +#endif + struct sctp_sndinfo sndinfo; + char line[LINE_LENGTH]; +#ifdef _WIN32 + WSADATA wsaData; +#endif + + if (argc < 4) { + printf("error: this program requires 4 arguments!\n"); + exit(EXIT_FAILURE); + } + +#ifdef _WIN32 + if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) { + printf("WSAStartup failed\n"); + exit (EXIT_FAILURE); + } +#endif + usrsctp_init(0, conn_output, debug_printf); + /* set up a connected UDP socket */ +#ifdef _WIN32 + if ((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) { + printf("socket() failed with error: %ld\n", WSAGetLastError()); + } +#else + if ((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { + perror("socket"); + } +#endif + memset(&sin, 0, sizeof(struct sockaddr_in)); + sin.sin_family = AF_INET; +#ifdef HAVE_SIN_LEN + sin.sin_len = sizeof(struct sockaddr_in); +#endif + 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); + } +#ifdef _WIN32 + if (bind(fd, (struct sockaddr *)&sin, sizeof(struct sockaddr_in)) == SOCKET_ERROR) { + printf("bind() failed with error: %ld\n", WSAGetLastError()); + } +#else + if (bind(fd, (struct sockaddr *)&sin, sizeof(struct sockaddr_in)) < 0) { + perror("bind"); + } +#endif + memset(&sin, 0, sizeof(struct sockaddr_in)); + sin.sin_family = AF_INET; +#ifdef HAVE_SIN_LEN + sin.sin_len = sizeof(struct sockaddr_in); +#endif + 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); + } +#ifdef _WIN32 + if (connect(fd, (struct sockaddr *)&sin, sizeof(struct sockaddr_in)) == SOCKET_ERROR) { + printf("connect() failed with error: %ld\n", WSAGetLastError()); + } +#else + if (connect(fd, (struct sockaddr *)&sin, sizeof(struct sockaddr_in)) < 0) { + perror("connect"); + } +#endif +#ifdef _WIN32 + tid = CreateThread(NULL, 0, &handle_packets, (void *)&fd, 0, NULL); +#else + pthread_create(&tid, NULL, &handle_packets, (void *)&fd); +#endif +#ifdef SCTP_DEBUG + usrsctp_sysctl_set_sctp_debug_on(SCTP_DEBUG_NONE); +#endif + usrsctp_register_address((void *)&fd); + usrsctp_sysctl_set_sctp_ecn_enable(0); + if ((s = usrsctp_socket(AF_CONN, SOCK_STREAM, IPPROTO_SCTP, receive_cb, NULL, 0, &fd)) == NULL) { + perror("usrsctp_socket"); + } + /* Enable the events of interest. */ + if (usrsctp_set_non_blocking(s, 1) < 0) { + perror("usrsctp_set_non_blocking"); + } + 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(s, IPPROTO_SCTP, SCTP_EVENT, &event, sizeof(event)) < 0) { + perror("setsockopt SCTP_EVENT"); + } + } + memset(&sconn, 0, sizeof(struct sockaddr_conn)); + sconn.sconn_family = AF_CONN; +#ifdef HAVE_SCONN_LEN + sconn.sconn_len = sizeof(struct sockaddr_conn); +#endif + sconn.sconn_port = htons(atoi(argv[5])); + sconn.sconn_addr = &fd; + if (usrsctp_bind(s, (struct sockaddr *)&sconn, sizeof(struct sockaddr_conn)) < 0) { + perror("usrsctp_bind"); + } + memset(&sconn, 0, sizeof(struct sockaddr_conn)); + sconn.sconn_family = AF_CONN; +#ifdef HAVE_SCONN_LEN + sconn.sconn_len = sizeof(struct sockaddr_conn); +#endif + sconn.sconn_port = htons(atoi(argv[6])); + sconn.sconn_addr = &fd; + if (usrsctp_connect(s, (struct sockaddr *)&sconn, sizeof(struct sockaddr_conn)) < 0) { + perror("usrsctp_connect"); + } + for (;;) { +#ifdef _WIN32 + if (gets_s(line, LINE_LENGTH) == NULL) { +#else + if (fgets(line, LINE_LENGTH, stdin) == NULL) { +#endif + if (usrsctp_shutdown(s, SHUT_WR) < 0) { + perror("usrsctp_shutdown"); + } + while (usrsctp_finish() != 0) { +#ifdef _WIN32 + Sleep(1000); +#else + sleep(1); +#endif + } + break; + } + sndinfo.snd_sid = 1; + sndinfo.snd_flags = 0; + sndinfo.snd_ppid = htonl(DISCARD_PPID); + sndinfo.snd_context = 0; + sndinfo.snd_assoc_id = 0; + if (usrsctp_sendv(s, line, strlen(line), NULL, 0, (void *)&sndinfo, + (socklen_t)sizeof(struct sctp_sndinfo), SCTP_SENDV_SNDINFO, 0) < 0) { + perror("usrsctp_sendv"); + } + } + while (usrsctp_finish() != 0) { +#ifdef _WIN32 + Sleep(1000); +#else + sleep(1); +#endif + } +#ifdef _WIN32 + TerminateThread(tid, 0); + WaitForSingleObject(tid, INFINITE); + if (closesocket(fd) == SOCKET_ERROR) { + printf("closesocket() failed with error: %ld\n", WSAGetLastError()); + } + WSACleanup(); +#else + pthread_cancel(tid); + pthread_join(tid, NULL); + if (close(fd) < 0) { + perror("close"); + } +#endif + return (0); +} diff --git a/chromium/third_party/usrsctp/usrsctplib/programs/ekr_server.c b/chromium/third_party/usrsctp/usrsctplib/programs/ekr_server.c new file mode 100644 index 00000000000..61c44a0ca53 --- /dev/null +++ b/chromium/third_party/usrsctp/usrsctplib/programs/ekr_server.c @@ -0,0 +1,295 @@ +/* + * Copyright (C) 2011-2013 Michael Tuexen + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef _WIN32 +#define _CRT_SECURE_NO_WARNINGS +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <stdarg.h> +#ifndef _WIN32 +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <errno.h> +#include <pthread.h> +#include <unistd.h> +#else +#include <winsock2.h> +#include <ws2tcpip.h> +#endif +#include <usrsctp.h> + +#define MAX_PACKET_SIZE (1<<16) + +#ifdef _WIN32 +static DWORD WINAPI +#else +static void * +#endif +handle_packets(void *arg) +{ +#ifdef _WIN32 + SOCKET *fdp; +#else + int *fdp; +#endif + char buf[MAX_PACKET_SIZE]; + char *dump_buf; + ssize_t length; + +#ifdef _WIN32 + fdp = (SOCKET *)arg; +#else + fdp = (int *)arg; +#endif + for (;;) { + length = recv(*fdp, buf, MAX_PACKET_SIZE, 0); + if (length > 0) { + if ((dump_buf = usrsctp_dumppacket(buf, (size_t)length, SCTP_DUMP_INBOUND)) != NULL) { + fprintf(stderr, "%s", dump_buf); + usrsctp_freedumpbuffer(dump_buf); + } + usrsctp_conninput(fdp, buf, (size_t)length, 0); + } + } +#ifdef _WIN32 + return 0; +#else + return (NULL); +#endif +} + +static int +conn_output(void *addr, void *buf, size_t length, uint8_t tos, uint8_t set_df) +{ + char *dump_buf; +#ifdef _WIN32 + SOCKET *fdp; +#else + int *fdp; +#endif + +#ifdef _WIN32 + fdp = (SOCKET *)addr; +#else + fdp = (int *)addr; +#endif + if ((dump_buf = usrsctp_dumppacket(buf, length, SCTP_DUMP_OUTBOUND)) != NULL) { + fprintf(stderr, "%s", dump_buf); + usrsctp_freedumpbuffer(dump_buf); + } +#ifdef _WIN32 + if (send(*fdp, buf, length, 0) == SOCKET_ERROR) { + return (WSAGetLastError()); +#else + if (send(*fdp, buf, length, 0) < 0) { + return (errno); +#endif + } else { + return (0); + } +} + +static int +receive_cb(struct socket *s, union sctp_sockstore addr, void *data, + size_t datalen, struct sctp_rcvinfo rcv, int flags, void *ulp_info) +{ + + if (data) { + if (flags & MSG_NOTIFICATION) { + printf("Notification of length %d received.\n", (int)datalen); + } else { + printf("Msg of length %d received via %p:%u on stream %d with SSN %u and TSN %u, PPID %d, context %u.\n", + (int)datalen, + addr.sconn.sconn_addr, + ntohs(addr.sconn.sconn_port), + rcv.rcv_sid, + rcv.rcv_ssn, + rcv.rcv_tsn, + ntohl(rcv.rcv_ppid), + rcv.rcv_context); + } + free(data); + } else { + usrsctp_close(s); + } + return (1); +} + +void +debug_printf(const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + vprintf(format, ap); + va_end(ap); +} + +int +main(int argc, char *argv[]) +{ + struct sockaddr_in sin; + struct sockaddr_conn sconn; +#ifdef _WIN32 + SOCKET fd; +#else + int fd; +#endif + struct socket *s; +#ifdef _WIN32 + HANDLE tid; +#else + pthread_t tid; +#endif +#ifdef _WIN32 + WSADATA wsaData; +#endif + + if (argc < 4) { + printf("error: this program requires 4 arguments!\n"); + exit(EXIT_FAILURE); + } + +#ifdef _WIN32 + if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) { + printf("WSAStartup failed\n"); + exit (EXIT_FAILURE); + } +#endif + usrsctp_init(0, conn_output, debug_printf); + /* set up a connected UDP socket */ +#ifdef _WIN32 + if ((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) { + printf("socket() failed with error: %ld\n", WSAGetLastError()); + } +#else + if ((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { + perror("socket"); + } +#endif + memset(&sin, 0, sizeof(struct sockaddr_in)); + sin.sin_family = AF_INET; +#ifdef HAVE_SIN_LEN + sin.sin_len = sizeof(struct sockaddr_in); +#endif + 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); + } +#ifdef _WIN32 + if (bind(fd, (struct sockaddr *)&sin, sizeof(struct sockaddr_in)) == SOCKET_ERROR) { + printf("bind() failed with error: %ld\n", WSAGetLastError()); + } +#else + if (bind(fd, (struct sockaddr *)&sin, sizeof(struct sockaddr_in)) < 0) { + perror("bind"); + } +#endif + memset(&sin, 0, sizeof(struct sockaddr_in)); + sin.sin_family = AF_INET; +#ifdef HAVE_SIN_LEN + sin.sin_len = sizeof(struct sockaddr_in); +#endif + 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); + } +#ifdef _WIN32 + if (connect(fd, (struct sockaddr *)&sin, sizeof(struct sockaddr_in)) == SOCKET_ERROR) { + printf("connect() failed with error: %ld\n", WSAGetLastError()); + } +#else + if (connect(fd, (struct sockaddr *)&sin, sizeof(struct sockaddr_in)) < 0) { + perror("connect"); + } +#endif +#ifdef SCTP_DEBUG + usrsctp_sysctl_set_sctp_debug_on(SCTP_DEBUG_NONE); +#endif + usrsctp_sysctl_set_sctp_ecn_enable(0); + usrsctp_register_address((void *)&fd); +#ifdef _WIN32 + tid = CreateThread(NULL, 0, &handle_packets, (void *)&fd, 0, NULL); +#else + pthread_create(&tid, NULL, &handle_packets, (void *)&fd); +#endif + if ((s = usrsctp_socket(AF_CONN, SOCK_STREAM, IPPROTO_SCTP, receive_cb, NULL, 0, NULL)) == NULL) { + perror("usrsctp_socket"); + } + memset(&sconn, 0, sizeof(struct sockaddr_conn)); + sconn.sconn_family = AF_CONN; +#ifdef HAVE_SCONN_LEN + sconn.sconn_len = sizeof(struct sockaddr_conn); +#endif + sconn.sconn_port = htons(5001); + sconn.sconn_addr = (void *)&fd; + if (usrsctp_bind(s, (struct sockaddr *)&sconn, sizeof(struct sockaddr_conn)) < 0) { + perror("usrsctp_bind"); + } + if (usrsctp_listen(s, 1) < 0) { + perror("usrsctp_listen"); + } + while (1) { + if (usrsctp_accept(s, NULL, NULL) == NULL) { + perror("usrsctp_accept"); + } + } + usrsctp_close(s); + usrsctp_deregister_address((void *)&fd); + while (usrsctp_finish() != 0) { +#ifdef _WIN32 + Sleep(1000); +#else + sleep(1); +#endif + } +#ifdef _WIN32 + TerminateThread(tid, 0); + WaitForSingleObject(tid, INFINITE); + if (closesocket(fd) == SOCKET_ERROR) { + printf("closesocket() failed with error: %ld\n", WSAGetLastError()); + } + WSACleanup(); +#else + pthread_cancel(tid); + pthread_join(tid, NULL); + if (close(fd) < 0) { + perror("close"); + } +#endif + return (0); +} diff --git a/chromium/third_party/usrsctp/usrsctplib/programs/rtcweb.c b/chromium/third_party/usrsctp/usrsctplib/programs/rtcweb.c new file mode 100644 index 00000000000..4b940edcc0e --- /dev/null +++ b/chromium/third_party/usrsctp/usrsctplib/programs/rtcweb.c @@ -0,0 +1,1517 @@ +/*- + * Copyright (C) 2012-2013 Michael Tuexen + * Copyright (C) 2012-2013 Irene Ruengeler + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: rtcweb.c,v 1.26 2012-07-17 13:50:02 tuexen Exp $ + */ + +/* + * gcc -Wall -std=c99 -pedantic -o rtcweb rtcweb.c -lusrsctp + */ + +#include <sys/types.h> +#ifdef _WIN32 +#define _CRT_SECURE_NO_WARNINGS +#include <WinSock2.h> +#include <WS2tcpip.h> +#include <crtdbg.h> +#else +#include <sys/socket.h> +#include <sys/select.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <pthread.h> +#include <unistd.h> +#include <stdint.h> +#endif +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <usrsctp.h> + +#define LINE_LENGTH (1024) +#define BUFFER_SIZE (1<<16) +#define NUMBER_OF_CHANNELS (100) +#define NUMBER_OF_STREAMS (100) + +#define DATA_CHANNEL_PPID_CONTROL 50 +#define DATA_CHANNEL_PPID_DOMSTRING 51 +#define DATA_CHANNEL_PPID_BINARY 52 + +#define DATA_CHANNEL_CLOSED 0 +#define DATA_CHANNEL_CONNECTING 1 +#define DATA_CHANNEL_OPEN 2 +#define DATA_CHANNEL_CLOSING 3 + +#define DATA_CHANNEL_FLAGS_SEND_REQ 0x00000001 +#define DATA_CHANNEL_FLAGS_SEND_RSP 0x00000002 +#define DATA_CHANNEL_FLAGS_SEND_ACK 0x00000004 + +struct channel { + uint32_t id; + uint32_t pr_value; + uint16_t pr_policy; + uint16_t i_stream; + uint16_t o_stream; + uint8_t unordered; + uint8_t state; + uint32_t flags; +}; + +struct peer_connection { + struct channel channels[NUMBER_OF_CHANNELS]; + struct channel *i_stream_channel[NUMBER_OF_STREAMS]; + struct channel *o_stream_channel[NUMBER_OF_STREAMS]; + uint16_t o_stream_buffer[NUMBER_OF_STREAMS]; + uint32_t o_stream_buffer_counter; +#ifdef _WIN32 + CRITICAL_SECTION mutex; +#else + pthread_mutex_t mutex; +#endif + struct socket *sock; +} peer_connection; + +#define DATA_CHANNEL_OPEN_REQUEST 0 +#define DATA_CHANNEL_OPEN_RESPONSE 1 +#define DATA_CHANNEL_ACK 2 + +#define DATA_CHANNEL_RELIABLE 0 +#define DATA_CHANNEL_RELIABLE_STREAM 1 +#define DATA_CHANNEL_UNRELIABLE 2 +#define DATA_CHANNEL_PARTIAL_RELIABLE_REXMIT 3 +#define DATA_CHANNEL_PARTIAL_RELIABLE_TIMED 4 + +#define DATA_CHANNEL_FLAG_OUT_OF_ORDER_ALLOWED 0x0001 + +#ifndef _WIN32 +#define SCTP_PACKED __attribute__((packed)) +#else +#pragma pack (push, 1) +#define SCTP_PACKED +#endif + +struct rtcweb_datachannel_open_request { + uint8_t msg_type; /* DATA_CHANNEL_OPEN_REQUEST */ + uint8_t channel_type; + uint16_t flags; + uint16_t reliability_params; + int16_t priority; + char label[]; +} SCTP_PACKED; + +struct rtcweb_datachannel_open_response { + uint8_t msg_type; /* DATA_CHANNEL_OPEN_RESPONSE */ + uint8_t error; + uint16_t flags; + uint16_t reverse_stream; +} SCTP_PACKED; + +struct rtcweb_datachannel_ack { + uint8_t msg_type; /* DATA_CHANNEL_ACK */ +} SCTP_PACKED; + +#ifdef _WIN32 +#pragma pack() +#endif + +#undef SCTP_PACKED + +static void +init_peer_connection(struct peer_connection *pc) +{ + uint32_t i; + struct channel *channel; + + for (i = 0; i < NUMBER_OF_CHANNELS; i++) { + channel = &(pc->channels[i]); + channel->id = i; + channel->state = DATA_CHANNEL_CLOSED; + channel->pr_policy = SCTP_PR_SCTP_NONE; + channel->pr_value = 0; + channel->i_stream = 0; + channel->o_stream = 0; + channel->unordered = 0; + channel->flags = 0; + } + for (i = 0; i < NUMBER_OF_STREAMS; i++) { + pc->i_stream_channel[i] = NULL; + pc->o_stream_channel[i] = NULL; + pc->o_stream_buffer[i] = 0; + } + pc->o_stream_buffer_counter = 0; + pc->sock = NULL; +#ifdef _WIN32 + InitializeCriticalSection(&(pc->mutex)); +#else + pthread_mutex_init(&pc->mutex, NULL); +#endif +} + +static void +lock_peer_connection(struct peer_connection *pc) +{ +#ifdef _WIN32 + EnterCriticalSection(&(pc->mutex)); +#else + pthread_mutex_lock(&pc->mutex); +#endif +} + +static void +unlock_peer_connection(struct peer_connection *pc) +{ +#ifdef _WIN32 + LeaveCriticalSection(&(pc->mutex)); +#else + pthread_mutex_unlock(&pc->mutex); +#endif +} + +static struct channel * +find_channel_by_i_stream(struct peer_connection *pc, uint16_t i_stream) +{ + if (i_stream < NUMBER_OF_STREAMS) { + return (pc->i_stream_channel[i_stream]); + } else { + return (NULL); + } +} + +static struct channel * +find_channel_by_o_stream(struct peer_connection *pc, uint16_t o_stream) +{ + if (o_stream < NUMBER_OF_STREAMS) { + return (pc->o_stream_channel[o_stream]); + } else { + return (NULL); + } +} + +static struct channel * +find_free_channel(struct peer_connection *pc) +{ + uint32_t i; + + for (i = 0; i < NUMBER_OF_CHANNELS; i++) { + if (pc->channels[i].state == DATA_CHANNEL_CLOSED) { + break; + } + } + if (i == NUMBER_OF_CHANNELS) { + return (NULL); + } else { + return (&(pc->channels[i])); + } +} + +static uint16_t +find_free_o_stream(struct peer_connection *pc) +{ + struct sctp_status status; + uint32_t i, limit; + socklen_t len; + + len = (socklen_t)sizeof(struct sctp_status); + if (usrsctp_getsockopt(pc->sock, IPPROTO_SCTP, SCTP_STATUS, &status, &len) < 0) { + perror("getsockopt"); + return (0); + } + if (status.sstat_outstrms < NUMBER_OF_STREAMS) { + limit = status.sstat_outstrms; + } else { + limit = NUMBER_OF_STREAMS; + } + /* stream id 0 is reserved */ + for (i = 1; i < limit; i++) { + if (pc->o_stream_channel[i] == NULL) { + break; + } + } + if (i == limit) { + return (0); + } else { + return ((uint16_t)i); + } +} + +static void +request_more_o_streams(struct peer_connection *pc) +{ + struct sctp_status status; + struct sctp_add_streams sas; + uint32_t i, o_streams_needed; + socklen_t len; + + o_streams_needed = 0; + for (i = 0; i < NUMBER_OF_CHANNELS; i++) { + if ((pc->channels[i].state == DATA_CHANNEL_CONNECTING) && + (pc->channels[i].o_stream == 0)) { + o_streams_needed++; + } + } + len = (socklen_t)sizeof(struct sctp_status); + if (usrsctp_getsockopt(pc->sock, IPPROTO_SCTP, SCTP_STATUS, &status, &len) < 0) { + perror("getsockopt"); + return; + } + if (status.sstat_outstrms + o_streams_needed > NUMBER_OF_STREAMS) { + o_streams_needed = NUMBER_OF_STREAMS - status.sstat_outstrms; + } + if (o_streams_needed == 0) { + return; + } + memset(&sas, 0, sizeof(struct sctp_add_streams)); + sas.sas_instrms = 0; + sas.sas_outstrms = (uint16_t)o_streams_needed; /* XXX eror handling */ + if (usrsctp_setsockopt(pc->sock, IPPROTO_SCTP, SCTP_ADD_STREAMS, &sas, (socklen_t)sizeof(struct sctp_add_streams)) < 0) { + perror("setsockopt"); + } + return; +} + +static int +send_open_request_message(struct socket *sock, uint16_t o_stream, uint8_t unordered, uint16_t pr_policy, uint32_t pr_value) +{ + /* XXX: This should be encoded in a better way */ + struct rtcweb_datachannel_open_request req; + struct sctp_sndinfo sndinfo; + + memset(&req, 0, sizeof(struct rtcweb_datachannel_open_request)); + req.msg_type = DATA_CHANNEL_OPEN_REQUEST; + switch (pr_policy) { + case SCTP_PR_SCTP_NONE: + /* XXX: What about DATA_CHANNEL_RELIABLE_STREAM */ + req.channel_type = DATA_CHANNEL_RELIABLE; + break; + case SCTP_PR_SCTP_TTL: + /* XXX: What about DATA_CHANNEL_UNRELIABLE */ + req.channel_type = DATA_CHANNEL_PARTIAL_RELIABLE_TIMED; + break; + case SCTP_PR_SCTP_RTX: + req.channel_type = DATA_CHANNEL_PARTIAL_RELIABLE_REXMIT; + break; + default: + return (0); + } + req.flags = htons(0); + if (unordered) { + req.flags |= htons(DATA_CHANNEL_FLAG_OUT_OF_ORDER_ALLOWED); + } + req.reliability_params = htons((uint16_t)pr_value); /* XXX Why 16-bit */ + req.priority = htons(0); /* XXX: add support */ + memset(&sndinfo, 0, sizeof(struct sctp_sndinfo)); + sndinfo.snd_sid = o_stream; + sndinfo.snd_flags = SCTP_EOR; + sndinfo.snd_ppid = htonl(DATA_CHANNEL_PPID_CONTROL); + if (usrsctp_sendv(sock, + &req, sizeof(struct rtcweb_datachannel_open_request), + NULL, 0, + &sndinfo, (socklen_t)sizeof(struct sctp_sndinfo), + SCTP_SENDV_SNDINFO, 0) < 0) { + perror("sctp_sendv"); + return (0); + } else { + return (1); + } +} + +static int +send_open_response_message(struct socket *sock, uint16_t o_stream, uint16_t i_stream) +{ + /* XXX: This should be encoded in a better way */ + struct rtcweb_datachannel_open_response rsp; + struct sctp_sndinfo sndinfo; + + memset(&rsp, 0, sizeof(struct rtcweb_datachannel_open_response)); + rsp.msg_type = DATA_CHANNEL_OPEN_RESPONSE; + rsp.error = 0; + rsp.flags = htons(0); + rsp.reverse_stream = htons(i_stream); + memset(&sndinfo, 0, sizeof(struct sctp_sndinfo)); + sndinfo.snd_sid = o_stream; + sndinfo.snd_flags = SCTP_EOR; + sndinfo.snd_ppid = htonl(DATA_CHANNEL_PPID_CONTROL); + if (usrsctp_sendv(sock, + &rsp, sizeof(struct rtcweb_datachannel_open_response), + NULL, 0, + &sndinfo, (socklen_t)sizeof(struct sctp_sndinfo), + SCTP_SENDV_SNDINFO, 0) < 0) { + perror("sctp_sendv"); + return (0); + } else { + return (1); + } +} + +static int +send_open_ack_message(struct socket *sock, uint16_t o_stream) +{ + /* XXX: This should be encoded in a better way */ + struct rtcweb_datachannel_ack ack; + struct sctp_sndinfo sndinfo; + + memset(&ack, 0, sizeof(struct rtcweb_datachannel_ack)); + ack.msg_type = DATA_CHANNEL_ACK; + memset(&sndinfo, 0, sizeof(struct sctp_sndinfo)); + sndinfo.snd_sid = o_stream; + sndinfo.snd_flags = SCTP_EOR; + sndinfo.snd_ppid = htonl(DATA_CHANNEL_PPID_CONTROL); + if (usrsctp_sendv(sock, + &ack, sizeof(struct rtcweb_datachannel_ack), + NULL, 0, + &sndinfo, (socklen_t)sizeof(struct sctp_sndinfo), + SCTP_SENDV_SNDINFO, 0) < 0) { + perror("sctp_sendv"); + return (0); + } else { + return (1); + } +} + +static void +send_deferred_messages(struct peer_connection *pc) +{ + uint32_t i; + struct channel *channel; + + for (i = 0; i < NUMBER_OF_CHANNELS; i++) { + channel = &(pc->channels[i]); + if (channel->flags & DATA_CHANNEL_FLAGS_SEND_REQ) { + if (send_open_request_message(pc->sock, channel->o_stream, channel->unordered, channel->pr_policy, channel->pr_value)) { + channel->flags &= ~DATA_CHANNEL_FLAGS_SEND_REQ; + } else { + if (errno != EAGAIN) { + /* XXX: error handling */ + } + } + } + if (channel->flags & DATA_CHANNEL_FLAGS_SEND_RSP) { + if (send_open_response_message(pc->sock, channel->o_stream, channel->i_stream)) { + channel->flags &= ~DATA_CHANNEL_FLAGS_SEND_RSP; + } else { + if (errno != EAGAIN) { + /* XXX: error handling */ + } + } + } + if (channel->flags & DATA_CHANNEL_FLAGS_SEND_ACK) { + if (send_open_ack_message(pc->sock, channel->o_stream)) { + channel->flags &= ~DATA_CHANNEL_FLAGS_SEND_ACK; + } else { + if (errno != EAGAIN) { + /* XXX: error handling */ + } + } + } + } + return; +} + +static struct channel * +open_channel(struct peer_connection *pc, uint8_t unordered, uint16_t pr_policy, uint32_t pr_value) +{ + struct channel *channel; + uint16_t o_stream; + + if ((pr_policy != SCTP_PR_SCTP_NONE) && + (pr_policy != SCTP_PR_SCTP_TTL) && + (pr_policy != SCTP_PR_SCTP_RTX)) { + return (NULL); + } + if ((unordered != 0) && (unordered != 1)) { + return (NULL); + } + if ((pr_policy == SCTP_PR_SCTP_NONE) && (pr_value != 0)) { + return (NULL); + } + if ((channel = find_free_channel(pc)) == NULL) { + return (NULL); + } + o_stream = find_free_o_stream(pc); + channel->state = DATA_CHANNEL_CONNECTING; + channel->unordered = unordered; + channel->pr_policy = pr_policy; + channel->pr_value = pr_value; + channel->o_stream = o_stream; + channel->flags = 0; + if (o_stream == 0) { + request_more_o_streams(pc); + } else { + if (send_open_request_message(pc->sock, o_stream, unordered, pr_policy, pr_value)) { + pc->o_stream_channel[o_stream] = channel; + } else { + if (errno == EAGAIN) { + pc->o_stream_channel[o_stream] = channel; + channel->flags |= DATA_CHANNEL_FLAGS_SEND_REQ; + } else { + channel->state = DATA_CHANNEL_CLOSED; + channel->unordered = 0; + channel->pr_policy = 0; + channel->pr_value = 0; + channel->o_stream = 0; + channel->flags = 0; + channel = NULL; + } + } + } + return (channel); +} + +static int +send_user_message(struct peer_connection *pc, struct channel *channel, char *message, size_t length) +{ + struct sctp_sendv_spa spa; + + if (channel == NULL) { + return (0); + } + if ((channel->state != DATA_CHANNEL_OPEN) && + (channel->state != DATA_CHANNEL_CONNECTING)) { + /* XXX: What to do in other states */ + return (0); + } + + memset(&spa, 0, sizeof(struct sctp_sendv_spa)); + spa.sendv_sndinfo.snd_sid = channel->o_stream; + if ((channel->state == DATA_CHANNEL_OPEN) && + (channel->unordered)) { + spa.sendv_sndinfo.snd_flags = SCTP_EOR | SCTP_UNORDERED; + } else { + spa.sendv_sndinfo.snd_flags = SCTP_EOR; + } + spa.sendv_sndinfo.snd_ppid = htonl(DATA_CHANNEL_PPID_DOMSTRING); + spa.sendv_flags = SCTP_SEND_SNDINFO_VALID; + if ((channel->pr_policy == SCTP_PR_SCTP_TTL) || + (channel->pr_policy == SCTP_PR_SCTP_RTX)) { + spa.sendv_prinfo.pr_policy = channel->pr_policy; + spa.sendv_prinfo.pr_value = channel->pr_value; + spa.sendv_flags |= SCTP_SEND_PRINFO_VALID; + } + if (usrsctp_sendv(pc->sock, + message, length, + NULL, 0, + &spa, (socklen_t)sizeof(struct sctp_sendv_spa), + SCTP_SENDV_SPA, 0) < 0) { + perror("sctp_sendv"); + return (0); + } else { + return (1); + } +} + +static void +reset_outgoing_stream(struct peer_connection *pc, uint16_t o_stream) +{ + uint32_t i; + + for (i = 0; i < pc->o_stream_buffer_counter; i++) { + if (pc->o_stream_buffer[i] == o_stream) { + return; + } + } + pc->o_stream_buffer[pc->o_stream_buffer_counter++] = o_stream; + return; +} + +static void +send_outgoing_stream_reset(struct peer_connection *pc) +{ + struct sctp_reset_streams *srs; + uint32_t i; + size_t len; + + if (pc->o_stream_buffer_counter == 0) { + return; + } + len = sizeof(sctp_assoc_t) + (2 + pc->o_stream_buffer_counter) * sizeof(uint16_t); + srs = (struct sctp_reset_streams *)malloc(len); + if (srs == NULL) { + return; + } + memset(srs, 0, len); + srs->srs_flags = SCTP_STREAM_RESET_OUTGOING; + srs->srs_number_streams = pc->o_stream_buffer_counter; + for (i = 0; i < pc->o_stream_buffer_counter; i++) { + srs->srs_stream_list[i] = pc->o_stream_buffer[i]; + } + if (usrsctp_setsockopt(pc->sock, IPPROTO_SCTP, SCTP_RESET_STREAMS, srs, (socklen_t)len) < 0) { + perror("setsockopt"); + } else { + for (i = 0; i < pc->o_stream_buffer_counter; i++) { + srs->srs_stream_list[i] = 0; + } + pc->o_stream_buffer_counter = 0; + } + free(srs); + return; +} + +static void +close_channel(struct peer_connection *pc, struct channel *channel) +{ + if (channel == NULL) { + return; + } + if (channel->state != DATA_CHANNEL_OPEN) { + return; + } + reset_outgoing_stream(pc, channel->o_stream); + send_outgoing_stream_reset(pc); + channel->state = DATA_CHANNEL_CLOSING; + return; +} + +static void +handle_open_request_message(struct peer_connection *pc, + struct rtcweb_datachannel_open_request *req, + size_t length, + uint16_t i_stream) +{ + struct channel *channel; + uint32_t pr_value; + uint16_t pr_policy; + uint16_t o_stream; + uint8_t unordered; + + if ((channel = find_channel_by_i_stream(pc, i_stream))) { + printf("handle_open_request_message: channel %d is in state %d instead of CLOSED.\n", + channel->id, channel->state); + /* XXX: some error handling */ + return; + } + if ((channel = find_free_channel(pc)) == NULL) { + /* XXX: some error handling */ + return; + } + switch (req->channel_type) { + case DATA_CHANNEL_RELIABLE: + pr_policy = SCTP_PR_SCTP_NONE; + break; + /* XXX Doesn't make sense */ + case DATA_CHANNEL_RELIABLE_STREAM: + pr_policy = SCTP_PR_SCTP_NONE; + break; + /* XXX Doesn't make sense */ + case DATA_CHANNEL_UNRELIABLE: + pr_policy = SCTP_PR_SCTP_TTL; + break; + case DATA_CHANNEL_PARTIAL_RELIABLE_REXMIT: + pr_policy = SCTP_PR_SCTP_RTX; + break; + case DATA_CHANNEL_PARTIAL_RELIABLE_TIMED: + pr_policy = SCTP_PR_SCTP_TTL; + break; + default: + pr_policy = SCTP_PR_SCTP_NONE; + /* XXX error handling */ + break; + } + pr_value = ntohs(req->reliability_params); + if (ntohs(req->flags) & DATA_CHANNEL_FLAG_OUT_OF_ORDER_ALLOWED) { + unordered = 1; + } else { + unordered = 0; + } + o_stream = find_free_o_stream(pc); + channel->state = DATA_CHANNEL_CONNECTING; + channel->unordered = unordered; + channel->pr_policy = pr_policy; + channel->pr_value = pr_value; + channel->i_stream = i_stream; + channel->o_stream = o_stream; + channel->flags = 0; + pc->i_stream_channel[i_stream] = channel; + if (o_stream == 0) { + request_more_o_streams(pc); + } else { + if (send_open_response_message(pc->sock, o_stream, i_stream)) { + pc->o_stream_channel[o_stream] = channel; + } else { + if (errno == EAGAIN) { + channel->flags |= DATA_CHANNEL_FLAGS_SEND_RSP; + pc->o_stream_channel[o_stream] = channel; + } else { + /* XXX: Signal error to the other end. */ + pc->i_stream_channel[i_stream] = NULL; + channel->state = DATA_CHANNEL_CLOSED; + channel->unordered = 0; + channel->pr_policy = 0; + channel->pr_value = 0; + channel->i_stream = 0; + channel->o_stream = 0; + channel->flags = 0; + } + } + } +} + +static void +handle_open_response_message(struct peer_connection *pc, + struct rtcweb_datachannel_open_response *rsp, + size_t length, uint16_t i_stream) +{ + uint16_t o_stream; + struct channel *channel; + + o_stream = ntohs(rsp->reverse_stream); + channel = find_channel_by_o_stream(pc, o_stream); + if (channel == NULL) { + /* XXX: improve error handling */ + printf("handle_open_response_message: Can't find channel for outgoing steam %d.\n", o_stream); + return; + } + if (channel->state != DATA_CHANNEL_CONNECTING) { + /* XXX: improve error handling */ + printf("handle_open_response_message: Channel with id %d for outgoing steam %d is in state %d.\n", channel->id, o_stream, channel->state); + return; + } + if (find_channel_by_i_stream(pc, i_stream)) { + /* XXX: improve error handling */ + printf("handle_open_response_message: Channel collision for channel with id %d and streams (in/out) = (%d/%d).\n", channel->id, i_stream, o_stream); + return; + } + channel->i_stream = i_stream; + channel->state = DATA_CHANNEL_OPEN; + pc->i_stream_channel[i_stream] = channel; + if (send_open_ack_message(pc->sock, o_stream)) { + channel->flags = 0; + } else { + channel->flags |= DATA_CHANNEL_FLAGS_SEND_ACK; + } + return; +} + +static void +handle_open_ack_message(struct peer_connection *pc, + struct rtcweb_datachannel_ack *ack, + size_t length, uint16_t i_stream) +{ + struct channel *channel; + + channel = find_channel_by_i_stream(pc, i_stream); + if (channel == NULL) { + /* XXX: some error handling */ + return; + } + if (channel->state == DATA_CHANNEL_OPEN) { + return; + } + if (channel->state != DATA_CHANNEL_CONNECTING) { + /* XXX: error handling */ + return; + } + channel->state = DATA_CHANNEL_OPEN; + return; +} + +static void +handle_unknown_message(char *msg, size_t length, uint16_t i_stream) +{ + /* XXX: Send an error message */ + return; +} + +static void +handle_data_message(struct peer_connection *pc, + char *buffer, size_t length, uint16_t i_stream) +{ + struct channel *channel; + + channel = find_channel_by_i_stream(pc, i_stream); + if (channel == NULL) { + /* XXX: Some error handling */ + return; + } + if (channel->state == DATA_CHANNEL_CONNECTING) { + /* Implicit ACK */ + channel->state = DATA_CHANNEL_OPEN; + } + if (channel->state != DATA_CHANNEL_OPEN) { + /* XXX: What about other states? */ + /* XXX: Some error handling */ + return; + } else { + /* Assuming DATA_CHANNEL_PPID_DOMSTRING */ + /* XXX: Protect for non 0 terminated buffer */ + printf("Message received of length %zu on channel with id %d: %.*s\n", + length, channel->id, (int)length, buffer); + } + return; +} + +static void +handle_message(struct peer_connection *pc, char *buffer, size_t length, uint32_t ppid, uint16_t i_stream) +{ + struct rtcweb_datachannel_open_request *req; + struct rtcweb_datachannel_open_response *rsp; + struct rtcweb_datachannel_ack *ack, *msg; + + switch (ppid) { + case DATA_CHANNEL_PPID_CONTROL: + if (length < sizeof(struct rtcweb_datachannel_ack)) { + return; + } + msg = (struct rtcweb_datachannel_ack *)buffer; + switch (msg->msg_type) { + case DATA_CHANNEL_OPEN_REQUEST: + if (length < sizeof(struct rtcweb_datachannel_open_request)) { + /* XXX: error handling? */ + return; + } + req = (struct rtcweb_datachannel_open_request *)buffer; + handle_open_request_message(pc, req, length, i_stream); + break; + case DATA_CHANNEL_OPEN_RESPONSE: + if (length < sizeof(struct rtcweb_datachannel_open_response)) { + /* XXX: error handling? */ + return; + } + rsp = (struct rtcweb_datachannel_open_response *)buffer; + handle_open_response_message(pc, rsp, length, i_stream); + break; + case DATA_CHANNEL_ACK: + if (length < sizeof(struct rtcweb_datachannel_ack)) { + /* XXX: error handling? */ + return; + } + ack = (struct rtcweb_datachannel_ack *)buffer; + handle_open_ack_message(pc, ack, length, i_stream); + break; + default: + handle_unknown_message(buffer, length, i_stream); + break; + } + break; + case DATA_CHANNEL_PPID_DOMSTRING: + case DATA_CHANNEL_PPID_BINARY: + handle_data_message(pc, buffer, length, i_stream); + break; + default: + printf("Message of length %zu, PPID %u on stream %u received.\n", + length, ppid, i_stream); + break; + } +} + +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; + + 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; + 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_adaptation_indication(struct sctp_adaptation_event *sai) +{ + printf("Adaptation indication: %x.\n", sai-> sai_adaptation_ind); + return; +} + +static void +handle_shutdown_event(struct sctp_shutdown_event *sse) +{ + printf("Shutdown event.\n"); + /* XXX: notify all channels. */ + return; +} + +static void +handle_stream_reset_event(struct peer_connection *pc, struct sctp_stream_reset_event *strrst) +{ + uint32_t n, i; + struct channel *channel; + + n = (strrst->strreset_length - sizeof(struct sctp_stream_reset_event)) / sizeof(uint16_t); + printf("Stream reset event: flags = %x, ", strrst->strreset_flags); + if (strrst->strreset_flags & SCTP_STREAM_RESET_INCOMING_SSN) { + if (strrst->strreset_flags & SCTP_STREAM_RESET_OUTGOING_SSN) { + printf("incoming/"); + } + printf("incoming "); + } + if (strrst->strreset_flags & SCTP_STREAM_RESET_OUTGOING_SSN) { + printf("outgoing "); + } + printf("stream ids = "); + for (i = 0; i < n; i++) { + if (i > 0) { + printf(", "); + } + printf("%d", strrst->strreset_stream_list[i]); + } + printf(".\n"); + if (!(strrst->strreset_flags & SCTP_STREAM_RESET_DENIED) && + !(strrst->strreset_flags & SCTP_STREAM_RESET_FAILED)) { + for (i = 0; i < n; i++) { + if (strrst->strreset_flags & SCTP_STREAM_RESET_INCOMING_SSN) { + channel = find_channel_by_i_stream(pc, strrst->strreset_stream_list[i]); + if (channel != NULL) { + pc->i_stream_channel[channel->i_stream] = NULL; + channel->i_stream = 0; + if (channel->o_stream == 0) { + channel->pr_policy = SCTP_PR_SCTP_NONE; + channel->pr_value = 0; + channel->unordered = 0; + channel->flags = 0; + channel->state = DATA_CHANNEL_CLOSED; + } else { + if (channel->state == DATA_CHANNEL_OPEN) { + reset_outgoing_stream(pc, channel->o_stream); + channel->state = DATA_CHANNEL_CLOSING; + } else { + /* XXX: What to do? */ + } + } + } + } + if (strrst->strreset_flags & SCTP_STREAM_RESET_OUTGOING_SSN) { + channel = find_channel_by_o_stream(pc, strrst->strreset_stream_list[i]); + if (channel != NULL) { + pc->o_stream_channel[channel->o_stream] = NULL; + channel->o_stream = 0; + if (channel->i_stream == 0) { + channel->pr_policy = SCTP_PR_SCTP_NONE; + channel->pr_value = 0; + channel->unordered = 0; + channel->flags = 0; + channel->state = DATA_CHANNEL_CLOSED; + } + } + } + } + } + return; +} + +static void +handle_stream_change_event(struct peer_connection *pc, struct sctp_stream_change_event *strchg) +{ + uint16_t o_stream; + uint32_t i; + struct channel *channel; + + printf("Stream change event: streams (in/out) = (%u/%u), flags = %x.\n", + strchg->strchange_instrms, strchg->strchange_outstrms, strchg->strchange_flags); + for (i = 0; i < NUMBER_OF_CHANNELS; i++) { + channel = &(pc->channels[i]); + if ((channel->state == DATA_CHANNEL_CONNECTING) && + (channel->o_stream == 0)) { + if ((strchg->strchange_flags & SCTP_STREAM_CHANGE_DENIED) || + (strchg->strchange_flags & SCTP_STREAM_CHANGE_FAILED)) { + /* XXX: Signal to the other end. */ + if (channel->i_stream != 0) { + pc->i_stream_channel[channel->i_stream] = NULL; + } + channel->unordered = 0; + channel->pr_policy = SCTP_PR_SCTP_NONE; + channel->pr_value = 0; + channel->i_stream = 0; + channel->o_stream = 0; + channel->flags = 0; + channel->state = DATA_CHANNEL_CLOSED; + } else { + o_stream = find_free_o_stream(pc); + if (o_stream != 0) { + channel->o_stream = o_stream; + pc->o_stream_channel[o_stream] = channel; + if (channel->i_stream == 0) { + channel->flags |= DATA_CHANNEL_FLAGS_SEND_REQ; + } else { + channel->flags |= DATA_CHANNEL_FLAGS_SEND_RSP; + } + } else { + /* We will not find more ... */ + break; + } + } + } + } + return; +} + +static void +handle_remote_error_event(struct sctp_remote_error *sre) +{ + size_t i, n; + + n = sre->sre_length - sizeof(struct sctp_remote_error); + printf("Remote Error (error = 0x%04x): ", sre->sre_error); + for (i = 0; i < n; i++) { + printf(" 0x%02x", sre-> sre_data[i]); + } + printf(".\n"); + 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 = %d, SID = %d, 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(struct peer_connection *pc, 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: + handle_remote_error_event(&(notif->sn_remote_error)); + break; + case SCTP_SHUTDOWN_EVENT: + handle_shutdown_event(&(notif->sn_shutdown_event)); + break; + case SCTP_ADAPTATION_INDICATION: + handle_adaptation_indication(&(notif->sn_adaptation_event)); + 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: + handle_stream_reset_event(pc, &(notif->sn_strreset_event)); + send_deferred_messages(pc); + send_outgoing_stream_reset(pc); + request_more_o_streams(pc); + break; + case SCTP_ASSOC_RESET_EVENT: + break; + case SCTP_STREAM_CHANGE_EVENT: + handle_stream_change_event(pc, &(notif->sn_strchange_event)); + send_deferred_messages(pc); + send_outgoing_stream_reset(pc); + request_more_o_streams(pc); + break; + default: + break; + } +} + +static void +print_status(struct peer_connection *pc) +{ + struct sctp_status status; + socklen_t len; + uint32_t i; + struct channel *channel; + + len = (socklen_t)sizeof(struct sctp_status); + if (usrsctp_getsockopt(pc->sock, IPPROTO_SCTP, SCTP_STATUS, &status, &len) < 0) { + perror("getsockopt"); + return; + } + printf("Association state: "); + switch (status.sstat_state) { + case SCTP_CLOSED: + printf("CLOSED\n"); + break; + case SCTP_BOUND: + printf("BOUND\n"); + break; + case SCTP_LISTEN: + printf("LISTEN\n"); + break; + case SCTP_COOKIE_WAIT: + printf("COOKIE_WAIT\n"); + break; + case SCTP_COOKIE_ECHOED: + printf("COOKIE_ECHOED\n"); + break; + case SCTP_ESTABLISHED: + printf("ESTABLISHED\n"); + break; + case SCTP_SHUTDOWN_PENDING: + printf("SHUTDOWN_PENDING\n"); + break; + case SCTP_SHUTDOWN_SENT: + printf("SHUTDOWN_SENT\n"); + break; + case SCTP_SHUTDOWN_RECEIVED: + printf("SHUTDOWN_RECEIVED\n"); + break; + case SCTP_SHUTDOWN_ACK_SENT: + printf("SHUTDOWN_ACK_SENT\n"); + break; + default: + printf("UNKNOWN\n"); + break; + } + printf("Number of streams (i/o) = (%u/%u)\n", + status.sstat_instrms, status.sstat_outstrms); + for (i = 0; i < NUMBER_OF_CHANNELS; i++) { + channel = &(pc->channels[i]); + if (channel->state == DATA_CHANNEL_CLOSED) { + continue; + } + printf("Channel with id = %u: state ", channel->id); + switch (channel->state) { + case DATA_CHANNEL_CLOSED: + printf("CLOSED"); + break; + case DATA_CHANNEL_CONNECTING: + printf("CONNECTING"); + break; + case DATA_CHANNEL_OPEN: + printf("OPEN"); + break; + case DATA_CHANNEL_CLOSING: + printf("CLOSING"); + break; + default: + printf("UNKNOWN(%d)", channel->state); + break; + } + printf(", flags = 0x%08x, stream id (in/out): (%u/%u), ", + channel->flags, + channel->i_stream, + channel->o_stream); + if (channel->unordered) { + printf("unordered, "); + } else { + printf("ordered, "); + } + switch (channel->pr_policy) { + case SCTP_PR_SCTP_NONE: + printf("reliable.\n"); + break; + case SCTP_PR_SCTP_TTL: + printf("unreliable (timeout %ums).\n", channel->pr_value); + break; + case SCTP_PR_SCTP_RTX: + printf("unreliable (max. %u rtx).\n", channel->pr_value); + break; + default: + printf("unkown policy %u.\n", channel->pr_policy); + 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) +{ + struct peer_connection *pc; + + pc = (struct peer_connection *)ulp_info; + + if (data) { + lock_peer_connection(pc); + if (flags & MSG_NOTIFICATION) { + handle_notification(pc, (union sctp_notification *)data, datalen); + } else { + handle_message(pc, data, datalen, ntohl(rcv.rcv_ppid), rcv.rcv_sid); + } + unlock_peer_connection(pc); + } + return (1); +} + +void +debug_printf(const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + vprintf(format, ap); + va_end(ap); +} + +int +main(int argc, char *argv[]) +{ + struct socket *sock; + struct sockaddr_in addr; + socklen_t addr_len; + char line[LINE_LENGTH + 1]; + unsigned int unordered, policy, value, id, seconds; + unsigned int i; + struct channel *channel; + const int on = 1; + struct sctp_assoc_value av; + struct sctp_event event; + struct sctp_udpencaps encaps; + struct sctp_initmsg initmsg; + uint16_t event_types[] = {SCTP_ASSOC_CHANGE, + SCTP_PEER_ADDR_CHANGE, + SCTP_REMOTE_ERROR, + SCTP_SHUTDOWN_EVENT, + SCTP_ADAPTATION_INDICATION, + SCTP_SEND_FAILED_EVENT, + SCTP_STREAM_RESET_EVENT, + SCTP_STREAM_CHANGE_EVENT}; + char addrbuf[INET_ADDRSTRLEN]; + + if (argc > 1) { + usrsctp_init(atoi(argv[1]), NULL, debug_printf); + } else { + usrsctp_init(9899, NULL, debug_printf); + } +#ifdef SCTP_DEBUG + usrsctp_sysctl_set_sctp_debug_on(SCTP_DEBUG_NONE); +#endif + usrsctp_sysctl_set_sctp_blackhole(2); + + if ((sock = usrsctp_socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP, receive_cb, NULL, 0, &peer_connection)) == NULL) { + perror("socket"); + } + init_peer_connection(&peer_connection); + if (argc > 2) { + memset(&encaps, 0, sizeof(struct sctp_udpencaps)); + encaps.sue_address.ss_family = AF_INET6; + encaps.sue_port = htons(atoi(argv[2])); + if (usrsctp_setsockopt(sock, IPPROTO_SCTP, SCTP_REMOTE_UDP_ENCAPS_PORT, (const void*)&encaps, (socklen_t)sizeof(struct sctp_udpencaps)) < 0) { + perror("setsockopt"); + } + } + if (usrsctp_setsockopt(sock, IPPROTO_SCTP, SCTP_RECVRCVINFO, &on, sizeof(int)) < 0) { + perror("setsockopt SCTP_RECVRCVINFO"); + } + if (usrsctp_setsockopt(sock, IPPROTO_SCTP, SCTP_EXPLICIT_EOR, &on, sizeof(int)) < 0) { + perror("setsockopt SCTP_EXPLICIT_EOR"); + } + /* Allow resetting streams. */ + av.assoc_id = SCTP_ALL_ASSOC; + av.assoc_value = SCTP_ENABLE_RESET_STREAM_REQ | SCTP_ENABLE_CHANGE_ASSOC_REQ; + if (usrsctp_setsockopt(sock, IPPROTO_SCTP, SCTP_ENABLE_STREAM_RESET, &av, sizeof(struct sctp_assoc_value)) < 0) { + perror("setsockopt SCTP_ENABLE_STREAM_RESET"); + } + /* Enable the events of interest. */ + 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"); + } + } + memset(&initmsg, 0, sizeof(struct sctp_initmsg)); + initmsg.sinit_num_ostreams = 5; + initmsg.sinit_max_instreams = 65535; + if (usrsctp_setsockopt(sock, IPPROTO_SCTP, SCTP_INITMSG, &initmsg, sizeof(struct sctp_initmsg)) < 0) { + perror("setsockopt SCTP_INITMSG"); + } + + if (argc == 5) { + /* operating as client */ + memset(&addr, 0, sizeof(struct sockaddr_in)); + addr.sin_family = AF_INET; +#ifdef HAVE_SIN_LEN + addr.sin_len = sizeof(struct sockaddr_in); +#endif + if (!inet_pton(AF_INET, argv[3], &addr.sin_addr.s_addr)){ + printf("error: invalid address\n"); + exit(1); + } + addr.sin_port = htons(atoi(argv[4])); + if (usrsctp_connect(sock, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0) { + perror("connect"); + } + + printf("Connected to %s:%d.\n", inet_ntop(AF_INET, &(addr.sin_addr), addrbuf, INET_ADDRSTRLEN), ntohs(addr.sin_port)); + } else if (argc == 4) { + struct socket *conn_sock; + + /* operating as server */ + memset(&addr, 0, sizeof(struct sockaddr_in)); + addr.sin_family = AF_INET; +#ifdef HAVE_SIN_LEN + addr.sin_len = sizeof(struct sockaddr_in); +#endif + addr.sin_addr.s_addr = INADDR_ANY; + addr.sin_port = htons(atoi(argv[3])); + if (usrsctp_bind(sock, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0) { + perror("bind"); + } + if (usrsctp_listen(sock, 1) < 0) { + perror("listen"); + } + addr_len = (socklen_t)sizeof(struct sockaddr_in); + memset(&addr, 0, sizeof(struct sockaddr_in)); + if ((conn_sock = usrsctp_accept(sock, (struct sockaddr *)&addr, &addr_len)) == NULL) { + perror("accept"); + } + usrsctp_close(sock); + sock = conn_sock; + printf("Connected to %s:%d.\n", inet_ntop(AF_INET, &(addr.sin_addr), addrbuf, INET_ADDRSTRLEN), ntohs(addr.sin_port)); + } else { + printf("Usage: %s local_udp_port remote_udp_port local_port when operating as server\n" + " %s local_udp_port remote_udp_port remote_addr remote_port when operating as client\n", + argv[0], argv[0]); + return (0); + } + + lock_peer_connection(&peer_connection); + peer_connection.sock = sock; + unlock_peer_connection(&peer_connection); + + for (;;) { +#ifdef _WIN32 + if (gets_s(line, LINE_LENGTH) == NULL) { +#else + if (fgets(line, LINE_LENGTH, stdin) == NULL) { +#endif + if (usrsctp_shutdown(sock, SHUT_WR) < 0) { + perror("usrsctp_shutdown"); + } + while (usrsctp_finish() != 0) { +#ifdef _WIN32 + Sleep(1000); +#else + sleep(1); +#endif + } + break; + } + if (strncmp(line, "?", strlen("?")) == 0 || + strncmp(line, "help", strlen("help")) == 0) { + printf("Commands:\n" + "open unordered pr_policy pr_value - opens a channel\n" + "close channel - closes the channel\n" + "send channel:string - sends string using channel\n" + "status - prints the status\n" + "sleep n - sleep for n seconds\n" + "help - this message\n"); + } else if (strncmp(line, "status", strlen("status")) == 0) { + lock_peer_connection(&peer_connection); + print_status(&peer_connection); + unlock_peer_connection(&peer_connection); + } else if (strncmp(line, "quit", strlen("quit")) == 0) { + if (usrsctp_shutdown(sock, SHUT_WR) < 0) { + perror("usrsctp_shutdown"); + } + while (usrsctp_finish() != 0) { +#ifdef _WIN32 + Sleep(1000); +#else + sleep(1); +#endif + } + break; + } else if (sscanf(line, "open %u %u %u", &unordered, &policy, &value) == 3) { + lock_peer_connection(&peer_connection); + channel = open_channel(&peer_connection, (uint8_t)unordered, (uint16_t)policy, (uint32_t)value); + unlock_peer_connection(&peer_connection); + if (channel == NULL) { + printf("Creating channel failed.\n"); + } else { + printf("Channel with id %u created.\n", channel->id); + } + } else if (sscanf(line, "close %u", &id) == 1) { + if (id < NUMBER_OF_CHANNELS) { + lock_peer_connection(&peer_connection); + close_channel(&peer_connection, &peer_connection.channels[id]); + unlock_peer_connection(&peer_connection); + } + } else if (sscanf(line, "send %u", &id) == 1) { + if (id < NUMBER_OF_CHANNELS) { + char *msg; + + msg = strstr(line, ":"); + if (msg) { + msg++; + lock_peer_connection(&peer_connection); +#ifdef _WIN32 + if (send_user_message(&peer_connection, &peer_connection.channels[id], msg, strlen(msg))) { +#else + if (send_user_message(&peer_connection, &peer_connection.channels[id], msg, strlen(msg) - 1)) { +#endif + printf("Message sent.\n"); + } else { + printf("Message sending failed.\n"); + } + unlock_peer_connection(&peer_connection); + } + } + } else if (sscanf(line, "sleep %u", &seconds) == 1) { +#ifdef _WIN32 + Sleep(seconds * 1000); +#else + sleep(seconds); +#endif + } else { + printf("Unknown command: %s", line); + } + } + return (0); +} diff --git a/chromium/third_party/usrsctp/usrsctplib/programs/tsctp.c b/chromium/third_party/usrsctp/usrsctplib/programs/tsctp.c new file mode 100644 index 00000000000..f7975712934 --- /dev/null +++ b/chromium/third_party/usrsctp/usrsctplib/programs/tsctp.c @@ -0,0 +1,827 @@ +/* + * Copyright (C) 2005-2013 Michael Tuexen + * Copyright (C) 2011-2013 Irene Ruengeler + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/types.h> +#ifdef _WIN32 +#include <WinSock2.h> +#include <WS2tcpip.h> +#include <stdlib.h> +#include <crtdbg.h> +#include <sys/timeb.h> +#else +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <sys/time.h> +#include <unistd.h> +#include <pthread.h> +#endif +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <signal.h> +#include <errno.h> +#ifdef LINUX +#include <getopt.h> +#endif +#include <usrsctp.h> + +/* global for the send callback, but used in kernel version as well */ +static unsigned long number_of_messages; +static char *buffer; +static int length; +static struct sockaddr_in remote_addr; +static int unordered; +uint32_t optval = 1; +struct socket *psock = NULL; + +static struct timeval start_time; +unsigned int runtime = 0; +static unsigned long messages = 0; +static unsigned int first_length = 0; +static unsigned long long sum = 0; +static unsigned int use_cb = 0; + +#ifndef timersub +#define timersub(tvp, uvp, vvp) \ + do { \ + (vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec; \ + (vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec; \ + if ((vvp)->tv_usec < 0) { \ + (vvp)->tv_sec--; \ + (vvp)->tv_usec += 1000000; \ + } \ + } while (0) +#endif + + +char Usage[] = +"Usage: tsctp [options] [address]\n" +"Options:\n" +" -a set adaptation layer indication\n" +" -c use callback API\n" +" -E local UDP encapsulation port (default 9899)\n" +" -f fragmentation point\n" +" -l size of send/receive buffer\n" +" -L bind to local IP (default INADDR_ANY)\n" +" -n number of messages sent (0 means infinite)/received\n" +" -D turns Nagle off\n" +" -R socket recv buffer\n" +" -S socket send buffer\n" +" -T time to send messages\n" +" -u use unordered user messages\n" +" -U remote UDP encapsulation port\n" +" -v verbose\n" +" -V very verbose\n" +; + +#define DEFAULT_LENGTH 1024 +#define DEFAULT_NUMBER_OF_MESSAGES 1024 +#define DEFAULT_PORT 5001 +#define BUFFERSIZE (1<<16) + +static int verbose, very_verbose; +static unsigned int done; + +void stop_sender(int sig) +{ + done = 1; +} + +#ifdef _WIN32 +static void +gettimeofday(struct timeval *tv, void *ignore) +{ + struct timeb tb; + + ftime(&tb); + tv->tv_sec = (long)tb.time; + tv->tv_usec = tb.millitm * 1000; +} +#endif + +#ifdef _WIN32 +static DWORD WINAPI +#else +static void * +#endif +handle_connection(void *arg) +{ + ssize_t n; + unsigned long long sum = 0, first_length = 0; + char *buf; +#ifdef _WIN32 + HANDLE tid; +#else + pthread_t tid; +#endif + struct socket *conn_sock; + struct timeval start_time, now, diff_time; + double seconds; + unsigned long messages = 0; + unsigned long recv_calls = 0; + unsigned long notifications = 0; + int flags; + struct sockaddr_in addr; + socklen_t len; + union sctp_notification *snp; + struct sctp_paddr_change *spc; + struct timeval note_time; + unsigned int infotype; + struct sctp_recvv_rn rn; + socklen_t infolen = sizeof(struct sctp_recvv_rn); + + conn_sock = *(struct socket **)arg; +#ifdef _WIN32 + tid = GetCurrentThread(); +#else + tid = pthread_self(); + pthread_detach(tid); +#endif + + buf = malloc(BUFFERSIZE); + flags = 0; + len = (socklen_t)sizeof(struct sockaddr_in); + infotype = 0; + memset(&rn, 0, sizeof(struct sctp_recvv_rn)); + n = usrsctp_recvv(conn_sock, buf, BUFFERSIZE, (struct sockaddr *) &addr, &len, (void *)&rn, + &infolen, &infotype, &flags); + + gettimeofday(&start_time, NULL); + while (n > 0) { + recv_calls++; + if (flags & MSG_NOTIFICATION) { + notifications++; + gettimeofday(¬e_time, NULL); + printf("notification arrived at %f\n", note_time.tv_sec+(double)note_time.tv_usec/1000000.0); + snp = (union sctp_notification *)buf; + if (snp->sn_header.sn_type==SCTP_PEER_ADDR_CHANGE) + { + spc = &snp->sn_paddr_change; + printf("SCTP_PEER_ADDR_CHANGE: state=%d, error=%d\n",spc->spc_state, spc->spc_error); + } + } else { + if (very_verbose) { + printf("Message received\n"); + } + sum += n; + if (flags & MSG_EOR) { + messages++; + if (first_length == 0) + first_length = sum; + } + } + flags = 0; + len = (socklen_t)sizeof(struct sockaddr_in); + infolen = sizeof(struct sctp_recvv_rn); + infotype = 0; + memset(&rn, 0, sizeof(struct sctp_recvv_rn)); + n = usrsctp_recvv(conn_sock, (void *) buf, BUFFERSIZE, (struct sockaddr *) &addr, &len, (void *)&rn, + &infolen, &infotype, &flags); + } + if (n < 0) + perror("sctp_recvv"); + gettimeofday(&now, NULL); + timersub(&now, &start_time, &diff_time); + seconds = diff_time.tv_sec + (double)diff_time.tv_usec/1000000.0; + printf("%llu, %lu, %lu, %lu, %llu, %f, %f\n", + first_length, messages, recv_calls, notifications, sum, seconds, (double)first_length * (double)messages / seconds); + fflush(stdout); + usrsctp_close(conn_sock); + free(buf); +#ifdef _WIN32 + return 0; +#else + return (NULL); +#endif +} + +static int +send_cb(struct socket *sock, uint32_t sb_free) { + struct sctp_sndinfo sndinfo; + + if ((messages == 0) & verbose) { + printf("Start sending "); + if (number_of_messages > 0) { + printf("%ld messages ", (long)number_of_messages); + } + if (runtime > 0) { + printf("for %u seconds ...", runtime); + } + printf("\n"); + fflush(stdout); + } + + sndinfo.snd_sid = 0; + sndinfo.snd_flags = 0; + if (unordered != 0) { + sndinfo.snd_flags |= SCTP_UNORDERED; + } + sndinfo.snd_ppid = 0; + sndinfo.snd_context = 0; + sndinfo.snd_assoc_id = 0; + + while (!done && ((number_of_messages == 0) || (messages < (number_of_messages - 1)))) { + if (very_verbose) { + printf("Sending message number %lu.\n", messages + 1); + } + + if (usrsctp_sendv(psock, buffer, length, + (struct sockaddr *) &remote_addr, 1, + (void *)&sndinfo, (socklen_t)sizeof(struct sctp_sndinfo), SCTP_SENDV_SNDINFO, + 0) < 0) { + if (errno != EWOULDBLOCK && errno != EAGAIN) { + perror("usrsctp_sendv (cb)"); + exit(1); + } else { + if (very_verbose){ + printf("EWOULDBLOCK or EAGAIN for message number %lu - will retry\n", messages + 1); + } + /* send until EWOULDBLOCK then exit callback. */ + return (1); + } + } + messages++; + } + if ((done == 1) || (messages == (number_of_messages - 1))) { + if (very_verbose) + printf("Sending final message number %lu.\n", messages + 1); + + sndinfo.snd_flags |= SCTP_EOF; + if (usrsctp_sendv(psock, buffer, length, (struct sockaddr *) &remote_addr, 1, + (void *)&sndinfo, (socklen_t)sizeof(struct sctp_sndinfo), SCTP_SENDV_SNDINFO, + 0) < 0) { + if (errno != EWOULDBLOCK && errno != EAGAIN) { + perror("usrsctp_sendv (cb)"); + exit(1); + } else { + if (very_verbose){ + printf("EWOULDBLOCK or EAGAIN for final message number %lu - will retry\n", messages + 1); + } + /* send until EWOULDBLOCK then exit callback. */ + return (1); + } + } + messages++; + done = 2; + } + + return (1); +} + +static int +server_receive_cb(struct socket *sock, union sctp_sockstore addr, void *data, + size_t datalen, struct sctp_rcvinfo rcv, int flags, void *ulp_info) +{ + struct timeval now, diff_time; + double seconds; + + if (data == NULL) { + gettimeofday(&now, NULL); + timersub(&now, &start_time, &diff_time); + seconds = diff_time.tv_sec + (double)diff_time.tv_usec/1000000.0; + printf("%u, %lu, %llu, %f, %f\n", + first_length, messages, sum, seconds, (double)first_length * (double)messages / seconds); + usrsctp_close(sock); + first_length = 0; + sum = 0; + messages = 0; + return (1); + } + if (first_length == 0) { + first_length = datalen; + gettimeofday(&start_time, NULL); + } + sum += datalen; + messages++; + + free(data); + return (1); +} + +static int +client_receive_cb(struct socket *sock, union sctp_sockstore addr, void *data, + size_t datalen, struct sctp_rcvinfo rcv, int flags, void *ulp_info) +{ + free(data); + return (1); +} + +void +debug_printf(const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + vprintf(format, ap); + va_end(ap); +} + +int main(int argc, char **argv) +{ +#ifndef _WIN32 + int c; +#endif + socklen_t addr_len; + struct sockaddr_in local_addr; + struct timeval start_time, now, diff_time; + int client; + uint16_t local_port, remote_port, port, local_udp_port, remote_udp_port; + int rcvbufsize=0, sndbufsize=0, myrcvbufsize, mysndbufsize; + socklen_t intlen; + double seconds; + double throughput; + int nodelay = 0; + struct sctp_assoc_value av; + struct sctp_udpencaps encaps; + struct sctp_sndinfo sndinfo; +#ifdef _WIN32 + unsigned long srcAddr; + HANDLE tid; +#else + in_addr_t srcAddr; + pthread_t tid; +#endif + int fragpoint = 0; + struct sctp_setadaptation ind = {0}; +#ifdef _WIN32 + char *opt; + int optind; +#endif + unordered = 0; + + length = DEFAULT_LENGTH; + number_of_messages = DEFAULT_NUMBER_OF_MESSAGES; + port = DEFAULT_PORT; + remote_udp_port = 0; + local_udp_port = 9899; + verbose = 0; + very_verbose = 0; + srcAddr = htonl(INADDR_ANY); + + memset((void *) &remote_addr, 0, sizeof(struct sockaddr_in)); + memset((void *) &local_addr, 0, sizeof(struct sockaddr_in)); + +#ifndef _WIN32 + while ((c = getopt(argc, argv, "a:cp:l:E:f:L:n:R:S:T:uU:vVD")) != -1) + switch(c) { + case 'a': + ind.ssb_adaptation_ind = atoi(optarg); + break; + case 'c': + use_cb = 1; + break; + case 'l': + length = atoi(optarg); + break; + case 'n': + number_of_messages = atoi(optarg); + break; + case 'p': + port = atoi(optarg); + break; + case 'E': + local_udp_port = atoi(optarg); + break; + case 'f': + fragpoint = atoi(optarg); + break; + case 'L': + inet_pton(AF_INET, optarg, &srcAddr); + break; + case 'R': + rcvbufsize = atoi(optarg); + break; + case 'S': + sndbufsize = atoi(optarg); + break; + case 'T': + runtime = atoi(optarg); + number_of_messages = 0; + break; + case 'u': + unordered = 1; + break; + case 'U': + remote_udp_port = atoi(optarg); + break; + case 'v': + verbose = 1; + break; + case 'V': + verbose = 1; + very_verbose = 1; + break; + case 'D': + nodelay = 1; + break; + default: + fprintf(stderr, "%s", Usage); + exit(1); + } +#else + for (optind = 1; optind < argc; optind++) { + if (argv[optind][0] == '-') { + switch (argv[optind][1]) { + case 'a': + if (++optind >= argc) { + printf("%s", Usage); + exit(1); + } + opt = argv[optind]; + ind.ssb_adaptation_ind = atoi(opt); + break; + case 'c': + use_cb = 1; + break; + case 'l': + if (++optind >= argc) { + printf("%s", Usage); + exit(1); + } + opt = argv[optind]; + length = atoi(opt); + break; + case 'p': + if (++optind >= argc) { + printf("%s", Usage); + exit(1); + } + opt = argv[optind]; + port = atoi(opt); + break; + case 'n': + if (++optind >= argc) { + printf("%s", Usage); + exit(1); + } + opt = argv[optind]; + number_of_messages = atoi(opt); + break; + case 'f': + if (++optind >= argc) { + printf("%s", Usage); + exit(1); + } + opt = argv[optind]; + fragpoint = atoi(opt); + break; + case 'L': + if (++optind >= argc) { + printf("%s", Usage); + exit(1); + } + opt = argv[optind]; + inet_pton(AF_INET, opt, &srcAddr); + break; + case 'U': + if (++optind >= argc) { + printf("%s", Usage); + exit(1); + } + opt = argv[optind]; + remote_udp_port = atoi(opt); + break; + case 'E': + if (++optind >= argc) { + printf("%s", Usage); + exit(1); + } + opt = argv[optind]; + local_udp_port = atoi(opt); + break; + case 'R': + if (++optind >= argc) { + printf("%s", Usage); + exit(1); + } + opt = argv[optind]; + rcvbufsize = atoi(opt); + break; + case 'S': + if (++optind >= argc) { + printf("%s", Usage); + exit(1); + } + opt = argv[optind]; + sndbufsize = atoi(opt); + break; + case 'T': + if (++optind >= argc) { + printf("%s", Usage); + exit(1); + } + opt = argv[optind]; + runtime = atoi(opt); + number_of_messages = 0; + break; + case 'u': + unordered = 1; + break; + case 'v': + verbose = 1; + break; + case 'V': + verbose = 1; + very_verbose = 1; + break; + case 'D': + nodelay = 1; + break; + default: + printf("%s", Usage); + exit(1); + } + } else { + break; + } + } +#endif + if (optind == argc) { + client = 0; + local_port = port; + remote_port = 0; + } else { + client = 1; + local_port = 0; + remote_port = port; + } + local_addr.sin_family = AF_INET; +#ifdef HAVE_SIN_LEN + local_addr.sin_len = sizeof(struct sockaddr_in); +#endif + local_addr.sin_port = htons(local_port); + local_addr.sin_addr.s_addr = srcAddr; + + usrsctp_init(local_udp_port, NULL, debug_printf); +#ifdef SCTP_DEBUG + usrsctp_sysctl_set_sctp_debug_on(SCTP_DEBUG_ALL); +#endif + usrsctp_sysctl_set_sctp_blackhole(2); + usrsctp_sysctl_set_sctp_enable_sack_immediately(1); + + if (client) { + if (use_cb) { + if (!(psock = usrsctp_socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP, client_receive_cb, send_cb, length, NULL))) { + perror("user_socket"); + exit(1); + } + } else { + if (!(psock = usrsctp_socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP, NULL, NULL, 0, NULL))) { + perror("user_socket"); + exit(1); + } + } + } else { + if (use_cb) { + if (!(psock = usrsctp_socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP, server_receive_cb, NULL, 0, NULL))) { + perror("user_socket"); + exit(1); + } + } else { + if (!(psock = usrsctp_socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP, NULL, NULL, 0, NULL))) { + perror("user_socket"); + exit(1); + } + } + } + + if (usrsctp_bind(psock, (struct sockaddr *)&local_addr, sizeof(struct sockaddr_in)) == -1) { + perror("usrsctp_bind"); + exit(1); + } + + if (usrsctp_setsockopt(psock, IPPROTO_SCTP, SCTP_ADAPTATION_LAYER, (const void*)&ind, (socklen_t)sizeof(struct sctp_setadaptation)) < 0) { + perror("setsockopt"); + } + + if (!client) { + if (rcvbufsize) { + if (usrsctp_setsockopt(psock, SOL_SOCKET, SO_RCVBUF, &rcvbufsize, sizeof(int)) < 0) { + perror("setsockopt: rcvbuf"); + } + } + if (verbose) { + intlen = sizeof(int); + if (usrsctp_getsockopt(psock, SOL_SOCKET, SO_RCVBUF, &myrcvbufsize, (socklen_t *)&intlen) < 0) { + perror("getsockopt: rcvbuf"); + } else { + fprintf(stdout,"Receive buffer size: %d.\n", myrcvbufsize); + } + } + + if (usrsctp_listen(psock, 1) < 0) { + perror("usrsctp_listen"); + exit(1); + } + + while (1) { + memset(&remote_addr, 0, sizeof(struct sockaddr_in)); + addr_len = sizeof(struct sockaddr_in); + if (use_cb) { + struct socket *conn_sock; + + if ((conn_sock = usrsctp_accept(psock, (struct sockaddr *) &remote_addr, &addr_len))== NULL) { + perror("usrsctp_accept"); + continue; + } + } else { + struct socket **conn_sock; + + conn_sock = (struct socket **)malloc(sizeof(struct socket *)); + if ((*conn_sock = usrsctp_accept(psock, (struct sockaddr *) &remote_addr, &addr_len))== NULL) { + perror("usrsctp_accept"); + continue; + } +#ifdef _WIN32 + tid = CreateThread(NULL, 0, &handle_connection, (void *)conn_sock, 0, NULL); +#else + pthread_create(&tid, NULL, &handle_connection, (void *)conn_sock); +#endif + } + if (verbose) { + // const char *inet_ntop(int af, const void *src, char *dst, socklen_t size) + //inet_ntoa(remote_addr.sin_addr) + char addrbuf[INET_ADDRSTRLEN]; + printf("Connection accepted from %s:%d\n", inet_ntop(AF_INET, &(remote_addr.sin_addr), addrbuf, INET_ADDRSTRLEN), ntohs(remote_addr.sin_port)); + } + } + usrsctp_close(psock); + } else { + memset(&encaps, 0, sizeof(struct sctp_udpencaps)); + encaps.sue_address.ss_family = AF_INET; + encaps.sue_port = htons(remote_udp_port); + if (usrsctp_setsockopt(psock, IPPROTO_SCTP, SCTP_REMOTE_UDP_ENCAPS_PORT, (const void*)&encaps, (socklen_t)sizeof(struct sctp_udpencaps)) < 0) { + perror("setsockopt"); + } + + remote_addr.sin_family = AF_INET; +#ifdef HAVE_SIN_LEN + remote_addr.sin_len = sizeof(struct sockaddr_in); +#endif + if (!inet_pton(AF_INET, argv[optind], &remote_addr.sin_addr.s_addr)){ + printf("error: invalid destination address\n"); + exit(1); + } + remote_addr.sin_port = htons(remote_port); + + /* TODO fragpoint stuff */ + if (nodelay == 1) { + optval = 1; + } else { + optval = 0; + } + usrsctp_setsockopt(psock, IPPROTO_SCTP, SCTP_NODELAY, &optval, sizeof(int)); + + if (fragpoint) { + av.assoc_id = 0; + av.assoc_value = fragpoint; + if (usrsctp_setsockopt(psock, IPPROTO_SCTP, SCTP_MAXSEG, &av, sizeof(struct sctp_assoc_value)) < 0) { + perror("setsockopt: SCTP_MAXSEG"); + } + } + + if (sndbufsize) { + if (usrsctp_setsockopt(psock, SOL_SOCKET, SO_SNDBUF, &sndbufsize, sizeof(int)) < 0) { + perror("setsockopt: sndbuf"); + } + } + if (verbose) { + intlen = sizeof(int); + if (usrsctp_getsockopt(psock, SOL_SOCKET, SO_SNDBUF, &mysndbufsize, (socklen_t *)&intlen) < 0) { + perror("setsockopt: SO_SNDBUF"); + } else { + fprintf(stdout,"Send buffer size: %d.\n", mysndbufsize); + } + } + + buffer = malloc(length); + memset(buffer, 'b', length); + + if (usrsctp_connect(psock, (struct sockaddr *) &remote_addr, sizeof(struct sockaddr_in)) == -1 ) { + perror("usrsctp_connect"); + exit(1); + } + + gettimeofday(&start_time, NULL); + + done = 0; + + if (runtime > 0) { +#ifndef _WIN32 + signal(SIGALRM, stop_sender); + alarm(runtime); +#else + printf("You cannot set the runtime in Windows yet\n"); + exit(-1); +#endif + } + + if (use_cb) { + while (!done && (messages < (number_of_messages - 1))) { +#ifdef _WIN32 + Sleep(1000); +#else + sleep(1); +#endif + } + } else { + sndinfo.snd_sid = 0; + sndinfo.snd_flags = 0; + if (unordered != 0) { + sndinfo.snd_flags |= SCTP_UNORDERED; + } + sndinfo.snd_ppid = 0; + sndinfo.snd_context = 0; + sndinfo.snd_assoc_id = 0; + if (verbose) { + printf("Start sending "); + if (number_of_messages > 0) { + printf("%ld messages ", (long)number_of_messages); + } + if (runtime > 0) { + printf("for %u seconds ...", runtime); + } + printf("\n"); + fflush(stdout); + } + while (!done && ((number_of_messages == 0) || (messages < (number_of_messages - 1)))) { + if (very_verbose) { + printf("Sending message number %lu.\n", messages + 1); + } + + if (usrsctp_sendv(psock, buffer, length, (struct sockaddr *) &remote_addr, 1, + (void *)&sndinfo, (socklen_t)sizeof(struct sctp_sndinfo), SCTP_SENDV_SNDINFO, + 0) < 0) { + perror("usrsctp_sendv"); + exit(1); + } + messages++; + } + if (very_verbose) { + printf("Sending message number %lu.\n", messages + 1); + } + + sndinfo.snd_flags |= SCTP_EOF; + if (usrsctp_sendv(psock, buffer, length, (struct sockaddr *) &remote_addr, 1, + (void *)&sndinfo, (socklen_t)sizeof(struct sctp_sndinfo), SCTP_SENDV_SNDINFO, + 0) < 0) { + perror("usrsctp_sendv"); + exit(1); + } + messages++; + } + free (buffer); + + if (verbose) { + printf("Closing socket.\n"); + } + + usrsctp_close(psock); + gettimeofday(&now, NULL); + timersub(&now, &start_time, &diff_time); + seconds = diff_time.tv_sec + (double)diff_time.tv_usec/1000000; + printf("%s of %ld messages of length %u took %f seconds.\n", + "Sending", messages, length, seconds); + throughput = (double)messages * (double)length / seconds; + printf("Throughput was %f Byte/sec.\n", throughput); + } + + while (usrsctp_finish() != 0) { +#ifdef _WIN32 + Sleep(1000); +#else + sleep(1); +#endif + } + return 0; +} diff --git a/chromium/third_party/usrsctp/usrsctplib/usrsctplib/CMakeLists.txt b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/CMakeLists.txt new file mode 100644 index 00000000000..e6d5d221925 --- /dev/null +++ b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/CMakeLists.txt @@ -0,0 +1,281 @@ +# +# Copyright (C) 2015-2015 Oleg Alexeenkov +# Copyright (C) 2015-2015 Felix Weinrank +# +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the project nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# + +cmake_minimum_required(VERSION 2.6) +message(">> WARNINING: CMAKE SUPPORT IS EXPERIMENTAL <<") + +project(usrsctplib) + +################################################# +# INCLUDE MODULES +################################################# + +include(CheckFunctionExists) +include(CheckStructHasMember) +include(CheckIncludeFile) +include(CMakePushCheckState) +include(CheckTypeSize) + +SET (VERSION "1.0.0") + +SET (prefix ${CMAKE_INSTALL_PREFIX}) +SET (exec_prefix "\${prefix}") +SET (libdir "\${exec_prefix}/lib") +SET (includedir "\${prefix}/include/usrsctp") + + +#include_directories(netinet netinet6) + +################################################# +# CHECK FOR TYPES AND FUNCTIONS +################################################# + +check_type_size("size_t" HAVE_SIZE_T) +check_type_size("ssize_t" HAVE_SSIZE_T) + +check_include_file(sys/socket.h HAVE_SYS_SOCKET_H) +check_include_file(sys/types.h HAVE_SYS_TYPES_H) +check_include_file(sys/queue.h HAVE_SYS_QUEUE_H) +check_include_file(linux/if_addr.h HAVE_LINUX_IF_ADDR_H) +check_include_file(linux/rtnetlink.h HAVE_LINUX_RTNETLINK_H) +check_include_file(netinet/ip_icmp.h HAVE_NETINET_IP_ICMP_H) + +check_function_exists("socket" HAVE_SOCKET) +check_function_exists("inet_addr" HAVE_INET_ADDR) + + +add_definitions(-D__Userspace__) +add_definitions(-D__Userspace_os_${CMAKE_SYSTEM_NAME}) +add_definitions(-D_GNU_SOURCE) + +################################################# +# CHECK STRUCT MEMBERS +################################################# + +check_struct_has_member("struct sockaddr" "sa_len" "sys/types.h;sys/socket.h" HAVE_SA_LEN) +if(HAVE_SA_LEN) + message("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("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("HAVE_SIN6_LEN") + add_definitions(-DHAVE_SIN6_LEN) +endif() + + +################################################# +# OS DEPENDENT +################################################# + +if (${CMAKE_SYSTEM_NAME} MATCHES "Linux") + add_definitions(-D_GNU_SOURCE) +endif() + +if (${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") + add_definitions(-U__FreeBSD__) + add_definitions(-DHAVE_SCONN_LEN) +endif() + +if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + add_definitions(-DHAVE_SCONN_LEN) + add_definitions(-U__APPLE__) + add_definitions(-D__APPLE_USE_RFC_2292) +endif() + +if (${CMAKE_SYSTEM_NAME} MATCHES "DragonFly") + add_definitions(-U__DragonFly__) +endif() + +if (${CMAKE_SYSTEM_NAME} MATCHES "NetBSD") + add_definitions(-U__NetBSD__) +endif() + +if (${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD") + add_definitions(-DHAVE_SCONN_LEN) + add_definitions(-U__OpenBSD__) +endif() + + +################################################# +# CHECK OPTIONS +################################################# + +option(INVARIANTS "Add runtime checks" 0) +if (INVARIANTS) + add_definitions(-DINVARIANTS) +endif() + +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) +endif() + +option(INET6 "Support IPv6 " 1) +if (INET6) + add_definitions(-DINET6) +endif() + +option(SCTP_SIMPLE_ALLOCATOR " " 1) +if (SCTP_SIMPLE_ALLOCATOR) + add_definitions(-DSCTP_SIMPLE_ALLOCATOR) +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" ON) + +include_directories(${PROJECT_SOURCE_DIR} ${PROJECT_SOURCE_DIR}/netinet ${PROJECT_SOURCE_DIR}/netinet6) + +LIST (APPEND usrsctp_root_HEADERS +user_atomic.h user_inpcb.h user_ip_icmp.h user_mbuf.h user_recv_thread.h user_socketvar.h usrsctp.h +user_environment.h user_ip6_var.h user_malloc.h user_queue.h user_route.h user_uma.h +) + +LIST (APPEND usrsctp_netinet_HEADERS +netinet/sctp_asconf.h netinet/sctp_constants.h netinet/sctp_indata.h netinet/sctp_os_userspace.h netinet/sctp_process_lock.h netinet/sctp_timer.h +netinet/sctp_auth.h netinet/sctp_crc32.h netinet/sctp_input.h netinet/sctp_output.h netinet/sctp_sha1.h netinet/sctp_uio.h +netinet/sctp_bsd_addr.h netinet/sctp.h netinet/sctp_lock_userspace.h netinet/sctp_pcb.h netinet/sctp_structs.h netinet/sctputil.h +netinet/sctp_callout.h netinet/sctp_header.h netinet/sctp_os.h netinet/sctp_peeloff.h netinet/sctp_sysctl.h netinet/sctp_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_SOURCES +netinet6/sctp6_usrreq.c netinet/sctp_callout.c netinet/sctp_input.c netinet/sctp_sha1.c netinet/sctp_userspace.c user_mbuf.c +netinet/sctp_asconf.c netinet/sctp_cc_functions.c netinet/sctp_output.c netinet/sctp_ss_functions.c netinet/sctp_usrreq.c user_recv_thread.c +netinet/sctp_auth.c netinet/sctp_crc32.c netinet/sctp_pcb.c netinet/sctp_sysctl.c netinet/sctputil.c user_socket.c +netinet/sctp_bsd_addr.c netinet/sctp_indata.c netinet/sctp_peeloff.c netinet/sctp_timer.c user_environment.c +) + +add_library(usrsctp SHARED ${usrsctp_SOURCES} ${usrsctp_HEADERS}) +add_library(usrsctp-static STATIC ${usrsctp_SOURCES} ${usrsctp_HEADERS}) + +if(WIN32) + message("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") +SET_TARGET_PROPERTIES (usrsctp PROPERTIES IMPORT_SUFFIX "_import.lib") +SET_TARGET_PROPERTIES (usrsctp PROPERTIES SOVERSION 1 VERSION 1.0.0) + +IF ("x${CMAKE_C_COMPILER_ID}" STREQUAL "xClang" OR "x${CMAKE_C_COMPILER_ID}" STREQUAL "xGNU") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -pedantic -Wall -std=c99") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -pedantic -Wall -std=c99") + if (WERROR) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror") + endif() + MESSAGE(STATUS "COMPILE FLAGS: ${CMAKE_C_FLAGS}") + #SET_PROPERTY (TARGET usrsctp APPEND_STRING PROPERTY COMPILE_FLAGS "-g -pedantic -Wall -Werror -std=c99") + #SET_PROPERTY (TARGET usrsctp-static APPEND_STRING PROPERTY COMPILE_FLAGS "-g -pedantic -Wall -Werror -std=c99") +ENDIF () +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 (WERROR) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /WX") + endif() +ENDIF () + +IF ("x${CMAKE_C_COMPILER_ID}" STREQUAL "xMSVC90" OR "x${CMAKE_C_COMPILER_ID}" STREQUAL "xMSVC10") + SET_SOURCE_FILES_PROPERTIES(${usrsctp_SOURCES} PROPERTIES LANGUAGE C) +ENDIF() + +IF (NOT DEFINED CMAKE_INSTALL_LIBDIR) + SET(CMAKE_INSTALL_LIBDIR lib) +ENDIF () + + +################################################# +# INSTALL LIBRARY AND HEADER +################################################# + +INSTALL (TARGETS usrsctp usrsctp-static DESTINATION ${CMAKE_INSTALL_LIBDIR}) +INSTALL (FILES usrsctp.h DESTINATION include) diff --git a/chromium/third_party/usrsctp/usrsctplib/usrsctplib/Makefile.am b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/Makefile.am new file mode 100644 index 00000000000..85240b7cea8 --- /dev/null +++ b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/Makefile.am @@ -0,0 +1,81 @@ +# +# Copyright (C) 2011-2012 Michael Tuexen +# +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the project nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# + +AUTOMAKE_OPTIONS = subdir-objects +EXTRA_DIST = Makefile.nmake +lib_LTLIBRARIES = libusrsctp.la +libusrsctp_la_SOURCES = user_atomic.h \ + user_environment.c user_environment.h \ + user_inpcb.h \ + user_ip_icmp.h \ + user_ip6_var.h \ + user_malloc.h \ + user_mbuf.c \ + user_mbuf.h \ + user_queue.h \ + user_recv_thread.c user_recv_thread.h \ + user_route.h \ + user_socket.c \ + user_socketvar.h \ + user_uma.h \ + netinet/sctp.h \ + netinet/sctp_asconf.c netinet/sctp_asconf.h \ + netinet/sctp_auth.c netinet/sctp_auth.h \ + netinet/sctp_bsd_addr.c netinet/sctp_bsd_addr.h \ + netinet/sctp_callout.c netinet/sctp_callout.h \ + netinet/sctp_cc_functions.c \ + netinet/sctp_constants.h \ + netinet/sctp_crc32.c netinet/sctp_crc32.h \ + netinet/sctp_header.h \ + netinet/sctp_indata.c netinet/sctp_indata.h \ + netinet/sctp_input.c netinet/sctp_input.h \ + netinet/sctp_lock_userspace.h \ + netinet/sctp_os.h \ + netinet/sctp_os_userspace.h \ + netinet/sctp_output.c netinet/sctp_output.h \ + netinet/sctp_pcb.c netinet/sctp_pcb.h \ + netinet/sctp_peeloff.c netinet/sctp_peeloff.h \ + netinet/sctp_process_lock.h \ + netinet/sctp_sha1.c netinet/sctp_sha1.h \ + netinet/sctp_ss_functions.c \ + netinet/sctp_structs.h \ + netinet/sctp_sysctl.c netinet/sctp_sysctl.h \ + netinet/sctp_userspace.c \ + netinet/sctp_timer.c netinet/sctp_timer.h \ + netinet/sctp_uio.h \ + netinet/sctp_usrreq.c \ + netinet/sctp_var.h \ + netinet/sctputil.c netinet/sctputil.h \ + netinet6/sctp6_var.h \ + netinet6/sctp6_usrreq.c +libusrsctp_la_CFLAGS = $(LIBCFLAGS) +libusrsctp_la_LDFLAGS = -version-info 1:0:0 +include_HEADERS = usrsctp.h + diff --git a/chromium/third_party/usrsctp/usrsctplib/usrsctplib/Makefile.nmake b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/Makefile.nmake new file mode 100644 index 00000000000..e16dc1e7875 --- /dev/null +++ b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/Makefile.nmake @@ -0,0 +1,179 @@ +# +# Copyright (C) 2011-2012 Michael Tuexen +# +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the project nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# + +CFLAGS=/I. /W3 /WX + +CVARSDLL=-DSCTP_DEBUG -DSCTP_SIMPLE_ALLOCATOR -DSCTP_PROCESS_LEVEL_LOCKS +CVARSDLL=$(CVARSDLL) -D__Userspace__ -D__Userspace_os_Windows +CVARSDLL=$(CVARSDLL) -DINET -DINET6 +CVARSDLL=$(CVARSDLL) -D_LIB + +LINKFLAGS=/LIBPATH:. Ws2_32.lib + +usrsctp_OBJECTS = \ + user_environment.obj \ + user_mbuf.obj \ + user_recv_thread.obj \ + user_socket.obj \ + sctp_asconf.obj \ + sctp_auth.obj \ + sctp_bsd_addr.obj \ + sctp_callout.obj \ + sctp_cc_functions.obj \ + sctp_crc32.obj \ + sctp_indata.obj \ + sctp_input.obj \ + sctp_output.obj \ + sctp_pcb.obj \ + sctp_peeloff.obj \ + sctp_sha1.obj \ + sctp_ss_functions.obj \ + sctp_sysctl.obj \ + sctp_timer.obj \ + sctp_userspace.obj \ + sctp_usrreq.obj \ + sctputil.obj \ + sctp6_usrreq.obj + +usrsctp_HEADERS = \ + user_atomic.h \ + user_environment.h \ + user_inpcb.h \ + user_ip6_var.h \ + user_malloc.h \ + user_mbuf.h \ + user_recv_thread.h \ + user_route.h \ + user_socketvar.h \ + user_uma.h \ + user_queue.h \ + user_ip_icmp.h \ + user_ip6_var.h \ + netinet\sctp.h \ + 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.h \ + netinet\sctp_os_userspace.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 \ + netinet6\sctp6_var.h + +usrsctp.lib : $(usrsctp_OBJECTS) + lib /out:usrsctp.lib $(LINKFLAGS) $(usrsctp_OBJECTS) + +user_environment.obj : user_environment.c $(usrsctp_HEADERS) + cl $(CVARSDLL) $(CFLAGS) -c user_environment.c + +user_mbuf.obj : user_mbuf.c $(usrsctp_HEADERS) + cl $(CVARSDLL) $(CFLAGS) -c user_mbuf.c + +user_recv_thread.obj: user_recv_thread.c $(usrsctp_HEADERS) + cl $(CVARSDLL) $(CFLAGS) -c user_recv_thread.c + +user_socket.obj : user_socket.c $(usrsctp_HEADERS) + cl $(CVARSDLL) $(CFLAGS) -c user_socket.c + +sctp_asconf.obj : netinet\sctp_asconf.c $(usrsctp_HEADERS) + cl $(CVARSDLL) $(CFLAGS) -c netinet\sctp_asconf.c + +sctp_auth.obj : netinet\sctp_auth.c $(usrsctp_HEADERS) + cl $(CVARSDLL) $(CFLAGS) -c netinet\sctp_auth.c + +sctp_bsd_addr.obj : netinet\sctp_bsd_addr.c $(usrsctp_HEADERS) + cl $(CVARSDLL) $(CFLAGS) -c netinet\sctp_bsd_addr.c + +sctp_callout.obj : netinet\sctp_callout.c $(usrsctp_HEADERS) + cl $(CVARSDLL) $(CFLAGS) -c netinet\sctp_callout.c + +sctp_cc_functions.obj : netinet\sctp_cc_functions.c $(usrsctp_HEADERS) + cl $(CVARSDLL) $(CFLAGS) -c netinet\sctp_cc_functions.c + +sctp_crc32.obj : netinet\sctp_crc32.c $(usrsctp_HEADERS) + cl $(CVARSDLL) $(CFLAGS) -c netinet\sctp_crc32.c + +sctp_indata.obj : netinet\sctp_indata.c $(usrsctp_HEADERS) + cl $(CVARSDLL) $(CFLAGS) -c netinet\sctp_indata.c + +sctp_input.obj : netinet\sctp_input.c $(usrsctp_HEADERS) + cl $(CVARSDLL) $(CFLAGS) -c netinet\sctp_input.c + +sctp_output.obj : netinet\sctp_output.c $(usrsctp_HEADERS) + cl $(CVARSDLL) $(CFLAGS) -c netinet\sctp_output.c + +sctp_pcb.obj : netinet\sctp_pcb.c $(usrsctp_HEADERS) + cl $(CVARSDLL) $(CFLAGS) -c netinet\sctp_pcb.c + +sctp_peeloff.obj : netinet\sctp_peeloff.c $(usrsctp_HEADERS) + cl $(CVARSDLL) $(CFLAGS) -c netinet\sctp_peeloff.c + +sctp_sha1.obj : netinet\sctp_sha1.c $(usrsctp_HEADERS) + cl $(CVARSDLL) $(CFLAGS) -c netinet\sctp_sha1.c + +sctp_ss_functions.obj : netinet\sctp_ss_functions.c $(usrsctp_HEADERS) + cl $(CVARSDLL) $(CFLAGS) -c netinet\sctp_ss_functions.c + +sctp_sysctl.obj : netinet\sctp_sysctl.c $(usrsctp_HEADERS) + cl $(CVARSDLL) $(CFLAGS) -c netinet\sctp_sysctl.c + +sctp_timer.obj : netinet\sctp_timer.c $(usrsctp_HEADERS) + cl $(CVARSDLL) $(CFLAGS) -c netinet\sctp_timer.c + +sctp_userspace.obj : netinet\sctp_userspace.c $(usrsctp_HEADERS) + cl $(CVARSDLL) $(CFLAGS) -c netinet\sctp_userspace.c + +sctp_usrreq.obj : netinet\sctp_usrreq.c $(usrsctp_HEADERS) + cl $(CVARSDLL) $(CFLAGS) -c netinet\sctp_usrreq.c + +sctputil.obj : netinet\sctputil.c $(usrsctp_HEADERS) + cl $(CVARSDLL) $(CFLAGS) -c netinet\sctputil.c + +sctp6_usrreq.obj : netinet6\sctp6_usrreq.c $(usrsctp_HEADERS) + cl $(CVARSDLL) $(CFLAGS) -c netinet6\sctp6_usrreq.c + +clean: + del *.obj + del usrsctp.lib diff --git a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp.h b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp.h index a5ff4eb0bc5..6a24b77d21c 100755 --- a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp.h +++ b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp.h @@ -32,7 +32,7 @@ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp.h 279859 2015-03-10 19:49:25Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp.h 287717 2015-09-12 17:08:51Z tuexen $"); #endif #ifndef _NETINET_SCTP_H_ @@ -402,33 +402,32 @@ struct sctp_error_cause { } SCTP_PACKED; struct sctp_error_invalid_stream { - struct sctp_error_cause cause; /* code=SCTP_ERROR_INVALID_STREAM */ + struct sctp_error_cause cause; /* code=SCTP_CAUSE_INVALID_STREAM */ uint16_t stream_id; /* stream id of the DATA in error */ uint16_t reserved; } SCTP_PACKED; struct sctp_error_missing_param { - struct sctp_error_cause cause; /* code=SCTP_ERROR_MISSING_PARAM */ + struct sctp_error_cause cause; /* code=SCTP_CAUSE_MISSING_PARAM */ uint32_t num_missing_params; /* number of missing parameters */ - /* uint16_t param_type's follow */ + uint16_t type[]; } SCTP_PACKED; struct sctp_error_stale_cookie { - struct sctp_error_cause cause; /* code=SCTP_ERROR_STALE_COOKIE */ + struct sctp_error_cause cause; /* code=SCTP_CAUSE_STALE_COOKIE */ uint32_t stale_time; /* time in usec of staleness */ } SCTP_PACKED; struct sctp_error_out_of_resource { - struct sctp_error_cause cause; /* code=SCTP_ERROR_OUT_OF_RESOURCES */ + struct sctp_error_cause cause; /* code=SCTP_CAUSE_OUT_OF_RESOURCES */ } SCTP_PACKED; struct sctp_error_unresolv_addr { - struct sctp_error_cause cause; /* code=SCTP_ERROR_UNRESOLVABLE_ADDR */ - + struct sctp_error_cause cause; /* code=SCTP_CAUSE_UNRESOLVABLE_ADDR */ } SCTP_PACKED; struct sctp_error_unrecognized_chunk { - struct sctp_error_cause cause; /* code=SCTP_ERROR_UNRECOG_CHUNK */ + struct sctp_error_cause cause; /* code=SCTP_CAUSE_UNRECOG_CHUNK */ struct sctp_chunkhdr ch;/* header from chunk in error */ } SCTP_PACKED; @@ -437,6 +436,11 @@ struct sctp_error_no_user_data { uint32_t tsn; /* TSN of the empty data chunk */ } SCTP_PACKED; +struct sctp_error_auth_invalid_hmac { + struct sctp_error_cause cause; /* code=SCTP_CAUSE_UNSUPPORTED_HMACID */ + uint16_t hmac_id; +} SCTP_PACKED; + /* * Main SCTP chunk types we place these here so natd and f/w's in user land * can find them. diff --git a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_asconf.c b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_asconf.c index 438879885e7..3b75e90d893 100755 --- a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_asconf.c +++ b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_asconf.c @@ -32,7 +32,7 @@ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_asconf.c 277347 2015-01-18 20:53:20Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp_asconf.c 285925 2015-07-27 22:35:54Z tuexen $"); #endif #include <netinet/sctp_os.h> @@ -560,7 +560,9 @@ sctp_process_asconf_set_primary(struct sockaddr *src, (stcb->asoc.primary_destination->dest_state & SCTP_ADDR_UNCONFIRMED) == 0) { - sctp_timer_stop(SCTP_TIMER_TYPE_PRIM_DELETED, stcb->sctp_ep, stcb, NULL, SCTP_FROM_SCTP_TIMER+SCTP_LOC_7); + sctp_timer_stop(SCTP_TIMER_TYPE_PRIM_DELETED, + stcb->sctp_ep, stcb, NULL, + SCTP_FROM_SCTP_ASCONF + SCTP_LOC_1); if (sctp_is_mobility_feature_on(stcb->sctp_ep, SCTP_MOBILITY_FASTHANDOFF)) { sctp_assoc_immediate_retrans(stcb, @@ -930,7 +932,7 @@ sctp_asconf_cleanup(struct sctp_tcb *stcb, struct sctp_nets *net) * clear out any existing asconfs going out */ sctp_timer_stop(SCTP_TIMER_TYPE_ASCONF, stcb->sctp_ep, stcb, net, - SCTP_FROM_SCTP_ASCONF+SCTP_LOC_2); + SCTP_FROM_SCTP_ASCONF + SCTP_LOC_2); stcb->asoc.asconf_seq_out_acked = stcb->asoc.asconf_seq_out; /* remove the old ASCONF on our outbound queue */ sctp_toss_old_asconf(stcb); @@ -998,7 +1000,7 @@ sctp_assoc_immediate_retrans(struct sctp_tcb *stcb, struct sctp_nets *dstnet) SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, &stcb->asoc.primary_destination->ro._l_addr.sa); sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, stcb->asoc.deleted_primary, - SCTP_FROM_SCTP_TIMER+SCTP_LOC_8); + SCTP_FROM_SCTP_ASCONF + SCTP_LOC_3); stcb->asoc.num_send_timers_up--; if (stcb->asoc.num_send_timers_up < 0) { stcb->asoc.num_send_timers_up = 0; @@ -1038,7 +1040,7 @@ sctp_net_immediate_retrans(struct sctp_tcb *stcb, struct sctp_nets *net) SCTPDBG(SCTP_DEBUG_ASCONF1, "net_immediate_retrans: RTO is %d\n", net->RTO); sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, net, - SCTP_FROM_SCTP_TIMER+SCTP_LOC_5); + SCTP_FROM_SCTP_ASCONF + SCTP_LOC_4); stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb, net); net->error_count = 0; TAILQ_FOREACH(chk, &stcb->asoc.sent_queue, sctp_next) { @@ -1114,7 +1116,8 @@ sctp_path_check_and_react(struct sctp_tcb *stcb, struct sctp_ifa *newifa) nexthop, the path will not be changed. */ SCTP_RTALLOC((sctp_route_t *)&net->ro, - stcb->sctp_ep->def_vrf_id); + stcb->sctp_ep->def_vrf_id, + stcb->sctp_ep->fibnum); if (net->ro.ro_rt == NULL) continue; @@ -1334,6 +1337,7 @@ sctp_asconf_queue_add(struct sctp_tcb *stcb, struct sctp_ifa *ifa, { uint32_t status; int pending_delete_queued = 0; + int last; /* see if peer supports ASCONF */ if (stcb->asoc.asconf_supported == 0) { @@ -1344,15 +1348,21 @@ sctp_asconf_queue_add(struct sctp_tcb *stcb, struct sctp_ifa *ifa, * if this is deleting the last address from the assoc, mark it as * pending. */ - if ((type == SCTP_DEL_IP_ADDRESS) && !stcb->asoc.asconf_del_pending && - (sctp_local_addr_count(stcb) < 2)) { - /* set the pending delete info only */ - stcb->asoc.asconf_del_pending = 1; - stcb->asoc.asconf_addr_del_pending = ifa; - atomic_add_int(&ifa->refcount, 1); - SCTPDBG(SCTP_DEBUG_ASCONF2, - "asconf_queue_add: mark delete last address pending\n"); - return (-1); + if ((type == SCTP_DEL_IP_ADDRESS) && !stcb->asoc.asconf_del_pending) { + if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) { + last = (sctp_local_addr_count(stcb) == 0); + } else { + last = (sctp_local_addr_count(stcb) == 1); + } + if (last) { + /* set the pending delete info only */ + stcb->asoc.asconf_del_pending = 1; + stcb->asoc.asconf_addr_del_pending = ifa; + atomic_add_int(&ifa->refcount, 1); + SCTPDBG(SCTP_DEBUG_ASCONF2, + "asconf_queue_add: mark delete last address pending\n"); + return (-1); + } } /* queue an asconf parameter */ @@ -1637,7 +1647,7 @@ sctp_asconf_ack_clear(struct sctp_tcb *stcb SCTP_UNUSED) { /* assume peer doesn't really know how to do asconfs */ /* XXX we could free the pending queue here */ - + } void @@ -1680,8 +1690,14 @@ sctp_handle_asconf_ack(struct mbuf *m, int offset, * abort the asoc, since someone probably just hijacked us... */ if (serial_num == (asoc->asconf_seq_out + 1)) { + struct mbuf *op_err; + char msg[SCTP_DIAG_INFO_LEN]; + SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf_ack: got unexpected next serial number! Aborting asoc!\n"); - sctp_abort_an_association(stcb->sctp_ep, stcb, NULL, SCTP_SO_NOT_LOCKED); + snprintf(msg, sizeof(msg), "Never sent serial number %8.8x", + serial_num); + op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); + sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); *abort_no_unlock = 1; return; } @@ -1695,7 +1711,7 @@ sctp_handle_asconf_ack(struct mbuf *m, int offset, if (serial_num == asoc->asconf_seq_out - 1) { /* stop our timer */ sctp_timer_stop(SCTP_TIMER_TYPE_ASCONF, stcb->sctp_ep, stcb, net, - SCTP_FROM_SCTP_ASCONF+SCTP_LOC_3); + SCTP_FROM_SCTP_ASCONF + SCTP_LOC_5); } /* process the ASCONF-ACK contents */ @@ -1990,7 +2006,8 @@ sctp_addr_mgmt_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, * sent when the state goes open. */ if (status == 0 && - SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) { + ((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, inp, stcb, stcb->asoc.primary_destination); @@ -2242,7 +2259,8 @@ sctp_asconf_iterator_stcb(struct sctp_inpcb *inp, struct sctp_tcb *stcb, * count of queued params. If in the non-open state, * these get sent when the assoc goes open. */ - if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) { + if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) || + (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) { if (status >= 0) { num_queued++; } @@ -2303,7 +2321,8 @@ sctp_set_primary_ip_address_sa(struct sctp_tcb *stcb, struct sockaddr *sa) "set_primary_ip_address_sa: queued on tcb=%p, ", (void *)stcb); SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa); - if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) { + 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, @@ -2339,7 +2358,8 @@ sctp_set_primary_ip_address(struct sctp_ifa *ifa) 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) { + 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, diff --git a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_asconf.h b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_asconf.h index a3622e41286..a3622e41286 100755 --- a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_asconf.h +++ b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_asconf.h diff --git a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_auth.c b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_auth.c index 1e628758260..3135b6bc186 100755 --- a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_auth.c +++ b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_auth.c @@ -32,7 +32,7 @@ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_auth.c 280642 2015-03-25 22:45:54Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp_auth.c 289570 2015-10-19 11:17:54Z tuexen $"); #endif #include <netinet/sctp_os.h> @@ -560,7 +560,7 @@ sctp_auth_key_acquire(struct sctp_tcb *stcb, uint16_t key_id) atomic_add_int(&skey->refcount, 1); SCTPDBG(SCTP_DEBUG_AUTH2, "%s: stcb %p key %u refcount acquire to %d\n", - __FUNCTION__, (void *)stcb, key_id, skey->refcount); + __func__, (void *)stcb, key_id, skey->refcount); } } @@ -580,7 +580,7 @@ sctp_auth_key_release(struct sctp_tcb *stcb, uint16_t key_id, int so_locked if (skey) { SCTPDBG(SCTP_DEBUG_AUTH2, "%s: stcb %p key %u refcount release to %d\n", - __FUNCTION__, (void *)stcb, key_id, skey->refcount); + __func__, (void *)stcb, key_id, skey->refcount); /* see if a notification should be generated */ if ((skey->refcount <= 2) && (skey->deactivated)) { @@ -589,7 +589,7 @@ sctp_auth_key_release(struct sctp_tcb *stcb, uint16_t key_id, int so_locked key_id, 0, so_locked); SCTPDBG(SCTP_DEBUG_AUTH2, "%s: stcb %p key %u no longer used, %d\n", - __FUNCTION__, (void *)stcb, key_id, skey->refcount); + __func__, (void *)stcb, key_id, skey->refcount); } sctp_free_sharedkey(skey); } @@ -1678,8 +1678,8 @@ sctp_handle_auth(struct sctp_tcb *stcb, struct sctp_auth_chunk *auth, /* is the indicated HMAC supported? */ if (!sctp_auth_is_supported_hmac(stcb->asoc.local_hmacs, hmac_id)) { - struct mbuf *m_err; - struct sctp_auth_invalid_hmac *err; + struct mbuf *op_err; + struct sctp_error_auth_invalid_hmac *cause; SCTP_STAT_INCR(sctps_recvivalhmacid); SCTPDBG(SCTP_DEBUG_AUTH1, @@ -1689,20 +1689,19 @@ sctp_handle_auth(struct sctp_tcb *stcb, struct sctp_auth_chunk *auth, * report this in an Error Chunk: Unsupported HMAC * Identifier */ - m_err = sctp_get_mbuf_for_msg(sizeof(*err), 0, M_NOWAIT, - 1, MT_HEADER); - if (m_err != NULL) { + op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_error_auth_invalid_hmac), + 0, M_NOWAIT, 1, MT_HEADER); + if (op_err != NULL) { /* pre-reserve some space */ - SCTP_BUF_RESV_UF(m_err, sizeof(struct sctp_chunkhdr)); + SCTP_BUF_RESV_UF(op_err, sizeof(struct sctp_chunkhdr)); /* fill in the error */ - err = mtod(m_err, struct sctp_auth_invalid_hmac *); - bzero(err, sizeof(*err)); - err->ph.param_type = htons(SCTP_CAUSE_UNSUPPORTED_HMACID); - err->ph.param_length = htons(sizeof(*err)); - err->hmac_id = ntohs(hmac_id); - SCTP_BUF_LEN(m_err) = sizeof(*err); + cause = mtod(op_err, struct sctp_error_auth_invalid_hmac *); + cause->cause.code = htons(SCTP_CAUSE_UNSUPPORTED_HMACID); + cause->cause.length = htons(sizeof(struct sctp_error_auth_invalid_hmac)); + cause->hmac_id = ntohs(hmac_id); + SCTP_BUF_LEN(op_err) = sizeof(struct sctp_error_auth_invalid_hmac); /* queue it */ - sctp_queue_op_err(stcb, m_err); + sctp_queue_op_err(stcb, op_err); } return (-1); } diff --git a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_auth.h b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_auth.h index 997389363de..997389363de 100755 --- a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_auth.h +++ b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_auth.h diff --git a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_bsd_addr.c b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_bsd_addr.c index f5f2a3b6bf9..00772b69d39 100755 --- a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_bsd_addr.c +++ b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_bsd_addr.c @@ -124,6 +124,9 @@ static void #endif sctp_iterator_thread(void *v SCTP_UNUSED) { +#if defined(__Userspace__) + sctp_userspace_set_threadname("SCTP iterator"); +#endif SCTP_IPI_ITERATOR_WQ_LOCK(); /* In FreeBSD this thread never terminates. */ #if defined(__FreeBSD__) @@ -196,11 +199,7 @@ sctp_startup_iterator(void) #elif defined(__APPLE__) kernel_thread_start((thread_continue_t)sctp_iterator_thread, NULL, &sctp_it_ctl.thread_proc); #elif defined(__Userspace__) -#if defined(__Userspace_os_Windows) - if ((sctp_it_ctl.thread_proc = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&sctp_iterator_thread, NULL, 0, NULL)) == NULL) { -#else - if (pthread_create(&sctp_it_ctl.thread_proc, NULL, &sctp_iterator_thread, NULL)) { -#endif + if (sctp_userspace_thread_create(&sctp_it_ctl.thread_proc, &sctp_iterator_thread)) { SCTP_PRINTF("ERROR: Creating sctp_iterator_thread failed.\n"); } #endif diff --git a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_bsd_addr.h b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_bsd_addr.h index 8373b3b8345..8373b3b8345 100755 --- a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_bsd_addr.h +++ b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_bsd_addr.h diff --git a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_callout.c b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_callout.c index 3174e3fd4be..4a6955d1ee3 100755 --- a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_callout.c +++ b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_callout.c @@ -56,11 +56,20 @@ * Callout/Timer routines for OS that doesn't have them */ #if defined(__APPLE__) || defined(__Userspace__) -int ticks = 0; +static int ticks = 0; #else extern int ticks; #endif +int sctp_get_tick_count(void) { + int ret; + + SCTP_TIMERQ_LOCK(); + ret = ticks; + SCTP_TIMERQ_UNLOCK(); + return ret; +} + /* * SCTP_TIMERQ_LOCK protects: * - SCTP_BASE_INFO(callqueue) @@ -178,6 +187,7 @@ sctp_timeout(void *arg SCTP_UNUSED) void * user_sctp_timer_iterate(void *arg) { + sctp_userspace_set_threadname("SCTP timer"); for (;;) { #if defined (__Userspace_os_Windows) Sleep(TIMEOUT_INTERVAL); @@ -203,18 +213,12 @@ sctp_start_timer(void) * No need to do SCTP_TIMERQ_LOCK_INIT(); * here, it is being done in sctp_pcb_init() */ -#if defined (__Userspace_os_Windows) - if ((SCTP_BASE_VAR(timer_thread) = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)user_sctp_timer_iterate, NULL, 0, NULL)) == NULL) { - SCTP_PRINTF("ERROR; Creating ithread failed\n"); - } -#else int rc; - rc = pthread_create(&SCTP_BASE_VAR(timer_thread), NULL, user_sctp_timer_iterate, NULL); + rc = sctp_userspace_thread_create(&SCTP_BASE_VAR(timer_thread), user_sctp_timer_iterate); if (rc) { - SCTP_PRINTF("ERROR; return code from pthread_create() is %d\n", rc); + SCTP_PRINTF("ERROR; return code from sctp_thread_create() is %d\n", rc); } -#endif } #endif diff --git a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_callout.h b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_callout.h index c53c5a4fc74..4d764c90982 100755 --- a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_callout.h +++ b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_callout.h @@ -57,15 +57,20 @@ __FBSDID("$FreeBSD$"); #define SCTP_TIMERQ_LOCK_INIT() InitializeCriticalSection(&SCTP_BASE_VAR(timer_mtx)) #define SCTP_TIMERQ_LOCK_DESTROY() DeleteCriticalSection(&SCTP_BASE_VAR(timer_mtx)) #else +#ifdef INVARIANTS +#define SCTP_TIMERQ_LOCK() KASSERT(pthread_mutex_lock(&SCTP_BASE_VAR(timer_mtx)) == 0, ("%s: timer_mtx already locked", __func__)) +#define SCTP_TIMERQ_UNLOCK() KASSERT(pthread_mutex_unlock(&SCTP_BASE_VAR(timer_mtx)) == 0, ("%s: timer_mtx not locked", __func__)) +#else #define SCTP_TIMERQ_LOCK() (void)pthread_mutex_lock(&SCTP_BASE_VAR(timer_mtx)) #define SCTP_TIMERQ_UNLOCK() (void)pthread_mutex_unlock(&SCTP_BASE_VAR(timer_mtx)) -#define SCTP_TIMERQ_LOCK_INIT() (void)pthread_mutex_init(&SCTP_BASE_VAR(timer_mtx), NULL) +#endif +#define SCTP_TIMERQ_LOCK_INIT() (void)pthread_mutex_init(&SCTP_BASE_VAR(timer_mtx), &SCTP_BASE_VAR(mtx_attr)) #define SCTP_TIMERQ_LOCK_DESTROY() (void)pthread_mutex_destroy(&SCTP_BASE_VAR(timer_mtx)) #endif - -extern int ticks; #endif +int sctp_get_tick_count(void); + TAILQ_HEAD(calloutlist, sctp_callout); struct sctp_callout { diff --git a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_cc_functions.c b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_cc_functions.c index 0e01c9860d4..5b84bbd4249 100755 --- a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_cc_functions.c +++ b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_cc_functions.c @@ -32,7 +32,7 @@ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_cc_functions.c 279859 2015-03-10 19:49:25Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp_cc_functions.c 283650 2015-05-28 16:00:23Z tuexen $"); #endif #include <netinet/sctp_os.h> @@ -229,7 +229,8 @@ sctp_cwnd_update_after_fr(struct sctp_tcb *stcb, } sctp_timer_stop(SCTP_TIMER_TYPE_SEND, - stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INDATA+SCTP_LOC_32 ); + stcb->sctp_ep, stcb, net, + SCTP_FROM_SCTP_CC_FUNCTIONS + SCTP_LOC_1); sctp_timer_start(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, net); } @@ -1822,7 +1823,8 @@ sctp_hs_cwnd_update_after_fr(struct sctp_tcb *stcb, } sctp_timer_stop(SCTP_TIMER_TYPE_SEND, - stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INDATA+SCTP_LOC_32); + stcb->sctp_ep, stcb, net, + SCTP_FROM_SCTP_CC_FUNCTIONS + SCTP_LOC_2); sctp_timer_start(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, net); } @@ -2348,7 +2350,8 @@ sctp_htcp_cwnd_update_after_fr(struct sctp_tcb *stcb, } sctp_timer_stop(SCTP_TIMER_TYPE_SEND, - stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INDATA+SCTP_LOC_32); + stcb->sctp_ep, stcb, net, + SCTP_FROM_SCTP_CC_FUNCTIONS + SCTP_LOC_3); sctp_timer_start(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, net); } diff --git a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_constants.h b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_constants.h index ff4874d9df7..ec9b86e578f 100755 --- a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_constants.h +++ b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_constants.h @@ -32,7 +32,7 @@ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_constants.h 271204 2014-09-06 19:12:14Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp_constants.h 287669 2015-09-11 13:54:33Z tuexen $"); #endif #ifndef _NETINET_SCTP_CONSTANTS_H_ @@ -71,6 +71,8 @@ extern void getwintimeofday(struct timeval *tv); */ #define SCTP_LARGEST_INIT_ACCEPTED (65535 - 2048) +/* Largest length of a chunk */ +#define SCTP_MAX_CHUNK_LENGTH 0xffff /* Number of addresses where we just skip the counting */ #define SCTP_COUNT_LIMIT 40 @@ -466,7 +468,7 @@ extern void getwintimeofday(struct timeval *tv); /* - * SCTP states for internal state machine XXX (should match "user" values) + * SCTP states for internal state machine */ #define SCTP_STATE_EMPTY 0x0000 #define SCTP_STATE_INUSE 0x0001 @@ -628,10 +630,6 @@ extern void getwintimeofday(struct timeval *tv); /* 30 seconds + RTO (in ms) */ #define SCTP_HB_DEFAULT_MSEC 30000 -/* Max time I will wait for Shutdown to complete */ -#define SCTP_DEF_MAX_SHUTDOWN_SEC 180 - - /* * This is how long a secret lives, NOT how long a cookie lives how many * ticks the current secret will live. @@ -785,18 +783,19 @@ extern void getwintimeofday(struct timeval *tv); */ /* File defines */ -#define SCTP_FROM_SCTP_INPUT 0x10000000 -#define SCTP_FROM_SCTP_PCB 0x20000000 -#define SCTP_FROM_SCTP_INDATA 0x30000000 -#define SCTP_FROM_SCTP_TIMER 0x40000000 -#define SCTP_FROM_SCTP_USRREQ 0x50000000 -#define SCTP_FROM_SCTPUTIL 0x60000000 -#define SCTP_FROM_SCTP6_USRREQ 0x70000000 -#define SCTP_FROM_SCTP_ASCONF 0x80000000 -#define SCTP_FROM_SCTP_OUTPUT 0x90000000 -#define SCTP_FROM_SCTP_PEELOFF 0xa0000000 -#define SCTP_FROM_SCTP_PANDA 0xb0000000 -#define SCTP_FROM_SCTP_SYSCTL 0xc0000000 +#define SCTP_FROM_SCTP_INPUT 0x10000000 +#define SCTP_FROM_SCTP_PCB 0x20000000 +#define SCTP_FROM_SCTP_INDATA 0x30000000 +#define SCTP_FROM_SCTP_TIMER 0x40000000 +#define SCTP_FROM_SCTP_USRREQ 0x50000000 +#define SCTP_FROM_SCTPUTIL 0x60000000 +#define SCTP_FROM_SCTP6_USRREQ 0x70000000 +#define SCTP_FROM_SCTP_ASCONF 0x80000000 +#define SCTP_FROM_SCTP_OUTPUT 0x90000000 +#define SCTP_FROM_SCTP_PEELOFF 0xa0000000 +#define SCTP_FROM_SCTP_PANDA 0xb0000000 +#define SCTP_FROM_SCTP_SYSCTL 0xc0000000 +#define SCTP_FROM_SCTP_CC_FUNCTIONS 0xd0000000 /* Location ID's */ #define SCTP_LOC_1 0x00000001 @@ -832,6 +831,8 @@ extern void getwintimeofday(struct timeval *tv); #define SCTP_LOC_31 0x0000001f #define SCTP_LOC_32 0x00000020 #define SCTP_LOC_33 0x00000021 +#define SCTP_LOC_34 0x00000022 +#define SCTP_LOC_35 0x00000023 /* Free assoc codes */ diff --git a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_crc32.c b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_crc32.c index b994aaace0e..b994aaace0e 100755 --- a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_crc32.c +++ b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_crc32.c diff --git a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_crc32.h b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_crc32.h index 2cc14f4503f..2cc14f4503f 100755 --- a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_crc32.h +++ b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_crc32.h diff --git a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_header.h b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_header.h index f62181fecde..ad03007aa22 100755 --- a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_header.h +++ b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_header.h @@ -32,7 +32,7 @@ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_header.h 273168 2014-10-16 15:36:04Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp_header.h 287717 2015-09-12 17:08:51Z tuexen $"); #endif #ifndef _NETINET_SCTP_HEADER_H_ @@ -220,34 +220,6 @@ struct sctp_state_cookie { /* this is our definition... */ */ } SCTP_PACKED; - -/* Used for NAT state error cause */ -struct sctp_missing_nat_state { - uint16_t cause; - uint16_t length; - uint8_t data[]; -} SCTP_PACKED; - - -struct sctp_inv_mandatory_param { - uint16_t cause; - uint16_t length; - uint32_t num_param; - uint16_t param; - /* - * We include this to 0 it since only a missing cookie will cause - * this error. - */ - uint16_t resv; -} SCTP_PACKED; - -struct sctp_unresolv_addr { - uint16_t cause; - uint16_t length; - uint16_t addr_type; - uint16_t reserved; /* Only one invalid addr type */ -} SCTP_PACKED; - /* state cookie parameter */ struct sctp_state_cookie_param { struct sctp_paramhdr ph; @@ -388,28 +360,11 @@ struct sctp_shutdown_complete_chunk { struct sctp_chunkhdr ch; } SCTP_PACKED; -/* Oper error holding a stale cookie */ -struct sctp_stale_cookie_msg { - struct sctp_paramhdr ph;/* really an error cause */ - uint32_t time_usec; -} SCTP_PACKED; - struct sctp_adaptation_layer_indication { struct sctp_paramhdr ph; uint32_t indication; } SCTP_PACKED; -struct sctp_cookie_while_shutting_down { - struct sctphdr sh; - struct sctp_chunkhdr ch; - struct sctp_paramhdr ph;/* really an error cause */ -} SCTP_PACKED; - -struct sctp_shutdown_complete_msg { - struct sctphdr sh; - struct sctp_shutdown_complete_chunk shut_cmp; -} SCTP_PACKED; - /* * draft-ietf-tsvwg-addip-sctp */ @@ -572,12 +527,6 @@ struct sctp_auth_chunk { uint8_t hmac[]; } SCTP_PACKED; -struct sctp_auth_invalid_hmac { - struct sctp_paramhdr ph; - uint16_t hmac_id; - uint16_t padding; -} SCTP_PACKED; - /* * we pre-reserve enough room for a ECNE or CWR AND a SACK with no missing * pieces. If ENCE is missing we could have a couple of blocks. This way we diff --git a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_indata.c b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_indata.c index f697d0ced94..878b58e214e 100755 --- a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_indata.c +++ b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_indata.c @@ -32,7 +32,7 @@ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_indata.c 280440 2015-03-24 15:05:36Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp_indata.c 291700 2015-12-03 15:19:29Z tuexen $"); #endif #include <netinet/sctp_os.h> @@ -230,9 +230,9 @@ sctp_build_ctl_nchunk(struct sctp_inpcb *inp, struct sctp_sndrcvinfo *sinfo) } seinfo = (struct sctp_extrcvinfo *)sinfo; if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVNXTINFO) && - (seinfo->sreinfo_next_flags & SCTP_NEXT_MSG_AVAIL)) { + (seinfo->serinfo_next_flags & SCTP_NEXT_MSG_AVAIL)) { provide_nxt = 1; - len += CMSG_SPACE(sizeof(struct sctp_rcvinfo)); + len += CMSG_SPACE(sizeof(struct sctp_nxtinfo)); } else { provide_nxt = 0; } @@ -291,20 +291,20 @@ sctp_build_ctl_nchunk(struct sctp_inpcb *inp, struct sctp_sndrcvinfo *sinfo) cmh->cmsg_len = CMSG_LEN(sizeof(struct sctp_nxtinfo)); cmh->cmsg_type = SCTP_NXTINFO; nxtinfo = (struct sctp_nxtinfo *)CMSG_DATA(cmh); - nxtinfo->nxt_sid = seinfo->sreinfo_next_stream; + nxtinfo->nxt_sid = seinfo->serinfo_next_stream; nxtinfo->nxt_flags = 0; - if (seinfo->sreinfo_next_flags & SCTP_NEXT_MSG_IS_UNORDERED) { + if (seinfo->serinfo_next_flags & SCTP_NEXT_MSG_IS_UNORDERED) { nxtinfo->nxt_flags |= SCTP_UNORDERED; } - if (seinfo->sreinfo_next_flags & SCTP_NEXT_MSG_IS_NOTIFICATION) { + if (seinfo->serinfo_next_flags & SCTP_NEXT_MSG_IS_NOTIFICATION) { nxtinfo->nxt_flags |= SCTP_NOTIFICATION; } - if (seinfo->sreinfo_next_flags & SCTP_NEXT_MSG_ISCOMPLETE) { + if (seinfo->serinfo_next_flags & SCTP_NEXT_MSG_ISCOMPLETE) { nxtinfo->nxt_flags |= SCTP_COMPLETE; } - nxtinfo->nxt_ppid = seinfo->sreinfo_next_ppid; - nxtinfo->nxt_length = seinfo->sreinfo_next_length; - nxtinfo->nxt_assoc_id = seinfo->sreinfo_next_aid; + nxtinfo->nxt_ppid = seinfo->serinfo_next_ppid; + nxtinfo->nxt_length = seinfo->serinfo_next_length; + nxtinfo->nxt_assoc_id = seinfo->serinfo_next_aid; #if defined(__Userspace_os_Windows) cmh = (WSACMSGHDR *)((caddr_t)cmh + CMSG_SPACE(sizeof(struct sctp_nxtinfo))); #else @@ -596,10 +596,10 @@ sctp_queue_data_to_stream(struct sctp_tcb *stcb, struct sctp_association *asoc, sctp_log_strm_del(control, NULL, SCTP_STR_LOG_FROM_INTO_STRD); } SCTPDBG(SCTP_DEBUG_INDATA1, - "queue to stream called for ssn:%u lastdel:%u nxt:%u\n", - (uint32_t) control->sinfo_stream, - (uint32_t) strm->last_sequence_delivered, - (uint32_t) nxt_todel); + "queue to stream called for sid:%u ssn:%u tsn:%u lastdel:%u nxt:%u\n", + (uint32_t)control->sinfo_stream, (uint32_t)control->sinfo_ssn, + (uint32_t)control->sinfo_tsn, + (uint32_t)strm->last_sequence_delivered, (uint32_t)nxt_todel); if (SCTP_SSN_GE(strm->last_sequence_delivered, control->sinfo_ssn)) { /* The incoming sseq is behind where we last delivered? */ SCTPDBG(SCTP_DEBUG_INDATA1, "Duplicate S-SEQ:%d delivered:%d from peer, Abort association\n", @@ -614,12 +614,26 @@ sctp_queue_data_to_stream(struct sctp_tcb *stcb, struct sctp_association *asoc, strm->last_sequence_delivered, control->sinfo_tsn, control->sinfo_stream, control->sinfo_ssn); op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); - stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_1; + stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_1; sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); *abort_flag = 1; return; } +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) + struct socket *so; + + so = SCTP_INP_SO(stcb->sctp_ep); + atomic_add_int(&stcb->asoc.refcnt, 1); + SCTP_TCB_UNLOCK(stcb); + SCTP_SOCKET_LOCK(so, 1); + SCTP_TCB_LOCK(stcb); + atomic_subtract_int(&stcb->asoc.refcnt, 1); + if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) { + SCTP_SOCKET_UNLOCK(so, 1); + return; + } +#endif if (nxt_todel == control->sinfo_ssn) { /* can be delivered right away? */ if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_STR_LOGGING_ENABLE) { @@ -635,7 +649,7 @@ sctp_queue_data_to_stream(struct sctp_tcb *stcb, struct sctp_association *asoc, sctp_add_to_readq(stcb->sctp_ep, stcb, control, &stcb->sctp_socket->so_rcv, 1, - SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED); + SCTP_READ_LOCK_NOT_HELD, SCTP_SO_LOCKED); TAILQ_FOREACH_SAFE(control, &strm->inqueue, next, at) { /* all delivered */ nxt_todel = strm->last_sequence_delivered + 1; @@ -659,7 +673,7 @@ sctp_queue_data_to_stream(struct sctp_tcb *stcb, struct sctp_association *asoc, control, &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, - SCTP_SO_NOT_LOCKED); + SCTP_SO_LOCKED); continue; } break; @@ -671,6 +685,9 @@ sctp_queue_data_to_stream(struct sctp_tcb *stcb, struct sctp_association *asoc, * to put it on the queue. */ if (SCTP_TSN_GE(asoc->cumulative_tsn, control->sinfo_tsn)) { +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) + SCTP_SOCKET_UNLOCK(so, 1); +#endif goto protocol_error; } if (TAILQ_EMPTY(&strm->inqueue)) { @@ -717,6 +734,9 @@ sctp_queue_data_to_stream(struct sctp_tcb *stcb, struct sctp_association *asoc, control->whoFrom = NULL; } sctp_free_a_readq(stcb, control); +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) + SCTP_SOCKET_UNLOCK(so, 1); +#endif return; } else { if (TAILQ_NEXT(at, next) == NULL) { @@ -736,6 +756,9 @@ sctp_queue_data_to_stream(struct sctp_tcb *stcb, struct sctp_association *asoc, } } } +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) + SCTP_SOCKET_UNLOCK(so, 1); +#endif } /* @@ -879,7 +902,7 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, chk->rec.data.stream_number, chk->rec.data.stream_seq); op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); - stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_2; + stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_2; sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); *abort_flag = 1; } else if (asoc->fragmented_delivery_inprogress && @@ -896,7 +919,7 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, chk->rec.data.stream_number, chk->rec.data.stream_seq); op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); - stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_3; + stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_3; sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); *abort_flag = 1; } else if (asoc->fragmented_delivery_inprogress) { @@ -917,7 +940,7 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, chk->rec.data.stream_number, chk->rec.data.stream_seq); op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); - stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_4; + stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_4; sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); *abort_flag = 1; } else if ((asoc->fragment_flags & SCTP_DATA_UNORDERED) != @@ -934,7 +957,7 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, chk->rec.data.stream_number, chk->rec.data.stream_seq); op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); - stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_5; + stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_5; sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); *abort_flag = 1; } @@ -1011,7 +1034,7 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, chk->rec.data.stream_number, chk->rec.data.stream_seq); op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); - stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_6; + stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_6; sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); *abort_flag = 1; return; @@ -1032,7 +1055,7 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, chk->rec.data.stream_number, chk->rec.data.stream_seq); op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); - stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_7; + stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_7; sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); *abort_flag = 1; return; @@ -1050,7 +1073,7 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, chk->rec.data.TSN_seq, (chk->rec.data.rcv_flags & SCTP_DATA_UNORDERED) ? 1 : 0); op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); - stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_7; + stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_8; sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); *abort_flag = 1; return; @@ -1072,7 +1095,7 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, chk->rec.data.stream_number, chk->rec.data.stream_seq); op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); - stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_8; + stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_9; sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); *abort_flag = 1; return; @@ -1089,7 +1112,7 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, chk->rec.data.stream_number, chk->rec.data.stream_seq); op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); - stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_9; + stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_10; sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); *abort_flag = 1; return; @@ -1116,7 +1139,7 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, chk->rec.data.stream_number, chk->rec.data.stream_seq); op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); - stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_10; + stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_11; sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); *abort_flag = 1; return; @@ -1139,7 +1162,7 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, chk->rec.data.stream_number, chk->rec.data.stream_seq); op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); - stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_11; + stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_12; sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); *abort_flag = 1; return; @@ -1160,7 +1183,7 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, chk->rec.data.stream_number, chk->rec.data.stream_seq); op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); - stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_12; + stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_13; sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); *abort_flag = 1; return; @@ -1178,7 +1201,7 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, chk->rec.data.TSN_seq, (chk->rec.data.rcv_flags & SCTP_DATA_UNORDERED) ? 1 : 0); op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); - stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_12; + stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_14; sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); *abort_flag = 1; return; @@ -1200,7 +1223,7 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc, chk->rec.data.stream_number, chk->rec.data.stream_seq); op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); - stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_13; + stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_15; sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); *abort_flag = 1; return; @@ -1419,30 +1442,25 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc, } strmno = ntohs(ch->dp.stream_id); if (strmno >= asoc->streamincnt) { - struct sctp_paramhdr *phdr; - struct mbuf *mb; + struct sctp_error_invalid_stream *cause; - mb = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) * 2), - 0, M_NOWAIT, 1, MT_DATA); - if (mb != NULL) { + op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_error_invalid_stream), + 0, M_NOWAIT, 1, MT_DATA); + if (op_err != NULL) { /* add some space up front so prepend will work well */ - SCTP_BUF_RESV_UF(mb, sizeof(struct sctp_chunkhdr)); - phdr = mtod(mb, struct sctp_paramhdr *); + SCTP_BUF_RESV_UF(op_err, sizeof(struct sctp_chunkhdr)); + cause = mtod(op_err, struct sctp_error_invalid_stream *); /* * Error causes are just param's and this one has * two back to back phdr, one with the error type * and size, the other with the streamid and a rsvd */ - SCTP_BUF_LEN(mb) = (sizeof(struct sctp_paramhdr) * 2); - phdr->param_type = htons(SCTP_CAUSE_INVALID_STREAM); - phdr->param_length = - htons(sizeof(struct sctp_paramhdr) * 2); - phdr++; - /* We insert the stream in the type field */ - phdr->param_type = ch->dp.stream_id; - /* And set the length to 0 for the rsvd field */ - phdr->param_length = 0; - sctp_queue_op_err(stcb, mb); + SCTP_BUF_LEN(op_err) = sizeof(struct sctp_error_invalid_stream); + cause->cause.code = htons(SCTP_CAUSE_INVALID_STREAM); + cause->cause.length = htons(sizeof(struct sctp_error_invalid_stream)); + cause->stream_id = ch->dp.stream_id; + cause->reserved = htons(0); + sctp_queue_op_err(stcb, op_err); } SCTP_STAT_INCR(sctps_badsid); SCTP_TCB_LOCK_ASSERT(stcb); @@ -1492,7 +1510,7 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc, asoc->strmin[strmno].last_sequence_delivered, tsn, strmno, strmseq); op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); - stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_14; + stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_16; sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); *abort_flag = 1; return (0); @@ -1725,7 +1743,7 @@ failed_express_del: snprintf(msg, sizeof(msg), "Reas. queue emtpy, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x", tsn, strmno, strmseq); op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); - stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_15; + stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_17; sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); *abort_flag = 1; if (last_chunk) { @@ -1744,7 +1762,7 @@ failed_express_del: snprintf(msg, sizeof(msg), "PD ongoing, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x", tsn, strmno, strmseq); op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); - stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_16; + stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_18; sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); *abort_flag = 1; if (last_chunk) { @@ -1773,7 +1791,7 @@ failed_express_del: snprintf(msg, sizeof(msg), "No PD ongoing, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x", tsn, strmno, strmseq); op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); - stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_17; + stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_19; sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); *abort_flag = 1; if (last_chunk) { @@ -1897,6 +1915,7 @@ finish_express_del: sctp_reset_in_stream(stcb, liste->number_entries, liste->list_of_streams); TAILQ_REMOVE(&asoc->resetHead, liste, next_resp); + sctp_send_deferred_reset_response(stcb, liste, SCTP_STREAM_RESET_RESULT_PERFORMED); SCTP_FREE(liste, SCTP_M_STRESET); /*sa_ignore FREED_MEMORY*/ liste = TAILQ_FIRST(&asoc->resetHead); @@ -2171,7 +2190,8 @@ sctp_sack_check(struct sctp_tcb *stcb, int was_a_gap) */ if (SCTP_OS_TIMER_PENDING(&stcb->asoc.dack_timer.timer)) { sctp_timer_stop(SCTP_TIMER_TYPE_RECV, - stcb->sctp_ep, stcb, NULL, SCTP_FROM_SCTP_INDATA+SCTP_LOC_18); + stcb->sctp_ep, stcb, NULL, + SCTP_FROM_SCTP_INDATA + SCTP_LOC_20); } sctp_send_shutdown(stcb, ((stcb->asoc.alternate) ? stcb->asoc.alternate : stcb->asoc.primary_destination)); @@ -2300,13 +2320,8 @@ sctp_service_queues(struct sctp_tcb *stcb, struct sctp_association *asoc) int sctp_process_data(struct mbuf **mm, int iphlen, int *offset, int length, - struct sockaddr *src, struct sockaddr *dst, - struct sctphdr *sh, struct sctp_inpcb *inp, - struct sctp_tcb *stcb, struct sctp_nets *net, uint32_t *high_tsn, -#if defined(__FreeBSD__) - uint8_t mflowtype, uint32_t mflowid, -#endif - uint32_t vrf_id, uint16_t port) + struct sctp_inpcb *inp, struct sctp_tcb *stcb, + struct sctp_nets *net, uint32_t *high_tsn) { struct sctp_data_chunk *ch, chunk_buf; struct sctp_association *asoc; @@ -2398,13 +2413,8 @@ sctp_process_data(struct mbuf **mm, int iphlen, int *offset, int length, snprintf(msg, sizeof(msg), "DATA chunk of length %d", chk_length); op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); - stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_19; - sctp_abort_association(inp, stcb, m, iphlen, - src, dst, sh, op_err, -#if defined(__FreeBSD__) - mflowtype, mflowid, -#endif - vrf_id, port); + stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_21; + sctp_abort_an_association(inp, stcb, op_err, SCTP_SO_NOT_LOCKED); return (2); } if ((size_t)chk_length == sizeof(struct sctp_data_chunk)) { @@ -2415,13 +2425,8 @@ sctp_process_data(struct mbuf **mm, int iphlen, int *offset, int length, struct mbuf *op_err; op_err = sctp_generate_no_user_data_cause(ch->dp.tsn); - stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_19; - sctp_abort_association(inp, stcb, m, iphlen, - src, dst, sh, op_err, -#if defined(__FreeBSD__) - mflowtype, mflowid, -#endif - vrf_id, port); + stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_22; + sctp_abort_an_association(inp, stcb, op_err, SCTP_SO_NOT_LOCKED); return (2); } #ifdef SCTP_AUDITING_ENABLED @@ -2483,16 +2488,12 @@ sctp_process_data(struct mbuf **mm, int iphlen, int *offset, int length, */ if (SCTP_BASE_SYSCTL(sctp_strict_data_order)) { struct mbuf *op_err; + char msg[SCTP_DIAG_INFO_LEN]; - op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, ""); - sctp_abort_association(inp, stcb, - m, iphlen, - src, dst, - sh, op_err, -#if defined(__FreeBSD__) - mflowtype, mflowid, -#endif - vrf_id, port); + snprintf(msg, sizeof(msg), "DATA chunk followed by chunk of type %2.2x", + ch->ch.chunk_type); + op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); + sctp_abort_an_association(inp, stcb, op_err, SCTP_SO_NOT_LOCKED); return (2); } break; @@ -2500,34 +2501,21 @@ sctp_process_data(struct mbuf **mm, int iphlen, int *offset, int length, /* unknown chunk type, use bit rules */ if (ch->ch.chunk_type & 0x40) { /* Add a error report to the queue */ - struct mbuf *merr; - struct sctp_paramhdr *phd; - - merr = sctp_get_mbuf_for_msg(sizeof(*phd), 0, M_NOWAIT, 1, MT_DATA); - if (merr) { - phd = mtod(merr, struct sctp_paramhdr *); - /* - * We cheat and use param - * type since we did not - * bother to define a error - * cause struct. They are - * the same basic format - * with different names. - */ - phd->param_type = - htons(SCTP_CAUSE_UNRECOG_CHUNK); - phd->param_length = - htons(chk_length + sizeof(*phd)); - SCTP_BUF_LEN(merr) = sizeof(*phd); - SCTP_BUF_NEXT(merr) = SCTP_M_COPYM(m, *offset, chk_length, M_NOWAIT); - if (SCTP_BUF_NEXT(merr)) { - if (sctp_pad_lastmbuf(SCTP_BUF_NEXT(merr), SCTP_SIZE32(chk_length) - chk_length, NULL) == NULL) { - sctp_m_freem(merr); - } else { - sctp_queue_op_err(stcb, merr); - } + struct mbuf *op_err; + struct sctp_gen_error_cause *cause; + + op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_gen_error_cause), + 0, M_NOWAIT, 1, MT_DATA); + if (op_err != NULL) { + cause = mtod(op_err, struct sctp_gen_error_cause *); + cause->code = htons(SCTP_CAUSE_UNRECOG_CHUNK); + cause->length = htons(chk_length + sizeof(struct sctp_gen_error_cause)); + SCTP_BUF_LEN(op_err) = sizeof(struct sctp_gen_error_cause); + SCTP_BUF_NEXT(op_err) = SCTP_M_COPYM(m, *offset, chk_length, M_NOWAIT); + if (SCTP_BUF_NEXT(op_err) != NULL) { + sctp_queue_op_err(stcb, op_err); } else { - sctp_m_freem(merr); + sctp_m_freem(op_err); } } } @@ -2790,6 +2778,11 @@ sctp_process_segment_range(struct sctp_tcb *stcb, struct sctp_tmit_chunk **p_tp1 panic("No chunks on the queues for sid %u.", tp1->rec.data.stream_number); #endif } + if ((stcb->asoc.strmout[tp1->rec.data.stream_number].chunks_on_queues == 0) && + (stcb->asoc.strmout[tp1->rec.data.stream_number].state == SCTP_STREAM_RESET_PENDING) && + TAILQ_EMPTY(&stcb->asoc.strmout[tp1->rec.data.stream_number].outqueue)) { + stcb->asoc.trigger_reset = 1; + } tp1->sent = SCTP_DATAGRAM_NR_ACKED; if (tp1->data) { /* sa_ignore NO_NULL_CHK */ @@ -3470,12 +3463,16 @@ sctp_fs_audit(struct sctp_association *asoc) { struct sctp_tmit_chunk *chk; int inflight = 0, resend = 0, inbetween = 0, acked = 0, above = 0; - int entry_flight, entry_cnt, ret; + int ret; +#ifndef INVARIANTS + int entry_flight, entry_cnt; +#endif + ret = 0; +#ifndef INVARIANTS entry_flight = asoc->total_flight; entry_cnt = asoc->total_flight_count; - ret = 0; - +#endif if (asoc->pr_sctp_cnt >= asoc->sent_queue_cnt) return (0); @@ -3623,24 +3620,17 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack, send_s = asoc->sending_seq; } if (SCTP_TSN_GE(cumack, send_s)) { -#ifndef INVARIANTS struct mbuf *op_err; char msg[SCTP_DIAG_INFO_LEN]; -#endif -#ifdef INVARIANTS - panic("Impossible sack 1"); -#else - *abort_now = 1; /* XXX */ - snprintf(msg, sizeof(msg), "Cum ack %8.8x greater or equal then TSN %8.8x", + snprintf(msg, sizeof(msg), "Cum ack %8.8x greater or equal than TSN %8.8x", cumack, send_s); op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); - stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_25; + stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_23; sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); return; -#endif } } asoc->this_sack_highest_gap = cumack; @@ -3749,6 +3739,11 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack, #endif } } + if ((asoc->strmout[tp1->rec.data.stream_number].chunks_on_queues == 0) && + (asoc->strmout[tp1->rec.data.stream_number].state == SCTP_STREAM_RESET_PENDING) && + TAILQ_EMPTY(&asoc->strmout[tp1->rec.data.stream_number].outqueue)) { + asoc->trigger_reset = 1; + } TAILQ_REMOVE(&asoc->sent_queue, tp1, sctp_next); if (tp1->data) { /* sa_ignore NO_NULL_CHK */ @@ -3856,7 +3851,9 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack, } if (net->dest_state & SCTP_ADDR_PF) { net->dest_state &= ~SCTP_ADDR_PF; - sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_3); + sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, + stcb->sctp_ep, stcb, net, + SCTP_FROM_SCTP_INDATA + SCTP_LOC_24); sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net); asoc->cc_functions.sctp_cwnd_update_exit_pf(stcb, net); /* Done with this net */ @@ -3939,7 +3936,7 @@ again: } else if (SCTP_OS_TIMER_PENDING(&net->rxt_timer.timer)) { sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, net, - SCTP_FROM_SCTP_INDATA + SCTP_LOC_22); + SCTP_FROM_SCTP_INDATA + SCTP_LOC_25); } } } @@ -4011,7 +4008,7 @@ again: *abort_now = 1; /* XXX */ op_err = sctp_generate_cause(SCTP_CAUSE_USER_INITIATED_ABT, ""); - stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_24; + stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_26; sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); } else { struct sctp_nets *netp; @@ -4221,10 +4218,10 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup, hopeless_peer: *abort_now = 1; /* XXX */ - snprintf(msg, sizeof(msg), "Cum ack %8.8x greater or equal then TSN %8.8x", + snprintf(msg, sizeof(msg), "Cum ack %8.8x greater or equal than TSN %8.8x", cum_ack, send_s); op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); - stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_25; + stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_27; sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); return; } @@ -4257,7 +4254,7 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup, /* stop any timers */ TAILQ_FOREACH(net, &asoc->nets, sctp_next) { sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, - stcb, net, SCTP_FROM_SCTP_INDATA + SCTP_LOC_26); + stcb, net, SCTP_FROM_SCTP_INDATA + SCTP_LOC_28); net->partial_bytes_acked = 0; net->flight_size = 0; } @@ -4462,14 +4459,14 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup, if (net->new_pseudo_cumack) sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, net, - SCTP_FROM_SCTP_INDATA + SCTP_LOC_27); + SCTP_FROM_SCTP_INDATA + SCTP_LOC_29); } } else { if (accum_moved) { TAILQ_FOREACH(net, &asoc->nets, sctp_next) { sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, - stcb, net, SCTP_FROM_SCTP_INDATA + SCTP_LOC_28); + stcb, net, SCTP_FROM_SCTP_INDATA + SCTP_LOC_30); } } } @@ -4491,6 +4488,11 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup, #endif } } + if ((asoc->strmout[tp1->rec.data.stream_number].chunks_on_queues == 0) && + (asoc->strmout[tp1->rec.data.stream_number].state == SCTP_STREAM_RESET_PENDING) && + TAILQ_EMPTY(&asoc->strmout[tp1->rec.data.stream_number].outqueue)) { + asoc->trigger_reset = 1; + } TAILQ_REMOVE(&asoc->sent_queue, tp1, sctp_next); if (PR_SCTP_ENABLED(tp1->flags)) { if (asoc->pr_sctp_cnt != 0) @@ -4667,7 +4669,9 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup, if (net->dest_state & SCTP_ADDR_PF) { net->dest_state &= ~SCTP_ADDR_PF; - sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_3); + sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, + stcb->sctp_ep, stcb, net, + SCTP_FROM_SCTP_INDATA + SCTP_LOC_31); sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net); asoc->cc_functions.sctp_cwnd_update_exit_pf(stcb, net); /* Done with this net */ @@ -4691,7 +4695,8 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup, TAILQ_FOREACH(net, &asoc->nets, sctp_next) { /* stop all timers */ sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, - stcb, net, SCTP_FROM_SCTP_INDATA + SCTP_LOC_30); + stcb, net, + SCTP_FROM_SCTP_INDATA + SCTP_LOC_32); net->flight_size = 0; net->partial_bytes_acked = 0; } @@ -4747,7 +4752,7 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup, *abort_now = 1; /* XXX */ op_err = sctp_generate_cause(SCTP_CAUSE_USER_INITIATED_ABT, ""); - stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_31; + stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_33; sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); return; } else { @@ -4897,7 +4902,7 @@ again: } else if (SCTP_OS_TIMER_PENDING(&net->rxt_timer.timer)) { sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, net, - SCTP_FROM_SCTP_INDATA + SCTP_LOC_22); + SCTP_FROM_SCTP_INDATA + SCTP_LOC_34); } } } @@ -5185,7 +5190,7 @@ sctp_handle_forward_tsn(struct sctp_tcb *stcb, "New cum ack %8.8x too high, highest TSN %8.8x", new_cum_tsn, asoc->highest_tsn_inside_map); op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg); - stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_33; + stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_35; sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); return; } diff --git a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_indata.h b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_indata.h index d90602a21d7..ef04c421d78 100755 --- a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_indata.h +++ b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_indata.h @@ -32,7 +32,7 @@ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_indata.h 252585 2013-07-03 18:48:43Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp_indata.h 286206 2015-08-02 16:07:30Z tuexen $"); #endif #ifndef _NETINET_SCTP_INDATA_H_ @@ -114,14 +114,8 @@ sctp_update_acked(struct sctp_tcb *, struct sctp_shutdown_chunk *, int *); int sctp_process_data(struct mbuf **, int, int *, int, - struct sockaddr *src, struct sockaddr *dst, - struct sctphdr *, struct sctp_inpcb *, struct sctp_tcb *, - struct sctp_nets *, uint32_t *, -#if defined(__FreeBSD__) - uint8_t, uint32_t, -#endif - uint32_t, uint16_t); + struct sctp_nets *, uint32_t *); void sctp_slide_mapping_arrays(struct sctp_tcb *stcb); diff --git a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_input.c b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_input.c index 54f2f9ba354..588548559fd 100755 --- a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_input.c +++ b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_input.c @@ -32,7 +32,7 @@ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_input.c 279859 2015-03-10 19:49:25Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp_input.c 292060 2015-12-10 11:49:32Z tuexen $"); #endif #include <netinet/sctp_os.h> @@ -79,12 +79,12 @@ sctp_stop_all_cookie_timers(struct sctp_tcb *stcb) sctp_timer_stop(SCTP_TIMER_TYPE_COOKIE, stcb->sctp_ep, stcb, - net, SCTP_FROM_SCTP_INPUT+SCTP_LOC_1); + net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_1); } else if (net->rxt_timer.type == SCTP_TIMER_TYPE_INIT) { sctp_timer_stop(SCTP_TIMER_TYPE_INIT, stcb->sctp_ep, stcb, - net, SCTP_FROM_SCTP_INPUT+SCTP_LOC_2); + net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_2); } } } @@ -207,7 +207,7 @@ sctp_handle_init(struct mbuf *m, int iphlen, int offset, "No listener"); sctp_send_abort(m, iphlen, src, dst, sh, 0, op_err, #if defined(__FreeBSD__) - mflowtype, mflowid, + mflowtype, mflowid, inp->fibnum, #endif vrf_id, port); } @@ -380,14 +380,17 @@ sctp_process_init(struct sctp_init_chunk *cp, struct sctp_tcb *stcb) sctp_free_a_strmoq(stcb, sp, SCTP_SO_NOT_LOCKED); /*sa_ignore FREED_MEMORY*/ } + outs->state = SCTP_STREAM_CLOSED; } } /* cut back the count */ asoc->pre_open_streams = newcnt; } SCTP_TCB_SEND_UNLOCK(stcb); - asoc->strm_realoutsize = asoc->streamoutcnt = asoc->pre_open_streams; - + asoc->streamoutcnt = asoc->pre_open_streams; + for (i = 0; i < asoc->streamoutcnt; i++) { + asoc->strmout[i].state = SCTP_STREAM_OPEN; + } /* EY - nr_sack: initialize highest tsn in nr_mapping_array */ asoc->highest_tsn_inside_nr_map = asoc->highest_tsn_inside_map; if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) { @@ -541,12 +544,36 @@ sctp_process_init_ack(struct mbuf *m, int iphlen, int offset, * primary. */ sctp_timer_stop(SCTP_TIMER_TYPE_INIT, stcb->sctp_ep, stcb, - asoc->primary_destination, SCTP_FROM_SCTP_INPUT+SCTP_LOC_4); + 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); +#if defined(__Userspace__) + if (stcb->sctp_ep->recv_callback) { + if (stcb->sctp_socket) { + uint32_t inqueue_bytes, sb_free_now; + struct sctp_inpcb *inp; + inp = stcb->sctp_ep; + inqueue_bytes = stcb->asoc.total_output_queue_size - (stcb->asoc.chunks_on_out_queue * sizeof(struct sctp_data_chunk)); + sb_free_now = SCTP_SB_LIMIT_SND(stcb->sctp_socket) - (inqueue_bytes + stcb->asoc.sb_send_resv); + + /* check if the amount free in the send socket buffer crossed the threshold */ + if (inp->send_callback && + (((inp->send_sb_threshold > 0) && + (sb_free_now >= inp->send_sb_threshold) && + (stcb->asoc.chunks_on_out_queue <= SCTP_BASE_SYSCTL(sctp_max_chunks_on_queue))) || + (inp->send_sb_threshold == 0))) { + atomic_add_int(&stcb->asoc.refcnt, 1); + SCTP_TCB_UNLOCK(stcb); + inp->send_callback(stcb->sctp_socket, sb_free_now); + SCTP_TCB_LOCK(stcb); + atomic_subtract_int(&stcb->asoc.refcnt, 1); + } + } + } +#endif retval = sctp_send_cookie_echo(m, offset, stcb, net); if (retval < 0) { /* @@ -555,25 +582,21 @@ sctp_process_init_ack(struct mbuf *m, int iphlen, int offset, * abandon the peer, its broke. */ if (retval == -3) { + uint16_t len; + + len = (uint16_t)(sizeof(struct sctp_error_missing_param) + sizeof(uint16_t)); /* We abort with an error of missing mandatory param */ - op_err = sctp_generate_cause(SCTP_CAUSE_MISSING_PARAM, ""); - if (op_err) { - /* - * Expand beyond to include the mandatory - * param cookie - */ - struct sctp_inv_mandatory_param *mp; + op_err = sctp_get_mbuf_for_msg(len, 0, M_NOWAIT, 1, MT_DATA); + if (op_err != NULL) { + struct sctp_error_missing_param *cause; - SCTP_BUF_LEN(op_err) = - sizeof(struct sctp_inv_mandatory_param); - mp = mtod(op_err, - struct sctp_inv_mandatory_param *); + SCTP_BUF_LEN(op_err) = len; + cause = mtod(op_err, struct sctp_error_missing_param *); /* Subtract the reserved param */ - mp->length = - htons(sizeof(struct sctp_inv_mandatory_param) - 2); - mp->num_param = htonl(1); - mp->param = htons(SCTP_STATE_COOKIE); - mp->resv = 0; + cause->cause.code = htons(SCTP_CAUSE_MISSING_PARAM); + cause->cause.length = htons(len); + cause->num_missing_params = htonl(1); + cause->type[0] = htons(SCTP_STATE_COOKIE); } sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, src, dst, sh, op_err, @@ -682,7 +705,8 @@ sctp_handle_heartbeat_ack(struct sctp_heartbeat_chunk *cp, } sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_CONFIRMED, stcb, 0, (void *)r_net, SCTP_SO_NOT_LOCKED); - sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, r_net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_3); + sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, + r_net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_4); sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, r_net); } old_error_counter = r_net->error_count; @@ -703,7 +727,8 @@ sctp_handle_heartbeat_ack(struct sctp_heartbeat_chunk *cp, stcb->asoc.cc_functions.sctp_cwnd_update_exit_pf(stcb, net); } if (old_error_counter > 0) { - sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, r_net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_3); + sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, + stcb, r_net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_5); sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, r_net); } if (r_net == stcb->asoc.primary_destination) { @@ -722,7 +747,9 @@ sctp_handle_heartbeat_ack(struct sctp_heartbeat_chunk *cp, sctp_is_mobility_feature_on(stcb->sctp_ep, SCTP_MOBILITY_PRIM_DELETED)) { - sctp_timer_stop(SCTP_TIMER_TYPE_PRIM_DELETED, stcb->sctp_ep, stcb, NULL, SCTP_FROM_SCTP_TIMER+SCTP_LOC_7); + sctp_timer_stop(SCTP_TIMER_TYPE_PRIM_DELETED, + stcb->sctp_ep, stcb, NULL, + SCTP_FROM_SCTP_INPUT + SCTP_LOC_6); if (sctp_is_mobility_feature_on(stcb->sctp_ep, SCTP_MOBILITY_FASTHANDOFF)) { sctp_assoc_immediate_retrans(stcb, @@ -815,10 +842,10 @@ sctp_handle_abort(struct sctp_abort_chunk *abort, * two magic nat aborts which don't kill the assoc * necessarily. */ - struct sctp_missing_nat_state *natc; + struct sctp_gen_error_cause *cause; - natc = (struct sctp_missing_nat_state *)(abort + 1); - error = ntohs(natc->cause); + cause = (struct sctp_gen_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); @@ -836,7 +863,8 @@ sctp_handle_abort(struct sctp_abort_chunk *abort, error = 0; } /* stop any receive timers */ - sctp_timer_stop(SCTP_TIMER_TYPE_RECV, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INPUT+SCTP_LOC_6); + sctp_timer_stop(SCTP_TIMER_TYPE_RECV, stcb->sctp_ep, stcb, net, + SCTP_FROM_SCTP_INPUT + SCTP_LOC_7); /* notify user of the abort and clean up... */ sctp_abort_notification(stcb, 1, error, abort, SCTP_SO_NOT_LOCKED); /* free the tcb */ @@ -858,7 +886,7 @@ sctp_handle_abort(struct sctp_abort_chunk *abort, #endif stcb->asoc.state |= SCTP_STATE_WAS_ABORTED; (void)sctp_free_assoc(stcb->sctp_ep, stcb, SCTP_NORMAL_PROC, - SCTP_FROM_SCTP_INPUT+SCTP_LOC_6); + SCTP_FROM_SCTP_INPUT + SCTP_LOC_8); #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) SCTP_SOCKET_UNLOCK(so, 1); #endif @@ -902,6 +930,7 @@ sctp_handle_shutdown(struct sctp_shutdown_chunk *cp, { struct sctp_association *asoc; int some_on_streamwheel; + int old_state; #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) struct socket *so; #endif @@ -918,11 +947,11 @@ sctp_handle_shutdown(struct sctp_shutdown_chunk *cp, if (ntohs(cp->ch.chunk_length) != sizeof(struct sctp_shutdown_chunk)) { /* Shutdown NOT the expected size */ return; - } else { - sctp_update_acked(stcb, cp, abort_flag); - if (*abort_flag) { - return; - } + } + old_state = SCTP_GET_STATE(asoc); + sctp_update_acked(stcb, cp, abort_flag); + if (*abort_flag) { + return; } if (asoc->control_pdapi) { /* With a normal shutdown @@ -970,7 +999,8 @@ sctp_handle_shutdown(struct sctp_shutdown_chunk *cp, * stop the shutdown timer, since we WILL move to * SHUTDOWN-ACK-SENT. */ - sctp_timer_stop(SCTP_TIMER_TYPE_SHUTDOWN, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INPUT+SCTP_LOC_8); + sctp_timer_stop(SCTP_TIMER_TYPE_SHUTDOWN, stcb->sctp_ep, stcb, + net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_9); } /* Now is there unsent data on a stream somewhere? */ some_on_streamwheel = sctp_is_there_unsent_data(stcb, SCTP_SO_NOT_LOCKED); @@ -988,12 +1018,16 @@ sctp_handle_shutdown(struct sctp_shutdown_chunk *cp, (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) { SCTP_STAT_DECR_GAUGE32(sctps_currestab); } - SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_ACK_SENT); SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING); - sctp_stop_timers_for_shutdown(stcb); - sctp_send_shutdown_ack(stcb, net); - sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNACK, stcb->sctp_ep, - stcb, net); + if (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_ACK_SENT) { + SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_ACK_SENT); + sctp_stop_timers_for_shutdown(stcb); + sctp_send_shutdown_ack(stcb, net); + sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNACK, + stcb->sctp_ep, stcb, net); + } else if (old_state == SCTP_STATE_SHUTDOWN_ACK_SENT) { + sctp_send_shutdown_ack(stcb, net); + } } } @@ -1062,7 +1096,8 @@ sctp_handle_shutdown_ack(struct sctp_shutdown_ack_chunk *cp SCTP_UNUSED, } #endif /* stop the timer */ - sctp_timer_stop(SCTP_TIMER_TYPE_SHUTDOWN, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INPUT+SCTP_LOC_9); + sctp_timer_stop(SCTP_TIMER_TYPE_SHUTDOWN, stcb->sctp_ep, stcb, net, + SCTP_FROM_SCTP_INPUT + SCTP_LOC_10); /* send SHUTDOWN-COMPLETE */ sctp_send_shutdown_complete(stcb, net, 0); /* notify upper layer protocol */ @@ -1083,7 +1118,7 @@ sctp_handle_shutdown_ack(struct sctp_shutdown_ack_chunk *cp SCTP_UNUSED, atomic_subtract_int(&stcb->asoc.refcnt, 1); #endif (void)sctp_free_assoc(stcb->sctp_ep, stcb, SCTP_NORMAL_PROC, - SCTP_FROM_SCTP_INPUT+SCTP_LOC_10); + SCTP_FROM_SCTP_INPUT + SCTP_LOC_11); #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) SCTP_SOCKET_UNLOCK(so, 1); #endif @@ -1241,7 +1276,7 @@ sctp_handle_error(struct sctp_chunkhdr *ch, atomic_subtract_int(&stcb->asoc.refcnt, 1); #endif (void)sctp_free_assoc(stcb->sctp_ep, stcb, SCTP_NORMAL_PROC, - SCTP_FROM_SCTP_INPUT+SCTP_LOC_11); + SCTP_FROM_SCTP_INPUT + SCTP_LOC_12); #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) SCTP_SOCKET_UNLOCK(so, 1); #endif @@ -1529,7 +1564,7 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, op_err = sctp_generate_cause(SCTP_CAUSE_COOKIE_IN_SHUTDOWN, ""); sctp_send_operr_to(src, dst, sh, cookie->peers_vtag, op_err, #if defined(__FreeBSD__) - mflowtype, mflowid, + mflowtype, mflowid, inp->fibnum, #endif vrf_id, net->port); if (how_indx < sizeof(asoc->cookie_how)) @@ -1611,9 +1646,12 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, return (NULL); } /* we have already processed the INIT so no problem */ - sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, - net, SCTP_FROM_SCTP_INPUT+SCTP_LOC_12); - sctp_timer_stop(SCTP_TIMER_TYPE_INIT, inp, stcb, net, SCTP_FROM_SCTP_INPUT+SCTP_LOC_13); + sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, + stcb, net, + SCTP_FROM_SCTP_INPUT + SCTP_LOC_13); + sctp_timer_stop(SCTP_TIMER_TYPE_INIT, inp, + stcb, net, + SCTP_FROM_SCTP_INPUT + SCTP_LOC_14); /* update current state */ if (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED) SCTP_STAT_INCR_COUNTER32(sctps_activeestab); @@ -1736,7 +1774,7 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, op_err = sctp_generate_cause(SCTP_CAUSE_NAT_COLLIDING_STATE, ""); sctp_send_abort(m, iphlen, src, dst, sh, 0, op_err, #if defined(__FreeBSD__) - mflowtype, mflowid, + mflowtype, mflowid, inp->fibnum, #endif vrf_id, port); return (NULL); @@ -1772,7 +1810,8 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, } if (how_indx < sizeof(asoc->cookie_how)) asoc->cookie_how[how_indx] = 8; - sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net, SCTP_FROM_SCTP_INPUT+SCTP_LOC_14); + sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net, + SCTP_FROM_SCTP_INPUT + SCTP_LOC_15); sctp_stop_all_cookie_timers(stcb); /* * since we did not send a HB make sure we don't double @@ -1913,8 +1952,10 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, /* temp code */ if (how_indx < sizeof(asoc->cookie_how)) asoc->cookie_how[how_indx] = 12; - sctp_timer_stop(SCTP_TIMER_TYPE_INIT, inp, stcb, net, SCTP_FROM_SCTP_INPUT+SCTP_LOC_15); - sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net, SCTP_FROM_SCTP_INPUT+SCTP_LOC_16); + sctp_timer_stop(SCTP_TIMER_TYPE_INIT, inp, stcb, net, + SCTP_FROM_SCTP_INPUT + SCTP_LOC_16); + sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net, + SCTP_FROM_SCTP_INPUT + SCTP_LOC_17); /* notify upper layer */ *notification = SCTP_NOTIFY_ASSOC_RESTART; @@ -2136,6 +2177,7 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset, */ stcb = sctp_aloc_assoc(inp, init_src, &error, ntohl(initack_cp->init.initiate_tag), vrf_id, + ntohs(initack_cp->init.num_outbound_streams), #if defined(__FreeBSD__) && __FreeBSD_version >= 500000 (struct thread *)NULL #elif defined(__Windows__) @@ -2199,7 +2241,7 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset, SCTP_TCB_LOCK(stcb); #endif (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, - SCTP_FROM_SCTP_INPUT+SCTP_LOC_16); + SCTP_FROM_SCTP_INPUT + SCTP_LOC_18); #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) SCTP_SOCKET_UNLOCK(so, 1); #endif @@ -2230,7 +2272,8 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset, SCTP_SOCKET_LOCK(so, 1); SCTP_TCB_LOCK(stcb); #endif - (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT+SCTP_LOC_16); + (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, + SCTP_FROM_SCTP_INPUT + SCTP_LOC_19); #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) SCTP_SOCKET_UNLOCK(so, 1); #endif @@ -2247,7 +2290,8 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset, SCTP_SOCKET_LOCK(so, 1); SCTP_TCB_LOCK(stcb); #endif - (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT+SCTP_LOC_17); + (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, + SCTP_FROM_SCTP_INPUT + SCTP_LOC_20); #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) SCTP_SOCKET_UNLOCK(so, 1); #endif @@ -2276,7 +2320,8 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset, SCTP_SOCKET_LOCK(so, 1); SCTP_TCB_LOCK(stcb); #endif - (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT+SCTP_LOC_18); + (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, + SCTP_FROM_SCTP_INPUT + SCTP_LOC_21); #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) SCTP_SOCKET_UNLOCK(so, 1); #endif @@ -2351,7 +2396,8 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset, SCTP_SOCKET_LOCK(so, 1); SCTP_TCB_LOCK(stcb); #endif - (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT+SCTP_LOC_19); + (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, + SCTP_FROM_SCTP_INPUT + SCTP_LOC_22); #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) SCTP_SOCKET_UNLOCK(so, 1); #endif @@ -2405,12 +2451,18 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset, sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTOCLOSE)) { sctp_timer_start(SCTP_TIMER_TYPE_AUTOCLOSE, inp, stcb, NULL); } - /* calculate the RTT */ (void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered); - if ((netp) && (*netp)) { + if ((netp != NULL) && (*netp != NULL)) { + /* calculate the RTT and set the encaps port */ (*netp)->RTO = sctp_calculate_rto(stcb, asoc, *netp, &cookie->time_entered, sctp_align_unsafe_makecopy, SCTP_RTT_FROM_NON_DATA); +#if defined(INET) || defined(INET6) + if (((*netp)->port == 0) && (port != 0)) { + sctp_pathmtu_adjustment(stcb, (*netp)->mtu - sizeof(struct udphdr)); + } + (*netp)->port = port; +#endif } /* respond with a COOKIE-ACK */ sctp_send_cookie_ack(stcb); @@ -2495,8 +2547,8 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset, cookie_offset = offset + sizeof(struct sctp_chunkhdr); cookie_len = ntohs(cp->ch.chunk_length); - if ((cookie->peerport != sh->src_port) && - (cookie->myport != sh->dest_port) && + if ((cookie->peerport != sh->src_port) || + (cookie->myport != sh->dest_port) || (cookie->my_vtag != sh->v_tag)) { /* * invalid ports or bad tag. Note that we always leave the @@ -2619,29 +2671,29 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset, { /* cookie is stale! */ struct mbuf *op_err; - struct sctp_stale_cookie_msg *scm; + struct sctp_error_stale_cookie *cause; uint32_t tim; - op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_stale_cookie_msg), + op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_error_stale_cookie), 0, M_NOWAIT, 1, MT_DATA); if (op_err == NULL) { /* FOOBAR */ return (NULL); } /* Set the len */ - SCTP_BUF_LEN(op_err) = sizeof(struct sctp_stale_cookie_msg); - scm = mtod(op_err, struct sctp_stale_cookie_msg *); - scm->ph.param_type = htons(SCTP_CAUSE_STALE_COOKIE); - scm->ph.param_length = htons((sizeof(struct sctp_paramhdr) + + SCTP_BUF_LEN(op_err) = sizeof(struct sctp_error_stale_cookie); + cause = mtod(op_err, struct sctp_error_stale_cookie *); + 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; - scm->time_usec = htonl(tim); + cause->stale_time = htonl(tim); sctp_send_operr_to(src, dst, sh, cookie->peers_vtag, op_err, #if defined(__FreeBSD__) - mflowtype, mflowid, + mflowtype, mflowid, l_inp->fibnum, #endif vrf_id, port); return (NULL); @@ -2765,8 +2817,9 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset, return (NULL); } #if defined(__FreeBSD__) - if ((*netp != NULL) && (mflowtype != M_HASHTYPE_NONE)) { + if (*netp != NULL) { (*netp)->flowtype = mflowtype; + (*netp)->flowid = mflowid; } #endif /* @@ -2874,7 +2927,8 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset, SCTP_TCB_LOCK((*stcb)); atomic_subtract_int(&(*stcb)->asoc.refcnt, 1); #endif - (void)sctp_free_assoc(*inp_p, *stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT+SCTP_LOC_20); + (void)sctp_free_assoc(*inp_p, *stcb, SCTP_NORMAL_PROC, + SCTP_FROM_SCTP_INPUT + SCTP_LOC_23); #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) SCTP_SOCKET_UNLOCK(pcb_so, 1); #endif @@ -2909,6 +2963,7 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset, inp->partial_delivery_point = (*inp_p)->partial_delivery_point; inp->sctp_context = (*inp_p)->sctp_context; inp->local_strreset_support = (*inp_p)->local_strreset_support; + inp->fibnum = (*inp_p)->fibnum; inp->inp_starting_point_for_iterator = NULL; #if defined(__Userspace__) inp->ulp_info = (*inp_p)->ulp_info; @@ -3306,7 +3361,8 @@ sctp_handle_shutdown_complete(struct sctp_shutdown_complete_chunk *cp SCTP_UNUSE } #endif /* stop the timer */ - sctp_timer_stop(SCTP_TIMER_TYPE_SHUTDOWNACK, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INPUT+SCTP_LOC_22); + sctp_timer_stop(SCTP_TIMER_TYPE_SHUTDOWNACK, stcb->sctp_ep, stcb, net, + SCTP_FROM_SCTP_INPUT + SCTP_LOC_24); SCTP_STAT_INCR_COUNTER32(sctps_shutdown); /* free the TCB */ SCTPDBG(SCTP_DEBUG_INPUT2, @@ -3319,7 +3375,8 @@ sctp_handle_shutdown_complete(struct sctp_shutdown_complete_chunk *cp SCTP_UNUSE SCTP_TCB_LOCK(stcb); atomic_subtract_int(&stcb->asoc.refcnt, 1); #endif - (void)sctp_free_assoc(stcb->sctp_ep, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT+SCTP_LOC_23); + (void)sctp_free_assoc(stcb->sctp_ep, stcb, SCTP_NORMAL_PROC, + SCTP_FROM_SCTP_INPUT + SCTP_LOC_25); #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) SCTP_SOCKET_UNLOCK(so, 1); #endif @@ -3427,7 +3484,8 @@ process_chunk_drop(struct sctp_tcb *stcb, struct sctp_chunk_desc *desc, /* restart the timer */ sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, - stcb, tp1->whoTo, SCTP_FROM_SCTP_INPUT+SCTP_LOC_24); + stcb, tp1->whoTo, + SCTP_FROM_SCTP_INPUT + SCTP_LOC_26); sctp_timer_start(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, tp1->whoTo); @@ -3495,7 +3553,8 @@ process_chunk_drop(struct sctp_tcb *stcb, struct sctp_chunk_desc *desc, * this, otherwise we let the timer fire. */ sctp_timer_stop(SCTP_TIMER_TYPE_INIT, stcb->sctp_ep, - stcb, net, SCTP_FROM_SCTP_INPUT+SCTP_LOC_25); + stcb, net, + SCTP_FROM_SCTP_INPUT + SCTP_LOC_27); sctp_send_initiate(stcb->sctp_ep, stcb, SCTP_SO_NOT_LOCKED); } break; @@ -3612,6 +3671,28 @@ sctp_reset_out_streams(struct sctp_tcb *stcb, uint32_t number_entries, uint16_t sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_SEND, stcb, number_entries, (void *)list, SCTP_SO_NOT_LOCKED); } +static void +sctp_reset_clear_pending(struct sctp_tcb *stcb, uint32_t number_entries, uint16_t *list) +{ + uint32_t i; + uint16_t temp; + + if (number_entries > 0) { + for (i = 0; i < number_entries; i++) { + temp = ntohs(list[i]); + if (temp >= stcb->asoc.streamoutcnt) { + /* no such stream */ + continue; + } + stcb->asoc.strmout[temp].state = SCTP_STREAM_OPEN; + } + } else { + for (i = 0; i < stcb->asoc.streamoutcnt; i++) { + stcb->asoc.strmout[i].state = SCTP_STREAM_OPEN; + } + } +} + struct sctp_stream_reset_request * sctp_find_stream_reset(struct sctp_tcb *stcb, uint32_t seq, struct sctp_tmit_chunk **bchk) @@ -3669,7 +3750,8 @@ sctp_clean_up_stream_reset(struct sctp_tcb *stcb) } asoc = &stcb->asoc; - sctp_timer_stop(SCTP_TIMER_TYPE_STRRESET, stcb->sctp_ep, stcb, chk->whoTo, SCTP_FROM_SCTP_INPUT+SCTP_LOC_26); + sctp_timer_stop(SCTP_TIMER_TYPE_STRRESET, stcb->sctp_ep, stcb, + chk->whoTo, SCTP_FROM_SCTP_INPUT + SCTP_LOC_28); TAILQ_REMOVE(&asoc->control_send_queue, chk, sctp_next); @@ -3679,7 +3761,7 @@ sctp_clean_up_stream_reset(struct sctp_tcb *stcb) } asoc->ctrl_queue_cnt--; sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED); - /*sa_ignore NO_NULL_CHK*/ + /*sa_ignore NO_NULL_CHK*/ stcb->asoc.str_reset = NULL; } @@ -3709,6 +3791,8 @@ sctp_handle_stream_reset_response(struct sctp_tcb *stcb, type = ntohs(req_param->ph.param_type); lparm_len = ntohs(req_param->ph.param_length); if (type == SCTP_STR_RESET_OUT_REQUEST) { + int no_clear = 0; + req_out_param = (struct sctp_stream_reset_out_request *)req_param; number_entries = (lparm_len - sizeof(struct sctp_stream_reset_out_request)) / sizeof(uint16_t); asoc->stream_reset_out_is_outstanding = 0; @@ -3719,9 +3803,18 @@ sctp_handle_stream_reset_response(struct sctp_tcb *stcb, sctp_reset_out_streams(stcb, number_entries, req_out_param->list_of_streams); } else if (action == SCTP_STREAM_RESET_RESULT_DENIED) { sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_DENIED_OUT, stcb, number_entries, req_out_param->list_of_streams, SCTP_SO_NOT_LOCKED); + } else if (action == SCTP_STREAM_RESET_RESULT_IN_PROGRESS) { + /* Set it up so we don't stop retransmitting */ + asoc->stream_reset_outstanding++; + stcb->asoc.str_reset_seq_out--; + asoc->stream_reset_out_is_outstanding = 1; + no_clear = 1; } else { sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_FAILED_OUT, stcb, number_entries, req_out_param->list_of_streams, SCTP_SO_NOT_LOCKED); } + if (no_clear == 0) { + sctp_reset_clear_pending(stcb, number_entries, req_out_param->list_of_streams); + } } else if (type == SCTP_STR_RESET_IN_REQUEST) { req_in_param = (struct sctp_stream_reset_in_request *)req_param; number_entries = (lparm_len - sizeof(struct sctp_stream_reset_in_request)) / sizeof(uint16_t); @@ -3748,7 +3841,11 @@ sctp_handle_stream_reset_response(struct sctp_tcb *stcb, asoc->stream_reset_outstanding--; if (action == SCTP_STREAM_RESET_RESULT_PERFORMED) { /* Put the new streams into effect */ - stcb->asoc.streamoutcnt += num_stream; + int i; + for ( i = asoc->streamoutcnt; i< (asoc->streamoutcnt + num_stream); i++) { + asoc->strmout[i].state = SCTP_STREAM_OPEN; + } + asoc->streamoutcnt += num_stream; sctp_notify_stream_reset_add(stcb, stcb->asoc.streamincnt, stcb->asoc.streamoutcnt, 0); } else if (action == SCTP_STREAM_RESET_RESULT_DENIED) { sctp_notify_stream_reset_add(stcb, stcb->asoc.streamincnt, stcb->asoc.streamoutcnt, @@ -3825,6 +3922,9 @@ sctp_handle_stream_reset_response(struct sctp_tcb *stcb, } } } + if (asoc->stream_reset_outstanding == 0) { + sctp_send_stream_reset_out_if_possible(stcb, SCTP_SO_NOT_LOCKED); + } return (0); } @@ -3855,22 +3955,33 @@ sctp_handle_str_reset_request_in(struct sctp_tcb *stcb, } else if (stcb->asoc.stream_reset_out_is_outstanding == 0) { len = ntohs(req->ph.param_length); number_entries = ((len - sizeof(struct sctp_stream_reset_in_request)) / sizeof(uint16_t)); - for (i = 0; i < number_entries; i++) { - temp = ntohs(req->list_of_streams[i]); - req->list_of_streams[i] = temp; + if (number_entries) { + for (i = 0; i < number_entries; i++) { + temp = ntohs(req->list_of_streams[i]); + if (temp >= stcb->asoc.streamoutcnt) { + asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; + goto bad_boy; + } + req->list_of_streams[i] = temp; + } + for (i = 0; i < number_entries; i++) { + if (stcb->asoc.strmout[req->list_of_streams[i]].state == SCTP_STREAM_OPEN) { + stcb->asoc.strmout[req->list_of_streams[i]].state = SCTP_STREAM_RESET_PENDING; + } + } + } else { + /* Its all */ + for (i = 0; i < stcb->asoc.streamoutcnt; i++) { + if (stcb->asoc.strmout[i].state == SCTP_STREAM_OPEN) + stcb->asoc.strmout[i].state = SCTP_STREAM_RESET_PENDING; + } } asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_PERFORMED; - sctp_add_stream_reset_out(chk, number_entries, req->list_of_streams, - asoc->str_reset_seq_out, - seq, (asoc->sending_seq - 1)); - asoc->stream_reset_out_is_outstanding = 1; - asoc->str_reset = chk; - sctp_timer_start(SCTP_TIMER_TYPE_STRRESET, stcb->sctp_ep, stcb, chk->whoTo); - stcb->asoc.stream_reset_outstanding++; } else { /* Can't do it, since we have sent one out */ asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_ERR_IN_PROGRESS; } + bad_boy: sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]); asoc->str_reset_seq_in++; } else if (asoc->str_reset_seq_in - 1 == seq) { @@ -3880,6 +3991,7 @@ sctp_handle_str_reset_request_in(struct sctp_tcb *stcb, } else { sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_RESULT_ERR_BAD_SEQNO); } + sctp_send_stream_reset_out_if_possible(stcb, SCTP_SO_NOT_LOCKED); } static int @@ -3998,11 +4110,12 @@ sctp_handle_str_reset_request_out(struct sctp_tcb *stcb, sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]); return; } + liste->seq = seq; liste->tsn = tsn; liste->number_entries = number_entries; memcpy(&liste->list_of_streams, req->list_of_streams, number_entries * sizeof(uint16_t)); TAILQ_INSERT_TAIL(&asoc->resetHead, liste, next_resp); - asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_PERFORMED; + asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_IN_PROGRESS; } sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]); asoc->str_reset_seq_in++; @@ -4140,7 +4253,7 @@ sctp_handle_str_reset_add_out_strm(struct sctp_tcb *stcb, struct sctp_tmit_chunk mychk += num_stream; if (mychk < 0x10000) { stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_RESULT_PERFORMED; - if (sctp_send_str_reset_req(stcb, 0, NULL, 0, 0, 0, 1, num_stream, 0, 1)) { + if (sctp_send_str_reset_req(stcb, 0, NULL, 0, 0, 1, num_stream, 0, 1)) { stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; } } else { @@ -4518,7 +4631,7 @@ sctp_process_control(struct mbuf *m, int iphlen, int *offset, int length, struct sctphdr *sh, struct sctp_chunkhdr *ch, struct sctp_inpcb *inp, struct sctp_tcb *stcb, struct sctp_nets **netp, int *fwd_tsn_seen, #if defined(__FreeBSD__) - uint8_t mflowtype, uint32_t mflowid, + uint8_t mflowtype, uint32_t mflowid, uint16_t fibnum, #endif uint32_t vrf_id, uint16_t port) { @@ -4675,13 +4788,13 @@ sctp_process_control(struct mbuf *m, int iphlen, int *offset, int length, } } if (stcb == NULL) { - snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s\n", __FILE__, __LINE__, __FUNCTION__); + snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s", __FILE__, __LINE__, __func__); op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), msg); /* no association, so it's out of the blue... */ sctp_handle_ootb(m, iphlen, *offset, src, dst, sh, inp, op_err, #if defined(__FreeBSD__) - mflowtype, mflowid, + mflowtype, mflowid, inp->fibnum, #endif vrf_id, port); *offset = length; @@ -4721,13 +4834,13 @@ sctp_process_control(struct mbuf *m, int iphlen, int *offset, int length, if (locked_tcb) { SCTP_TCB_UNLOCK(locked_tcb); } - snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s\n", __FILE__, __LINE__, __FUNCTION__); + snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s", __FILE__, __LINE__, __func__); op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), msg); sctp_handle_ootb(m, iphlen, *offset, src, dst, sh, inp, op_err, #if defined(__FreeBSD__) - mflowtype, mflowid, + mflowtype, mflowid, fibnum, #endif vrf_id, port); return (NULL); @@ -4870,15 +4983,11 @@ sctp_process_control(struct mbuf *m, int iphlen, int *offset, int length, /* The INIT chunk must be the only chunk. */ if ((num_chunks > 1) || (length - *offset > (int)SCTP_SIZE32(chk_length))) { - op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), - "INIT not the only chunk"); - sctp_abort_association(inp, stcb, m, iphlen, - src, dst, sh, op_err, -#if defined(__FreeBSD__) - mflowtype, mflowid, -#endif - vrf_id, port); + /* RFC 4960 requires that no ABORT is sent */ *offset = length; + if (locked_tcb) { + SCTP_TCB_UNLOCK(locked_tcb); + } return (NULL); } /* Honor our resource limit. */ @@ -4929,7 +5038,8 @@ sctp_process_control(struct mbuf *m, int iphlen, int *offset, int length, SCTP_TCB_LOCK(stcb); atomic_subtract_int(&stcb->asoc.refcnt, 1); #endif - (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT+SCTP_LOC_27); + (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, + SCTP_FROM_SCTP_INPUT + SCTP_LOC_29); #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) SCTP_SOCKET_UNLOCK(so, 1); #endif @@ -5348,7 +5458,8 @@ sctp_process_control(struct mbuf *m, int iphlen, int *offset, int length, SCTP_TCB_LOCK(stcb); atomic_subtract_int(&stcb->asoc.refcnt, 1); #endif - (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT+SCTP_LOC_27); + (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, + SCTP_FROM_SCTP_INPUT + SCTP_LOC_30); #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) SCTP_SOCKET_UNLOCK(so, 1); #endif @@ -5527,7 +5638,8 @@ sctp_process_control(struct mbuf *m, int iphlen, int *offset, int length, SCTP_TCB_LOCK(stcb); atomic_subtract_int(&stcb->asoc.refcnt, 1); #endif - (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT+SCTP_LOC_29); + (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, + SCTP_FROM_SCTP_INPUT + SCTP_LOC_31); #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) SCTP_SOCKET_UNLOCK(so, 1); #endif @@ -5640,39 +5752,27 @@ sctp_process_control(struct mbuf *m, int iphlen, int *offset, int length, unknown_chunk: /* it's an unknown chunk! */ if ((ch->chunk_type & 0x40) && (stcb != NULL)) { - struct mbuf *mm; - struct sctp_paramhdr *phd; + struct sctp_gen_error_cause *cause; int len; - mm = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr), - 0, M_NOWAIT, 1, MT_DATA); - if (mm) { + op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_gen_error_cause), + 0, M_NOWAIT, 1, MT_DATA); + if (op_err != NULL) { len = min(SCTP_SIZE32(chk_length), (uint32_t)(length - *offset)); - phd = mtod(mm, struct sctp_paramhdr *); - /* - * We cheat and use param type since - * we did not bother to define a - * error cause struct. They are the - * same basic format with different - * names. - */ - phd->param_type = htons(SCTP_CAUSE_UNRECOG_CHUNK); - phd->param_length = htons(len + sizeof(*phd)); - SCTP_BUF_LEN(mm) = sizeof(*phd); - SCTP_BUF_NEXT(mm) = SCTP_M_COPYM(m, *offset, len, M_NOWAIT); - if (SCTP_BUF_NEXT(mm)) { - if (sctp_pad_lastmbuf(SCTP_BUF_NEXT(mm), SCTP_SIZE32(len) - len, NULL) == NULL) { - sctp_m_freem(mm); - } else { + cause = mtod(op_err, struct sctp_gen_error_cause *); + cause->code = htons(SCTP_CAUSE_UNRECOG_CHUNK); + cause->length = htons(len + sizeof(struct sctp_gen_error_cause)); + SCTP_BUF_LEN(op_err) = sizeof(struct sctp_gen_error_cause); + SCTP_BUF_NEXT(op_err) = SCTP_M_COPYM(m, *offset, len, M_NOWAIT); + if (SCTP_BUF_NEXT(op_err) != NULL) { #ifdef SCTP_MBUF_LOGGING - if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) { - sctp_log_mbc(SCTP_BUF_NEXT(mm), SCTP_MBUF_ICOPY); - } -#endif - sctp_queue_op_err(stcb, mm); + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) { + sctp_log_mbc(SCTP_BUF_NEXT(op_err), SCTP_MBUF_ICOPY); } +#endif + sctp_queue_op_err(stcb, op_err); } else { - sctp_m_freem(mm); + sctp_m_freem(op_err); } } } @@ -5710,31 +5810,6 @@ sctp_process_control(struct mbuf *m, int iphlen, int *offset, int length, } -#ifdef INVARIANTS -#ifdef __GNUC__ -__attribute__((noinline)) -#endif -void -sctp_validate_no_locks(struct sctp_inpcb *inp) -{ -#ifndef __APPLE__ - struct sctp_tcb *lstcb; - - LIST_FOREACH(lstcb, &inp->sctp_asoc_list, sctp_tcblist) { - if (mtx_owned(&lstcb->tcb_mtx)) { - panic("Own lock on stcb at return from input"); - } - } - if (mtx_owned(&inp->inp_create_mtx)) { - panic("Own create lock on inp"); - } - if (mtx_owned(&inp->inp_mtx)) { - panic("Own inp lock on inp"); - } -#endif -} -#endif - /* * common input chunk processing (v4 and v6) */ @@ -5747,7 +5822,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt #endif uint8_t ecn_bits, #if defined(__FreeBSD__) - uint8_t mflowtype, uint32_t mflowid, + uint8_t mflowtype, uint32_t mflowid, uint16_t fibnum, #endif uint32_t vrf_id, uint16_t port) { @@ -5788,8 +5863,9 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt } #endif #if defined(__FreeBSD__) - if ((net != NULL) && (mflowtype != M_HASHTYPE_NONE)) { + if (net != NULL) { net->flowtype = mflowtype; + net->flowid = mflowid; } #endif if ((inp != NULL) && (stcb != NULL)) { @@ -5820,8 +5896,9 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt } #endif #if defined(__FreeBSD__) - if ((net != NULL) && (mflowtype != M_HASHTYPE_NONE)) { + if (net != NULL) { net->flowtype = mflowtype; + net->flowid = mflowid; } #endif if (inp == NULL) { @@ -5834,7 +5911,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt if (ch->chunk_type == SCTP_SHUTDOWN_ACK) { sctp_send_shutdown_complete2(src, dst, sh, #if defined(__FreeBSD__) - mflowtype, mflowid, + mflowtype, mflowid, fibnum, #endif vrf_id, port); goto out; @@ -5851,7 +5928,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt sctp_send_abort(m, iphlen, src, dst, sh, 0, op_err, #if defined(__FreeBSD__) - mflowtype, mflowid, + mflowtype, mflowid, fibnum, #endif vrf_id, port); } @@ -5907,12 +5984,12 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt */ SCTP_TCB_UNLOCK(stcb); stcb = NULL; - snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s\n", __FILE__, __LINE__, __FUNCTION__); + snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s", __FILE__, __LINE__, __func__); op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), msg); sctp_handle_ootb(m, iphlen, offset, src, dst, sh, inp, op_err, #if defined(__FreeBSD__) - mflowtype, mflowid, + mflowtype, mflowid, inp->fibnum, #endif vrf_id, port); goto out; @@ -5926,7 +6003,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt src, dst, sh, ch, inp, stcb, &net, &fwd_tsn_seen, #if defined(__FreeBSD__) - mflowtype, mflowid, + mflowtype, mflowid, fibnum, #endif vrf_id, port); if (stcb) { @@ -5935,7 +6012,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt */ inp = stcb->sctp_ep; #if defined(INET) || defined(INET6) - if ((net) && (port)) { + if ((net != NULL) && (port != 0)) { if (net->port == 0) { sctp_pathmtu_adjustment(stcb, net->mtu - sizeof(struct udphdr)); } @@ -5963,12 +6040,12 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt } if (stcb == NULL) { /* out of the blue DATA chunk */ - snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s\n", __FILE__, __LINE__, __FUNCTION__); + snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s", __FILE__, __LINE__, __func__); op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), msg); sctp_handle_ootb(m, iphlen, offset, src, dst, sh, inp, op_err, #if defined(__FreeBSD__) - mflowtype, mflowid, + mflowtype, mflowid, fibnum, #endif vrf_id, port); goto out; @@ -6038,12 +6115,12 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt /* * We consider OOTB any data sent during asoc setup. */ - snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s\n", __FILE__, __LINE__, __FUNCTION__); + snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s", __FILE__, __LINE__, __func__); op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), msg); sctp_handle_ootb(m, iphlen, offset, src, dst, sh, inp, op_err, #if defined(__FreeBSD__) - mflowtype, mflowid, + mflowtype, mflowid, inp->fibnum, #endif vrf_id, port); goto out; @@ -6063,12 +6140,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt } /* plow through the data chunks while length > offset */ retval = sctp_process_data(mm, iphlen, &offset, length, - src, dst, sh, - inp, stcb, net, &high_tsn, -#if defined(__FreeBSD__) - mflowtype, mflowid, -#endif - vrf_id, port); + inp, stcb, net, &high_tsn); if (retval == 2) { /* * The association aborted, NO UNLOCK needed since @@ -6122,7 +6194,7 @@ trigger_send: if (!TAILQ_EMPTY(&stcb->asoc.control_send_queue)) { cnt_ctrl_ready = stcb->asoc.ctrl_queue_cnt - stcb->asoc.ecn_echo_cnt_onq; } - if (cnt_ctrl_ready || + if (cnt_ctrl_ready || stcb->asoc.trigger_reset || ((un_sent) && (stcb->asoc.peers_rwnd > 0 || (stcb->asoc.peers_rwnd <= 0 && stcb->asoc.total_flight == 0)))) { @@ -6144,11 +6216,6 @@ trigger_send: SCTP_INP_DECR_REF(inp_decr); SCTP_INP_WUNLOCK(inp_decr); } -#ifdef INVARIANTS - if (inp != NULL) { - sctp_validate_no_locks(inp); - } -#endif return; } @@ -6185,6 +6252,7 @@ sctp_input(i_pak, va_alist) #if defined(__FreeBSD__) uint32_t mflowid; uint8_t mflowtype; + uint16_t fibnum; #endif #if !(defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)) uint16_t port = 0; @@ -6255,6 +6323,7 @@ sctp_input(i_pak, va_alist) #if defined(__FreeBSD__) mflowid = m->m_pkthdr.flowid; mflowtype = M_HASHTYPE_GET(m); + fibnum = M_GETFIB(m); #endif SCTP_STAT_INCR(sctps_recvpackets); SCTP_STAT_INCR_COUNTER64(sctps_inpackets); @@ -6351,7 +6420,7 @@ sctp_input(i_pak, va_alist) #endif ecn_bits, #if defined(__FreeBSD__) - mflowtype, mflowid, + mflowtype, mflowid, fibnum, #endif vrf_id, port); out: @@ -6365,7 +6434,7 @@ sctp_input(i_pak, va_alist) extern int *sctp_cpuarry; #endif -#if defined(__FreeBSD__) && __FreeBSD_version >= 1100020 +#if defined(__FreeBSD__) && __FreeBSD_version >= 1100020 int sctp_input(struct mbuf **mp, int *offp, int proto SCTP_UNUSED) { @@ -6397,7 +6466,7 @@ sctp_input(struct mbuf *m, int off) if (SCTP_BUF_LEN(m) < offset) { if ((m = m_pullup(m, offset)) == NULL) { SCTP_STAT_INCR(sctps_hdrops); -#if defined(__FreeBSD__) && __FreeBSD_version >= 1100020 +#if defined(__FreeBSD__) && __FreeBSD_version >= 1100020 return (IPPROTO_DONE); #else return; @@ -6413,7 +6482,7 @@ sctp_input(struct mbuf *m, int off) } cpu_to_use = sctp_cpuarry[flowid % mp_ncpus]; sctp_queue_to_mcore(m, off, cpu_to_use); -#if defined(__FreeBSD__) && __FreeBSD_version >= 1100020 +#if defined(__FreeBSD__) && __FreeBSD_version >= 1100020 return (IPPROTO_DONE); #else return; @@ -6421,7 +6490,7 @@ sctp_input(struct mbuf *m, int off) } #endif sctp_input_with_port(m, off, 0); -#if defined(__FreeBSD__) && __FreeBSD_version >= 1100020 +#if defined(__FreeBSD__) && __FreeBSD_version >= 1100020 return (IPPROTO_DONE); #endif } diff --git a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_input.h b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_input.h index 5d45fef20c3..866f480a888 100755 --- a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_input.h +++ b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_input.h @@ -32,7 +32,7 @@ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_input.h 273168 2014-10-16 15:36:04Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp_input.h 284515 2015-06-17 15:20:14Z tuexen $"); #endif #ifndef _NETINET_SCTP_INPUT_H_ @@ -48,7 +48,7 @@ sctp_common_input_processing(struct mbuf **, int, int, int, #endif uint8_t, #if defined(__FreeBSD__) - uint8_t, uint32_t, + uint8_t, uint32_t, uint16_t, #endif uint32_t, uint16_t); diff --git a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_lock_userspace.h b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_lock_userspace.h index 83a565c371c..83a565c371c 100755 --- a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_lock_userspace.h +++ b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_lock_userspace.h diff --git a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_os.h b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_os.h index 48883811a1e..48883811a1e 100755 --- a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_os.h +++ b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_os.h diff --git a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_os_userspace.h b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_os_userspace.h index 13df4242388..a261deb01b8 100755 --- a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_os_userspace.h +++ b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_os_userspace.h @@ -530,7 +530,6 @@ struct sx {int dummy;}; #endif #if !defined(__Userspace_os_Windows) #include <netinet/ip6.h> -#include <netinet/icmp6.h> #endif #if defined(__Userspace_os_Darwin) || defined(__Userspace_os_FreeBSD) || defined(__Userspace_os_Linux) || defined(__Userspace_os_NetBSD) || defined(__Userspace_os_OpenBSD) || defined(__Userspace_os_Windows) #include "user_ip6_var.h" @@ -810,8 +809,6 @@ sctp_hashfreedestroy(void *vhashtbl, struct malloc_type *type, u_long hashmask); /*__Userspace__ defining KTR_SUBSYS 1 as done in sctp_os_macosx.h */ #define KTR_SUBSYS 1 -#define sctp_get_tick_count() (ticks) - /* The packed define for 64 bit platforms */ #if !defined(__Userspace_os_Windows) #define SCTP_PACKED __attribute__((packed)) @@ -888,7 +885,7 @@ static inline void sctp_userspace_rtalloc(sctp_route_t *ro) * SCTP_GET_IF_INDEX_FROM_ROUTE macro. */ } -#define SCTP_RTALLOC(ro, vrf_id) sctp_userspace_rtalloc((sctp_route_t *)ro) +#define SCTP_RTALLOC(ro, vrf_id, fibnum) sctp_userspace_rtalloc((sctp_route_t *)ro) /* dummy rtfree needed once user_route.h is included */ static inline void sctp_userspace_rtfree(sctp_rtentry_t *rt) @@ -949,13 +946,6 @@ int sctp_userspace_get_mtu_from_ifn(uint32_t if_index, int af); #define SCTP_GET_HEADER_FOR_OUTPUT(o_pak) 0 #define SCTP_RELEASE_HEADER(m) #define SCTP_RELEASE_PKT(m) sctp_m_freem(m) -/* UDP __Userspace__ - dummy definition */ -#define SCTP_ENABLE_UDP_CSUM(m) m=m -/* BSD definition */ -/* #define SCTP_ENABLE_UDP_CSUM(m) do { \ */ -/* m->m_pkthdr.csum_flags = CSUM_UDP; \ */ -/* m->m_pkthdr.csum_data = offsetof(struct udphdr, uh_sum); \ */ -/* } while (0) */ #define SCTP_GET_PKT_VRFID(m, vrf_id) ((vrf_id = SCTP_DEFAULT_VRFID) != SCTP_DEFAULT_VRFID) @@ -1050,6 +1040,14 @@ struct sockaddr_conn { void *sconn_addr; }; +typedef void *(*start_routine_t)(void *); + +extern int +sctp_userspace_thread_create(userland_thread_t *thread, start_routine_t start_routine); + +void +sctp_userspace_set_threadname(const char *name); + /* * SCTP protocol specific mbuf flags. */ @@ -1127,7 +1125,7 @@ sctp_get_mbuf_for_msg(unsigned int space_needed, int want_header, int how, int a #endif #define I_AM_HERE \ do { \ - SCTP_PRINTF("%s:%d at %s\n", __FILE__, __LINE__ , __FUNCTION__); \ + SCTP_PRINTF("%s:%d at %s\n", __FILE__, __LINE__ , __func__); \ } while (0) #ifndef timevalsub diff --git a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_output.c b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_output.c index 49447fa9da4..3a58970ae41 100755 --- a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_output.c +++ b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_output.c @@ -32,7 +32,7 @@ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_output.c 280371 2015-03-23 15:12:02Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp_output.c 292060 2015-12-10 11:49:32Z tuexen $"); #endif #include <netinet/sctp_os.h> @@ -2470,7 +2470,7 @@ sctp_is_addr_restricted(struct sctp_tcb *stcb, struct sctp_ifa *ifa) LIST_FOREACH(laddr, &stcb->asoc.sctp_restricted_addrs, sctp_nxt_addr) { if (laddr->ifa == NULL) { SCTPDBG(SCTP_DEBUG_OUTPUT1, "%s: NULL ifa\n", - __FUNCTION__); + __func__); continue; } if (laddr->ifa == ifa) { @@ -2492,7 +2492,7 @@ sctp_is_addr_in_ep(struct sctp_inpcb *inp, struct sctp_ifa *ifa) LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) { if (laddr->ifa == NULL) { SCTPDBG(SCTP_DEBUG_OUTPUT1, "%s: NULL ifa\n", - __FUNCTION__); + __func__); continue; } if ((laddr->ifa == ifa) && laddr->action == 0) @@ -3242,8 +3242,6 @@ again_with_private_addresses_allowed: sifa = NULL; continue; } - } else { - SCTP_PRINTF("Stcb is null - no print\n"); } atomic_add_int(&sifa->refcount, 1); goto out; @@ -3472,7 +3470,7 @@ sctp_source_address_selection(struct sctp_inpcb *inp, /* * Need a route to cache. */ - SCTP_RTALLOC(ro, vrf_id); + SCTP_RTALLOC(ro, vrf_id, inp->fibnum); } if (ro->ro_rt == NULL) { return (NULL); @@ -3747,6 +3745,7 @@ sctp_process_cmsgs_for_init(struct sctp_tcb *stcb, struct mbuf *control, int *er #endif stcb->asoc.strmout[i].stream_no = i; stcb->asoc.strmout[i].last_msg_incomplete = 0; + stcb->asoc.strmout[i].state = SCTP_STREAM_OPENING; stcb->asoc.ss_functions.sctp_ss_init_stream(&stcb->asoc.strmout[i], NULL); } } @@ -4175,7 +4174,7 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp, sctp_route_t iproute; int len; - len = sizeof(struct ip) + sizeof(struct sctphdr); + len = SCTP_MIN_V4_OVERHEAD; if (port) { len += sizeof(struct udphdr); } @@ -4238,10 +4237,13 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp, } #if defined(__FreeBSD__) /* FreeBSD has a function for ip_id's */ - ip->ip_id = ip_newid(); -#elif defined(RANDOM_IP_ID) - /* Apple has RANDOM_IP_ID switch */ - ip->ip_id = htons(ip_randomid()); + ip_fillid(ip); +#elif defined(__APPLE__) +#if RANDOM_IP_ID + ip->ip_id = ip_randomid(); +#else + ip->ip_id = htons(ip_id++); +#endif #elif defined(__Userspace__) ip->ip_id = htons(SCTP_IP_ID(inp)++); #else @@ -4324,7 +4326,7 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp, sctp_free_ifa(_lsrc); } else { ip->ip_src = over_addr->sin.sin_addr; - SCTP_RTALLOC(ro, vrf_id); + SCTP_RTALLOC(ro, vrf_id, inp->fibnum); } } if (port) { @@ -4403,6 +4405,7 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp, sctphdr->checksum = sctp_calculate_cksum(m, sizeof(struct ip) + sizeof(struct udphdr)); SCTP_STAT_INCR(sctps_sendswcrc); #endif +#if !defined(__Windows__) && !defined(__Userspace__) #if defined(__FreeBSD__) && ((__FreeBSD_version > 803000 && __FreeBSD_version < 900000) || __FreeBSD_version > 900000) if (V_udp_cksum) { SCTP_ENABLE_UDP_CSUM(o_pak); @@ -4410,6 +4413,7 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp, #else SCTP_ENABLE_UDP_CSUM(o_pak); #endif +#endif } else { #if defined(SCTP_WITH_NO_CSUM) SCTP_STAT_INCR(sctps_sendnocrc); @@ -4529,7 +4533,7 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp, #endif } flowlabel &= 0x000fffff; - len = sizeof(struct ip6_hdr) + sizeof(struct sctphdr); + len = SCTP_MIN_OVERHEAD; if (port) { len += sizeof(struct udphdr); } @@ -4727,7 +4731,7 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp, sctp_free_ifa(_lsrc); } else { lsa6->sin6_addr = over_addr->sin6.sin6_addr; - SCTP_RTALLOC(ro, vrf_id); + SCTP_RTALLOC(ro, vrf_id, inp->fibnum); } #ifdef SCTP_EMBEDDED_V6_SCOPE #ifdef SCTP_KAME @@ -5468,10 +5472,11 @@ sctp_arethere_unrecognized_parameters(struct mbuf *in_initpkt, if (op_err == NULL) { /* Ok need to try to get a mbuf */ #ifdef INET6 - l_len = sizeof(struct ip6_hdr) + sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr); + l_len = SCTP_MIN_OVERHEAD; #else - l_len = sizeof(struct ip) + sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr); + l_len = SCTP_MIN_V4_OVERHEAD; #endif + l_len += sizeof(struct sctp_chunkhdr); l_len += plen; l_len += sizeof(struct sctp_paramhdr); op_err = sctp_get_mbuf_for_msg(l_len, 0, M_NOWAIT, 1, MT_DATA); @@ -5534,10 +5539,11 @@ sctp_arethere_unrecognized_parameters(struct mbuf *in_initpkt, int l_len; /* Ok need to try to get an mbuf */ #ifdef INET6 - l_len = sizeof(struct ip6_hdr) + sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr); + l_len = SCTP_MIN_OVERHEAD; #else - l_len = sizeof(struct ip) + sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr); + l_len = SCTP_MIN_V4_OVERHEAD; #endif + l_len += sizeof(struct sctp_chunkhdr); l_len += plen; l_len += sizeof(struct sctp_paramhdr); op_err = sctp_get_mbuf_for_msg(l_len, 0, M_NOWAIT, 1, MT_DATA); @@ -5608,10 +5614,11 @@ sctp_arethere_unrecognized_parameters(struct mbuf *in_initpkt, if ((op_err == NULL) && phdr) { int l_len; #ifdef INET6 - l_len = sizeof(struct ip6_hdr) + sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr); + l_len = SCTP_MIN_OVERHEAD; #else - l_len = sizeof(struct ip) + sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr); + l_len = SCTP_MIN_V4_OVERHEAD; #endif + l_len += sizeof(struct sctp_chunkhdr); l_len += (2 * sizeof(struct sctp_paramhdr)); op_err = sctp_get_mbuf_for_msg(l_len, 0, M_NOWAIT, 1, MT_DATA); if (op_err) { @@ -5873,7 +5880,7 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb, "Address added"); sctp_send_abort(init_pkt, iphlen, src, dst, sh, 0, op_err, #if defined(__FreeBSD__) - mflowtype, mflowid, + mflowtype, mflowid, inp->fibnum, #endif vrf_id, port); return; @@ -5887,14 +5894,14 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb, if (op_err == NULL) { char msg[SCTP_DIAG_INFO_LEN]; - snprintf(msg, sizeof(msg), "%s:%d at %s\n", __FILE__, __LINE__, __FUNCTION__); + snprintf(msg, sizeof(msg), "%s:%d at %s", __FILE__, __LINE__, __func__); op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), msg); } sctp_send_abort(init_pkt, iphlen, src, dst, sh, init_chk->init.initiate_tag, op_err, #if defined(__FreeBSD__) - mflowtype, mflowid, + mflowtype, mflowid, inp->fibnum, #endif vrf_id, port); return; @@ -5967,11 +5974,7 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb, stc.ipv4_addr_legal = 1; #endif } -#ifdef SCTP_DONT_DO_PRIVADDR_SCOPE - stc.ipv4_scope = 1; -#else stc.ipv4_scope = 0; -#endif if (net == NULL) { to = src; switch (dst->sa_family) { @@ -5992,13 +5995,10 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb, stc.laddr_type = SCTP_IPV4_ADDRESS; /* scope_id is only for v6 */ stc.scope_id = 0; -#ifndef SCTP_DONT_DO_PRIVADDR_SCOPE - if (IN4_ISPRIVATE_ADDRESS(&src4->sin_addr)) { + if ((IN4_ISPRIVATE_ADDRESS(&src4->sin_addr)) || + (IN4_ISPRIVATE_ADDRESS(&dst4->sin_addr))){ stc.ipv4_scope = 1; } -#else - stc.ipv4_scope = 1; -#endif /* SCTP_DONT_DO_PRIVADDR_SCOPE */ /* Must use the address in this case */ if (sctp_is_address_on_local_host(src, vrf_id)) { stc.loopback_scope = 1; @@ -6024,14 +6024,15 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb, stc.local_scope = 0; stc.site_scope = 1; stc.ipv4_scope = 1; - } else if (IN6_IS_ADDR_LINKLOCAL(&src6->sin6_addr)) { + } else if (IN6_IS_ADDR_LINKLOCAL(&src6->sin6_addr) || + IN6_IS_ADDR_LINKLOCAL(&dst6->sin6_addr)) { /* - * If the new destination is a LINK_LOCAL we - * must have common both site and local - * scope. Don't set local scope though since - * we must depend on the source to be added - * implicitly. We cannot assure just because - * we share one link that all links are + * If the new destination or source is a + * LINK_LOCAL we must have common both site and + * local scope. Don't set local scope though + * since we must depend on the source to be + * added implicitly. We cannot assure just + * because we share one link that all links are * common. */ #if defined(__APPLE__) @@ -6049,10 +6050,12 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb, */ cnt_inits_to = 1; /* pull out the scope_id from incoming pkt */ - } else if (IN6_IS_ADDR_SITELOCAL(&src6->sin6_addr)) { + } else if (IN6_IS_ADDR_SITELOCAL(&src6->sin6_addr) || + IN6_IS_ADDR_SITELOCAL(&dst6->sin6_addr)) { /* - * If the new destination is SITE_LOCAL then - * we must have site scope in common. + * If the new destination or source is + * SITE_LOCAL then we must have site scope in + * common. */ stc.site_scope = 1; } @@ -6263,10 +6266,10 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb, his_limit = ntohs(init_chk->init.num_inbound_streams); /* choose what I want */ if (asoc != NULL) { - if (asoc->streamoutcnt > inp->sctp_ep.pre_open_stream_count) { + if (asoc->streamoutcnt > asoc->pre_open_streams) { i_want = asoc->streamoutcnt; } else { - i_want = inp->sctp_ep.pre_open_stream_count; + i_want = asoc->pre_open_streams; } } else { i_want = inp->sctp_ep.pre_open_stream_count; @@ -6356,7 +6359,7 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb, padding_len = SCTP_SIZE32(parameter_len) - parameter_len; chunk_len += parameter_len; } - + /* add authentication parameters */ if (((asoc != NULL) && (asoc->auth_supported == 1)) || ((asoc == NULL) && (inp->auth_supported == 1))) { @@ -7102,10 +7105,17 @@ sctp_sendall_iterator(struct sctp_inpcb *inp, struct sctp_tcb *stcb, void *ptr, if (TAILQ_EMPTY(&asoc->send_queue) && TAILQ_EMPTY(&asoc->sent_queue) && (asoc->state & SCTP_STATE_PARTIAL_MSG_LEFT)) { + struct mbuf *op_err; + char msg[SCTP_DIAG_INFO_LEN]; + abort_anyway: + snprintf(msg, sizeof(msg), + "%s:%d at %s", __FILE__, __LINE__, __func__); + op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), + msg); atomic_add_int(&stcb->asoc.refcnt, 1); sctp_abort_an_association(stcb->sctp_ep, stcb, - NULL, SCTP_SO_NOT_LOCKED); + op_err, SCTP_SO_NOT_LOCKED); atomic_add_int(&stcb->asoc.refcnt, -1); goto no_chunk_output; } @@ -7594,6 +7604,11 @@ one_more_time: } atomic_subtract_int(&asoc->stream_queue_cnt, 1); TAILQ_REMOVE(&strq->outqueue, sp, next); + if ((strq->state == SCTP_STREAM_RESET_PENDING) && + (strq->chunks_on_queues == 0) && + TAILQ_EMPTY(&strq->outqueue)) { + stcb->asoc.trigger_reset = 1; + } stcb->asoc.ss_functions.sctp_ss_remove_from_stream(stcb, asoc, strq, sp, send_lock_up); if (sp->net) { sctp_free_remote_addr(sp->net); @@ -7989,6 +8004,11 @@ re_look: send_lock_up = 1; } TAILQ_REMOVE(&strq->outqueue, sp, next); + if ((strq->state == SCTP_STREAM_RESET_PENDING) && + (strq->chunks_on_queues == 0) && + TAILQ_EMPTY(&strq->outqueue)) { + stcb->asoc.trigger_reset = 1; + } stcb->asoc.ss_functions.sctp_ss_remove_from_stream(stcb, asoc, strq, sp, send_lock_up); if (sp->net) { sctp_free_remote_addr(sp->net); @@ -8225,7 +8245,7 @@ sctp_med_chunk_output(struct sctp_inpcb *inp, #endif SCTP_TCB_LOCK_ASSERT(stcb); hbflag = 0; - if ((control_only) || (asoc->stream_reset_outstanding)) + if (control_only) no_data_chunks = 1; else no_data_chunks = 0; @@ -8396,12 +8416,12 @@ again_one_more_time: switch (((struct sockaddr *)&net->ro._l_addr)->sa_family) { #ifdef INET case AF_INET: - mtu = net->mtu - (sizeof(struct ip) + sizeof(struct sctphdr)); + mtu = net->mtu - SCTP_MIN_V4_OVERHEAD; break; #endif #ifdef INET6 case AF_INET6: - mtu = net->mtu - (sizeof(struct ip6_hdr) + sizeof(struct sctphdr)); + mtu = net->mtu - SCTP_MIN_OVERHEAD; break; #endif #if defined(__Userspace__) @@ -8428,6 +8448,7 @@ again_one_more_time: } else { r_mtu = mtu; } + error = 0; /************************/ /* ASCONF transmission */ /************************/ @@ -8553,6 +8574,12 @@ again_one_more_time: * appropriate source address * selection. */ + if (*now_filled == 0) { + (void)SCTP_GETTIME_TIMEVAL(now); + *now_filled = 1; + } + net->last_sent_time = *now; + hbflag = 0; if ((error = sctp_lowlevel_chunk_output(inp, stcb, net, (struct sockaddr *)&net->ro._l_addr, outchain, auth_offset, auth, @@ -8565,21 +8592,15 @@ again_one_more_time: 0, 0, #endif so_locked))) { - if (error == ENOBUFS) { - asoc->ifp_had_enobuf = 1; - SCTP_STAT_INCR(sctps_lowlevelerr); - } + /* error, we could not output */ + SCTPDBG(SCTP_DEBUG_OUTPUT3, "Gak send error %d\n", error); if (from_where == 0) { SCTP_STAT_INCR(sctps_lowlevelerrusr); } - if (*now_filled == 0) { - (void)SCTP_GETTIME_TIMEVAL(&net->last_sent_time); - *now_filled = 1; - *now = net->last_sent_time; - } else { - net->last_sent_time = *now; + if (error == ENOBUFS) { + asoc->ifp_had_enobuf = 1; + SCTP_STAT_INCR(sctps_lowlevelerr); } - hbflag = 0; /* error, could not output */ if (error == EHOSTUNREACH) { /* @@ -8590,17 +8611,10 @@ again_one_more_time: sctp_move_chunks_from_net(stcb, net); } *reason_code = 7; - continue; - } else - asoc->ifp_had_enobuf = 0; - if (*now_filled == 0) { - (void)SCTP_GETTIME_TIMEVAL(&net->last_sent_time); - *now_filled = 1; - *now = net->last_sent_time; + break; } else { - net->last_sent_time = *now; + asoc->ifp_had_enobuf = 0; } - hbflag = 0; /* * increase the number we sent, if a * cookie is sent we don't tell them @@ -8638,6 +8652,10 @@ again_one_more_time: } } } + if (error != 0) { + /* try next net */ + continue; + } /************************/ /* Control transmission */ /************************/ @@ -8769,7 +8787,8 @@ again_one_more_time: /* turn off the timer */ if (SCTP_OS_TIMER_PENDING(&stcb->asoc.dack_timer.timer)) { sctp_timer_stop(SCTP_TIMER_TYPE_RECV, - inp, stcb, net, SCTP_FROM_SCTP_OUTPUT+SCTP_LOC_1); + inp, stcb, net, + SCTP_FROM_SCTP_OUTPUT + SCTP_LOC_1); } } ctl_cnt++; @@ -8822,6 +8841,15 @@ again_one_more_time: sctp_timer_start(SCTP_TIMER_TYPE_COOKIE, inp, stcb, net); cookie = 0; } + /* Only HB or ASCONF advances time */ + if (hbflag) { + if (*now_filled == 0) { + (void)SCTP_GETTIME_TIMEVAL(now); + *now_filled = 1; + } + net->last_sent_time = *now; + hbflag = 0; + } if ((error = sctp_lowlevel_chunk_output(inp, stcb, net, (struct sockaddr *)&net->ro._l_addr, outchain, @@ -8835,23 +8863,14 @@ again_one_more_time: 0, 0, #endif so_locked))) { - if (error == ENOBUFS) { - asoc->ifp_had_enobuf = 1; - SCTP_STAT_INCR(sctps_lowlevelerr); - } + /* error, we could not output */ + SCTPDBG(SCTP_DEBUG_OUTPUT3, "Gak send error %d\n", error); if (from_where == 0) { SCTP_STAT_INCR(sctps_lowlevelerrusr); } - /* error, could not output */ - if (hbflag) { - if (*now_filled == 0) { - (void)SCTP_GETTIME_TIMEVAL(&net->last_sent_time); - *now_filled = 1; - *now = net->last_sent_time; - } else { - net->last_sent_time = *now; - } - hbflag = 0; + if (error == ENOBUFS) { + asoc->ifp_had_enobuf = 1; + SCTP_STAT_INCR(sctps_lowlevelerr); } if (error == EHOSTUNREACH) { /* @@ -8862,19 +8881,9 @@ again_one_more_time: sctp_move_chunks_from_net(stcb, net); } *reason_code = 7; - continue; - } else + break; + } else { asoc->ifp_had_enobuf = 0; - /* Only HB or ASCONF advances time */ - if (hbflag) { - if (*now_filled == 0) { - (void)SCTP_GETTIME_TIMEVAL(&net->last_sent_time); - *now_filled = 1; - *now = net->last_sent_time; - } else { - net->last_sent_time = *now; - } - hbflag = 0; } /* * increase the number we sent, if a @@ -8913,6 +8922,10 @@ again_one_more_time: } } } + if (error != 0) { + /* try next net */ + continue; + } /* JRI: if dest is in PF state, do not send data to it */ if ((asoc->sctp_cmt_on_off > 0) && (net != stcb->asoc.alternate) && @@ -8957,16 +8970,16 @@ again_one_more_time: switch (((struct sockaddr *)&net->ro._l_addr)->sa_family) { #ifdef INET case AF_INET: - if (net->mtu > (sizeof(struct ip) + sizeof(struct sctphdr))) - omtu = net->mtu - (sizeof(struct ip) + sizeof(struct sctphdr)); + if (net->mtu > SCTP_MIN_V4_OVERHEAD) + omtu = net->mtu - SCTP_MIN_V4_OVERHEAD; else omtu = 0; break; #endif #ifdef INET6 case AF_INET6: - if (net->mtu > (sizeof(struct ip6_hdr) + sizeof(struct sctphdr))) - omtu = net->mtu - (sizeof(struct ip6_hdr) + sizeof(struct sctphdr)); + if (net->mtu > SCTP_MIN_OVERHEAD) + omtu = net->mtu - SCTP_MIN_OVERHEAD; else omtu = 0; break; @@ -8985,7 +8998,8 @@ again_one_more_time: omtu = 0; break; } - if ((((asoc->state & SCTP_STATE_OPEN) == SCTP_STATE_OPEN) && + if ((((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) || + (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) && (skip_data_for_this_net == 0)) || (cookie)) { TAILQ_FOREACH_SAFE(chk, &asoc->send_queue, sctp_next, nchk) { @@ -9164,6 +9178,14 @@ again_one_more_time: */ sctp_timer_start(SCTP_TIMER_TYPE_SEND, inp, stcb, net); } + if (bundle_at || hbflag) { + /* For data/asconf and hb set time */ + if (*now_filled == 0) { + (void)SCTP_GETTIME_TIMEVAL(now); + *now_filled = 1; + } + net->last_sent_time = *now; + } /* Now send it, if there is anything to send :> */ if ((error = sctp_lowlevel_chunk_output(inp, stcb, @@ -9184,23 +9206,13 @@ again_one_more_time: #endif so_locked))) { /* error, we could not output */ - if (error == ENOBUFS) { - SCTP_STAT_INCR(sctps_lowlevelerr); - asoc->ifp_had_enobuf = 1; - } + SCTPDBG(SCTP_DEBUG_OUTPUT3, "Gak send error %d\n", error); if (from_where == 0) { SCTP_STAT_INCR(sctps_lowlevelerrusr); } - SCTPDBG(SCTP_DEBUG_OUTPUT3, "Gak send error %d\n", error); - if (hbflag) { - if (*now_filled == 0) { - (void)SCTP_GETTIME_TIMEVAL(&net->last_sent_time); - *now_filled = 1; - *now = net->last_sent_time; - } else { - net->last_sent_time = *now; - } - hbflag = 0; + if (error == ENOBUFS) { + SCTP_STAT_INCR(sctps_lowlevelerr); + asoc->ifp_had_enobuf = 1; } if (error == EHOSTUNREACH) { /* @@ -9224,16 +9236,6 @@ again_one_more_time: endoutchain = NULL; auth = NULL; auth_offset = 0; - if (bundle_at || hbflag) { - /* For data/asconf and hb set time */ - if (*now_filled == 0) { - (void)SCTP_GETTIME_TIMEVAL(&net->last_sent_time); - *now_filled = 1; - *now = net->last_sent_time; - } else { - net->last_sent_time = *now; - } - } if (!no_out_cnt) { *num_out += (ctl_cnt + bundle_at); } @@ -9295,9 +9297,37 @@ sctp_queue_op_err(struct sctp_tcb *stcb, struct mbuf *op_err) */ struct sctp_chunkhdr *hdr; struct sctp_tmit_chunk *chk; - struct mbuf *mat; + struct mbuf *mat, *last_mbuf; + uint32_t chunk_length; + uint16_t padding_length; SCTP_TCB_LOCK_ASSERT(stcb); + SCTP_BUF_PREPEND(op_err, sizeof(struct sctp_chunkhdr), M_NOWAIT); + if (op_err == NULL) { + return; + } + last_mbuf = NULL; + chunk_length = 0; + for (mat = op_err; mat != NULL; mat = SCTP_BUF_NEXT(mat)) { + chunk_length += SCTP_BUF_LEN(mat); + if (SCTP_BUF_NEXT(mat) == NULL) { + last_mbuf = mat; + } + } + if (chunk_length > SCTP_MAX_CHUNK_LENGTH) { + sctp_m_freem(op_err); + return; + } + padding_length = chunk_length % 4; + if (padding_length != 0) { + padding_length = 4 - padding_length; + } + if (padding_length != 0) { + if (sctp_add_pad_tombuf(last_mbuf, padding_length) == NULL) { + sctp_m_freem(op_err); + return; + } + } sctp_alloc_a_chunk(stcb, chk); if (chk == NULL) { /* no memory */ @@ -9305,15 +9335,7 @@ sctp_queue_op_err(struct sctp_tcb *stcb, struct mbuf *op_err) return; } chk->copy_by_ref = 0; - SCTP_BUF_PREPEND(op_err, sizeof(struct sctp_chunkhdr), M_NOWAIT); - if (op_err == NULL) { - sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED); - return; - } - chk->send_size = 0; - for (mat = op_err; mat != NULL; mat = SCTP_BUF_NEXT(mat)) { - chk->send_size += SCTP_BUF_LEN(mat); - } + chk->send_size = (uint16_t)chunk_length; chk->sent = SCTP_DATAGRAM_UNSENT; chk->snd_count = 0; chk->asoc = &stcb->asoc; @@ -9323,9 +9345,7 @@ sctp_queue_op_err(struct sctp_tcb *stcb, struct mbuf *op_err) hdr->chunk_type = SCTP_OPERATION_ERROR; hdr->chunk_flags = 0; hdr->chunk_length = htons(chk->send_size); - TAILQ_INSERT_TAIL(&chk->asoc->control_send_queue, - chk, - sctp_next); + TAILQ_INSERT_TAIL(&chk->asoc->control_send_queue, chk, sctp_next); chk->asoc->ctrl_queue_cnt++; } @@ -9919,12 +9939,16 @@ sctp_chunk_retransmission(struct sctp_inpcb *inp, } if ((SCTP_BASE_SYSCTL(sctp_max_retran_chunk)) && (chk->snd_count >= SCTP_BASE_SYSCTL(sctp_max_retran_chunk))) { - /* Gak, we have exceeded max unlucky retran, abort! */ - SCTP_PRINTF("Gak, chk->snd_count:%d >= max:%d - send abort\n", - chk->snd_count, - SCTP_BASE_SYSCTL(sctp_max_retran_chunk)); + struct mbuf *op_err; + char msg[SCTP_DIAG_INFO_LEN]; + + snprintf(msg, sizeof(msg), "TSN %8.8x retransmitted %d times, giving up", + chk->rec.data.TSN_seq, chk->snd_count); + op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), + msg); atomic_add_int(&stcb->asoc.refcnt, 1); - sctp_abort_an_association(stcb->sctp_ep, stcb, NULL, so_locked); + sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, + so_locked); SCTP_TCB_LOCK(stcb); atomic_subtract_int(&stcb->asoc.refcnt, 1); return (SCTP_RETRAN_EXIT); @@ -10240,7 +10264,7 @@ sctp_chunk_retransmission(struct sctp_inpcb *inp, * t3-expiring. */ sctp_timer_stop(SCTP_TIMER_TYPE_SEND, inp, stcb, net, - SCTP_FROM_SCTP_OUTPUT+SCTP_LOC_4); + SCTP_FROM_SCTP_OUTPUT + SCTP_LOC_2); sctp_timer_start(SCTP_TIMER_TYPE_SEND, inp, stcb, net); } } @@ -10338,6 +10362,7 @@ sctp_chunk_output (struct sctp_inpcb *inp, } #endif asoc = &stcb->asoc; +do_it_again: /* The Nagle algorithm is only applied when handling a send call. */ if (from_where == SCTP_OUTPUT_FROM_USR_SEND) { if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NODELAY)) { @@ -10355,7 +10380,8 @@ sctp_chunk_output (struct sctp_inpcb *inp, if ((un_sent <= 0) && (TAILQ_EMPTY(&asoc->control_send_queue)) && (TAILQ_EMPTY(&asoc->asconf_send_queue)) && - (asoc->sent_queue_retran_cnt == 0)) { + (asoc->sent_queue_retran_cnt == 0) && + (asoc->trigger_reset == 0)) { /* Nothing to do unless there is something to be sent left */ return; } @@ -10566,6 +10592,12 @@ sctp_chunk_output (struct sctp_inpcb *inp, */ if (stcb->asoc.ecn_echo_cnt_onq) sctp_fix_ecn_echo(asoc); + + if (stcb->asoc.trigger_reset) { + if (sctp_send_stream_reset_out_if_possible(stcb, so_locked) == 0) { + goto do_it_again; + } + } return; } @@ -10869,7 +10901,8 @@ sctp_send_sack(struct sctp_tcb *stcb, int so_locked /* No memory so we drop the idea, and set a timer */ if (stcb->asoc.delayed_ack) { sctp_timer_stop(SCTP_TIMER_TYPE_RECV, - stcb->sctp_ep, stcb, NULL, SCTP_FROM_SCTP_OUTPUT + SCTP_LOC_5); + stcb->sctp_ep, stcb, NULL, + SCTP_FROM_SCTP_OUTPUT + SCTP_LOC_3); sctp_timer_start(SCTP_TIMER_TYPE_RECV, stcb->sctp_ep, stcb, NULL); } else { @@ -10891,32 +10924,17 @@ sctp_send_sack(struct sctp_tcb *stcb, int so_locked a_chk->sent = SCTP_DATAGRAM_UNSENT; a_chk->whoTo = NULL; - if ((asoc->numduptsns) || - (!(asoc->last_data_chunk_from->dest_state & SCTP_ADDR_REACHABLE))) { + if (!(asoc->last_data_chunk_from->dest_state & SCTP_ADDR_REACHABLE)) { /*- - * Ok, we have some duplicates or the destination for the - * sack is unreachable, lets see if we can select an - * alternate than asoc->last_data_chunk_from + * Ok, the destination for the SACK is unreachable, lets see if + * we can select an alternate to asoc->last_data_chunk_from */ - if ((asoc->last_data_chunk_from->dest_state & SCTP_ADDR_REACHABLE) && - (asoc->used_alt_onsack > asoc->numnets)) { - /* We used an alt last time, don't this time */ - a_chk->whoTo = NULL; - } else { - asoc->used_alt_onsack++; - a_chk->whoTo = sctp_find_alternate_net(stcb, asoc->last_data_chunk_from, 0); - } + a_chk->whoTo = sctp_find_alternate_net(stcb, asoc->last_data_chunk_from, 0); if (a_chk->whoTo == NULL) { /* Nope, no alternate */ a_chk->whoTo = asoc->last_data_chunk_from; - asoc->used_alt_onsack = 0; } } else { - /* - * No duplicates so we use the last place we received data - * from. - */ - asoc->used_alt_onsack = 0; a_chk->whoTo = asoc->last_data_chunk_from; } if (a_chk->whoTo) { @@ -10952,7 +10970,8 @@ sctp_send_sack(struct sctp_tcb *stcb, int so_locked /* sa_ignore NO_NULL_CHK */ if (stcb->asoc.delayed_ack) { sctp_timer_stop(SCTP_TIMER_TYPE_RECV, - stcb->sctp_ep, stcb, NULL, SCTP_FROM_SCTP_OUTPUT + SCTP_LOC_6); + stcb->sctp_ep, stcb, NULL, + SCTP_FROM_SCTP_OUTPUT + SCTP_LOC_4); sctp_timer_start(SCTP_TIMER_TYPE_RECV, stcb->sctp_ep, stcb, NULL); } else { @@ -11359,7 +11378,7 @@ static void sctp_send_resp_msg(struct sockaddr *src, struct sockaddr *dst, struct sctphdr *sh, uint32_t vtag, uint8_t type, struct mbuf *cause, - uint8_t mflowtype, uint32_t mflowid, + uint8_t mflowtype, uint32_t mflowid, uint16_t fibnum, uint32_t vrf_id, uint16_t port) #else static void @@ -11465,6 +11484,7 @@ sctp_send_resp_msg(struct sockaddr *src, struct sockaddr *dst, SCTP_BUF_LEN(mout) = len; SCTP_BUF_NEXT(mout) = cause; #if defined(__FreeBSD__) + M_SETFIB(mout, fibnum); mout->m_pkthdr.flowid = mflowid; M_HASHTYPE_SET(mout, mflowtype); #endif @@ -11483,18 +11503,20 @@ sctp_send_resp_msg(struct sockaddr *src, struct sockaddr *dst, ip->ip_v = IPVERSION; ip->ip_hl = (sizeof(struct ip) >> 2); ip->ip_tos = 0; + ip->ip_off = 0; #if defined(__FreeBSD__) - ip->ip_id = ip_newid(); + ip_fillid(ip); #elif defined(__APPLE__) #if RANDOM_IP_ID ip->ip_id = ip_randomid(); #else ip->ip_id = htons(ip_id++); #endif -#else +#elif defined(__Userspace__) ip->ip_id = htons(ip_id++); +#else + ip->ip_id = ip_id++; #endif - ip->ip_off = 0; ip->ip_ttl = MODULE_GLOBAL(ip_defttl); if (port) { ip->ip_p = IPPROTO_UDP; @@ -11628,6 +11650,7 @@ sctp_send_resp_msg(struct sockaddr *src, struct sockaddr *dst, shout->checksum = sctp_calculate_cksum(mout, sizeof(struct ip) + sizeof(struct udphdr)); SCTP_STAT_INCR(sctps_sendswcrc); #endif +#if !defined(__Windows__) && !defined(__Userspace__) #if defined(__FreeBSD__) && ((__FreeBSD_version > 803000 && __FreeBSD_version < 900000) || __FreeBSD_version > 900000) if (V_udp_cksum) { SCTP_ENABLE_UDP_CSUM(o_pak); @@ -11635,6 +11658,7 @@ sctp_send_resp_msg(struct sockaddr *src, struct sockaddr *dst, #else SCTP_ENABLE_UDP_CSUM(o_pak); #endif +#endif } else { #if defined(SCTP_WITH_NO_CSUM) SCTP_STAT_INCR(sctps_sendnocrc); @@ -11754,13 +11778,13 @@ void sctp_send_shutdown_complete2(struct sockaddr *src, struct sockaddr *dst, struct sctphdr *sh, #if defined(__FreeBSD__) - uint8_t mflowtype, uint32_t mflowid, + uint8_t mflowtype, uint32_t mflowid, uint16_t fibnum, #endif uint32_t vrf_id, uint16_t port) { sctp_send_resp_msg(src, dst, sh, 0, SCTP_SHUTDOWN_COMPLETE, NULL, #if defined(__FreeBSD__) - mflowtype, mflowid, + mflowtype, mflowid, fibnum, #endif vrf_id, port); } @@ -11893,6 +11917,11 @@ sctp_send_hb(struct sctp_tcb *stcb, struct sctp_nets *net,int so_locked break; #endif default: + if (chk->data) { + sctp_m_freem(chk->data); + chk->data = NULL; + } + sctp_free_a_chunk(stcb, chk, so_locked); return; break; } @@ -12173,30 +12202,60 @@ sctp_send_cwr(struct sctp_tcb *stcb, struct sctp_nets *net, uint32_t high_tsn, u asoc->ctrl_queue_cnt++; } -void -sctp_add_stream_reset_out(struct sctp_tmit_chunk *chk, - int number_entries, uint16_t * list, +static int +sctp_add_stream_reset_out(struct sctp_tcb *stcb, struct sctp_tmit_chunk *chk, uint32_t seq, uint32_t resp_seq, uint32_t last_sent) { uint16_t len, old_len, i; struct sctp_stream_reset_out_request *req_out; struct sctp_chunkhdr *ch; + int at; + int number_entries=0; ch = mtod(chk->data, struct sctp_chunkhdr *); old_len = len = SCTP_SIZE32(ntohs(ch->chunk_length)); - /* get to new offset for the param. */ req_out = (struct sctp_stream_reset_out_request *)((caddr_t)ch + len); /* now how long will this param be? */ + for (i = 0; i < stcb->asoc.streamoutcnt; i++) { + if ((stcb->asoc.strmout[i].state == SCTP_STREAM_RESET_PENDING) && + (stcb->asoc.strmout[i].chunks_on_queues == 0) && + TAILQ_EMPTY(&stcb->asoc.strmout[i].outqueue)) { + number_entries++; + } + } + if (number_entries == 0) { + return (0); + } + if (number_entries == stcb->asoc.streamoutcnt) { + number_entries = 0; + } + if (number_entries > SCTP_MAX_STREAMS_AT_ONCE_RESET) { + number_entries = SCTP_MAX_STREAMS_AT_ONCE_RESET; + } len = (sizeof(struct sctp_stream_reset_out_request) + (sizeof(uint16_t) * number_entries)); req_out->ph.param_type = htons(SCTP_STR_RESET_OUT_REQUEST); req_out->ph.param_length = htons(len); req_out->request_seq = htonl(seq); req_out->response_seq = htonl(resp_seq); req_out->send_reset_at_tsn = htonl(last_sent); + at = 0; if (number_entries) { - for (i = 0; i < number_entries; i++) { - req_out->list_of_streams[i] = htons(list[i]); + for (i = 0; i < stcb->asoc.streamoutcnt; i++) { + if ((stcb->asoc.strmout[i].state == SCTP_STREAM_RESET_PENDING) && + (stcb->asoc.strmout[i].chunks_on_queues == 0) && + TAILQ_EMPTY(&stcb->asoc.strmout[i].outqueue)) { + req_out->list_of_streams[at] = htons(i); + at++; + stcb->asoc.strmout[i].state = SCTP_STREAM_RESET_IN_FLIGHT; + if (at >= number_entries) { + break; + } + } + } + } else { + for (i = 0; i < stcb->asoc.streamoutcnt; i++) { + stcb->asoc.strmout[i].state = SCTP_STREAM_RESET_IN_FLIGHT; } } if (SCTP_SIZE32(len) > len) { @@ -12213,7 +12272,7 @@ sctp_add_stream_reset_out(struct sctp_tmit_chunk *chk, chk->book_size_scale = 0; chk->send_size = SCTP_SIZE32(chk->book_size); SCTP_BUF_LEN(chk->data) = chk->send_size; - return; + return (1); } static void @@ -12315,6 +12374,68 @@ sctp_add_stream_reset_result(struct sctp_tmit_chunk *chk, } void +sctp_send_deferred_reset_response(struct sctp_tcb *stcb, + struct sctp_stream_reset_list *ent, + int response) +{ + struct sctp_association *asoc; + struct sctp_tmit_chunk *chk; + struct sctp_chunkhdr *ch; + + asoc = &stcb->asoc; + + /* + * Reset our last reset action to the new one IP -> response + * (PERFORMED probably). This assures that if we fail to send, a + * retran from the peer will get the new response. + */ + asoc->last_reset_action[0] = response; + if (asoc->stream_reset_outstanding) { + return; + } + sctp_alloc_a_chunk(stcb, chk); + if (chk == NULL) { + SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, ENOMEM); + return; + } + chk->copy_by_ref = 0; + chk->rec.chunk_id.id = SCTP_STREAM_RESET; + chk->rec.chunk_id.can_take_data = 0; + chk->flags = 0; + chk->asoc = &stcb->asoc; + chk->book_size = sizeof(struct sctp_chunkhdr); + chk->send_size = SCTP_SIZE32(chk->book_size); + chk->book_size_scale = 0; + chk->data = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_NOWAIT, 1, MT_DATA); + if (chk->data == NULL) { + sctp_free_a_chunk(stcb, chk, SCTP_SO_LOCKED); + SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, ENOMEM); + return; + } + SCTP_BUF_RESV_UF(chk->data, SCTP_MIN_OVERHEAD); + sctp_add_stream_reset_result(chk, ent->seq, response); + /* setup chunk parameters */ + chk->sent = SCTP_DATAGRAM_UNSENT; + chk->snd_count = 0; + if (stcb->asoc.alternate) { + chk->whoTo = stcb->asoc.alternate; + } else { + chk->whoTo = stcb->asoc.primary_destination; + } + ch = mtod(chk->data, struct sctp_chunkhdr *); + ch->chunk_type = SCTP_STREAM_RESET; + ch->chunk_flags = 0; + ch->chunk_length = htons(chk->book_size); + atomic_add_int(&chk->whoTo->ref_count, 1); + SCTP_BUF_LEN(chk->data) = chk->send_size; + /* insert the chunk for sending */ + TAILQ_INSERT_TAIL(&asoc->control_send_queue, + chk, + sctp_next); + asoc->ctrl_queue_cnt++; +} + +void sctp_add_stream_reset_result_tsn(struct sctp_tmit_chunk *chk, uint32_t resp_seq, uint32_t result, uint32_t send_una, uint32_t recv_next) @@ -12412,19 +12533,90 @@ sctp_add_an_in_stream(struct sctp_tmit_chunk *chk, } int +sctp_send_stream_reset_out_if_possible(struct sctp_tcb *stcb, int so_locked) +{ + struct sctp_association *asoc; + struct sctp_tmit_chunk *chk; + struct sctp_chunkhdr *ch; + uint32_t seq; + + asoc = &stcb->asoc; + asoc->trigger_reset = 0; + if (asoc->stream_reset_outstanding) { + return (EALREADY); + } + sctp_alloc_a_chunk(stcb, chk); + if (chk == NULL) { + SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, ENOMEM); + return (ENOMEM); + } + chk->copy_by_ref = 0; + chk->rec.chunk_id.id = SCTP_STREAM_RESET; + chk->rec.chunk_id.can_take_data = 0; + chk->flags = 0; + chk->asoc = &stcb->asoc; + chk->book_size = sizeof(struct sctp_chunkhdr); + chk->send_size = SCTP_SIZE32(chk->book_size); + chk->book_size_scale = 0; + chk->data = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_NOWAIT, 1, MT_DATA); + if (chk->data == NULL) { + sctp_free_a_chunk(stcb, chk, so_locked); + SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, ENOMEM); + return (ENOMEM); + } + SCTP_BUF_RESV_UF(chk->data, SCTP_MIN_OVERHEAD); + + /* setup chunk parameters */ + chk->sent = SCTP_DATAGRAM_UNSENT; + chk->snd_count = 0; + if (stcb->asoc.alternate) { + chk->whoTo = stcb->asoc.alternate; + } else { + chk->whoTo = stcb->asoc.primary_destination; + } + ch = mtod(chk->data, struct sctp_chunkhdr *); + ch->chunk_type = SCTP_STREAM_RESET; + ch->chunk_flags = 0; + ch->chunk_length = htons(chk->book_size); + atomic_add_int(&chk->whoTo->ref_count, 1); + SCTP_BUF_LEN(chk->data) = chk->send_size; + seq = stcb->asoc.str_reset_seq_out; + if (sctp_add_stream_reset_out(stcb, chk, seq, (stcb->asoc.str_reset_seq_in - 1), (stcb->asoc.sending_seq - 1))) { + seq++; + asoc->stream_reset_outstanding++; + } else { + m_freem(chk->data); + chk->data = NULL; + sctp_free_a_chunk(stcb, chk, so_locked); + return (ENOENT); + } + asoc->str_reset = chk; + /* insert the chunk for sending */ + TAILQ_INSERT_TAIL(&asoc->control_send_queue, + chk, + sctp_next); + asoc->ctrl_queue_cnt++; + + if (stcb->asoc.send_sack) { + sctp_send_sack(stcb, so_locked); + } + sctp_timer_start(SCTP_TIMER_TYPE_STRRESET, stcb->sctp_ep, stcb, chk->whoTo); + return (0); +} + +int sctp_send_str_reset_req(struct sctp_tcb *stcb, uint16_t number_entries, uint16_t *list, - uint8_t send_out_req, uint8_t send_in_req, uint8_t send_tsn_req, uint8_t add_stream, uint16_t adding_o, uint16_t adding_i, uint8_t peer_asked) { - struct sctp_association *asoc; struct sctp_tmit_chunk *chk; struct sctp_chunkhdr *ch; + int can_send_out_req=0; uint32_t seq; asoc = &stcb->asoc; @@ -12435,16 +12627,18 @@ sctp_send_str_reset_req(struct sctp_tcb *stcb, SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, EBUSY); return (EBUSY); } - if ((send_out_req == 0) && (send_in_req == 0) && (send_tsn_req == 0) && + if ((send_in_req == 0) && (send_tsn_req == 0) && (add_stream == 0)) { /* nothing to do */ SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, EINVAL); return (EINVAL); } - if (send_tsn_req && (send_out_req || send_in_req)) { + if (send_tsn_req && send_in_req) { /* error, can't do that */ SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, EINVAL); return (EINVAL); + } else if (send_in_req) { + can_send_out_req = 1; } if (number_entries > (MCLBYTES - SCTP_MIN_OVERHEAD - @@ -12492,12 +12686,13 @@ sctp_send_str_reset_req(struct sctp_tcb *stcb, SCTP_BUF_LEN(chk->data) = chk->send_size; seq = stcb->asoc.str_reset_seq_out; - if (send_out_req) { - sctp_add_stream_reset_out(chk, number_entries, list, - seq, (stcb->asoc.str_reset_seq_in - 1), (stcb->asoc.sending_seq - 1)); - asoc->stream_reset_out_is_outstanding = 1; - seq++; - asoc->stream_reset_outstanding++; + if (can_send_out_req) { + int ret; + ret = sctp_add_stream_reset_out(stcb, chk, seq, (stcb->asoc.str_reset_seq_in - 1), (stcb->asoc.sending_seq - 1)); + if (ret) { + seq++; + asoc->stream_reset_outstanding++; + } } if ((add_stream & 1) && ((stcb->asoc.strm_realoutsize - stcb->asoc.streamoutcnt) < adding_o)) { @@ -12512,7 +12707,7 @@ sctp_send_str_reset_req(struct sctp_tcb *stcb, oldstream = stcb->asoc.strmout; /* get some more */ SCTP_MALLOC(stcb->asoc.strmout, struct sctp_stream_out *, - ((stcb->asoc.streamoutcnt+adding_o) * sizeof(struct sctp_stream_out)), + (stcb->asoc.streamoutcnt + adding_o) * sizeof(struct sctp_stream_out), SCTP_M_STRMO); if (stcb->asoc.strmout == NULL) { uint8_t x; @@ -12533,6 +12728,7 @@ sctp_send_str_reset_req(struct sctp_tcb *stcb, stcb->asoc.strmout[i].next_sequence_send = oldstream[i].next_sequence_send; stcb->asoc.strmout[i].last_msg_incomplete = oldstream[i].last_msg_incomplete; stcb->asoc.strmout[i].stream_no = i; + stcb->asoc.strmout[i].state = oldstream[i].state; stcb->asoc.ss_functions.sctp_ss_init_stream(&stcb->asoc.strmout[i], &oldstream[i]); /* now anything on those queues? */ TAILQ_FOREACH_SAFE(sp, &oldstream[i].outqueue, next, nsp) { @@ -12565,6 +12761,7 @@ sctp_send_str_reset_req(struct sctp_tcb *stcb, stcb->asoc.strmout[i].stream_no = i; stcb->asoc.strmout[i].last_msg_incomplete = 0; stcb->asoc.ss_functions.sctp_ss_init_stream(&stcb->asoc.strmout[i], NULL); + stcb->asoc.strmout[i].state = SCTP_STREAM_CLOSED; } stcb->asoc.strm_realoutsize = stcb->asoc.streamoutcnt + adding_o; SCTP_FREE(oldstream, SCTP_M_STRMO); @@ -12598,6 +12795,9 @@ skip_stuff: chk, sctp_next); asoc->ctrl_queue_cnt++; + if (stcb->asoc.send_sack) { + sctp_send_sack(stcb, SCTP_SO_LOCKED); + } sctp_timer_start(SCTP_TIMER_TYPE_STRRESET, stcb->sctp_ep, stcb, chk->whoTo); return (0); } @@ -12606,7 +12806,7 @@ void sctp_send_abort(struct mbuf *m, int iphlen, struct sockaddr *src, struct sockaddr *dst, struct sctphdr *sh, uint32_t vtag, struct mbuf *cause, #if defined(__FreeBSD__) - uint8_t mflowtype, uint32_t mflowid, + uint8_t mflowtype, uint32_t mflowid, uint16_t fibnum, #endif uint32_t vrf_id, uint16_t port) { @@ -12618,7 +12818,7 @@ sctp_send_abort(struct mbuf *m, int iphlen, struct sockaddr *src, struct sockadd } sctp_send_resp_msg(src, dst, sh, vtag, SCTP_ABORT_ASSOCIATION, cause, #if defined(__FreeBSD__) - mflowtype, mflowid, + mflowtype, mflowid, fibnum, #endif vrf_id, port); return; @@ -12628,13 +12828,13 @@ void sctp_send_operr_to(struct sockaddr *src, struct sockaddr *dst, struct sctphdr *sh, uint32_t vtag, struct mbuf *cause, #if defined(__FreeBSD__) - uint8_t mflowtype, uint32_t mflowid, + uint8_t mflowtype, uint32_t mflowid, uint16_t fibnum, #endif uint32_t vrf_id, uint16_t port) { sctp_send_resp_msg(src, dst, sh, vtag, SCTP_OPERATION_ERROR, cause, #if defined(__FreeBSD__) - mflowtype, mflowid, + mflowtype, mflowid, fibnum, #endif vrf_id, port); return; @@ -12746,9 +12946,7 @@ sctp_copy_one(struct sctp_stream_queue_pending *sp, struct uio *uio, int resv_upfront) { - int left; #if defined(__Panda__) - left = sp->length; sp->data = m_uiotombuf(uio, M_WAITOK, sp->length, resv_upfront, 0); if (sp->data == NULL) { @@ -12758,9 +12956,7 @@ sctp_copy_one(struct sctp_stream_queue_pending *sp, sp->tail_mbuf = m_last(sp->data); return (0); - #elif defined(__FreeBSD__) && __FreeBSD_version > 602000 - left = sp->length; sp->data = m_uiotombuf(uio, M_WAITOK, sp->length, resv_upfront, 0); if (sp->data == NULL) { @@ -12771,6 +12967,7 @@ sctp_copy_one(struct sctp_stream_queue_pending *sp, sp->tail_mbuf = m_last(sp->data); return (0); #else + int left; int cancpy, willcpy, error; struct mbuf *m, *head; int cpsz = 0; @@ -13348,6 +13545,7 @@ sctp_lower_sosend(struct socket *so, } #endif stcb = sctp_aloc_assoc(inp, addr, &error, 0, vrf_id, + inp->sctp_ep.pre_open_stream_count, #if !(defined( __Panda__) || defined(__Userspace__)) p #else @@ -13381,7 +13579,8 @@ sctp_lower_sosend(struct socket *so, if (control) { if (sctp_process_cmsgs_for_init(stcb, control, &error)) { - sctp_free_assoc(inp, stcb, SCTP_PCBFREE_FORCE, SCTP_FROM_SCTP_OUTPUT + SCTP_LOC_7); + sctp_free_assoc(inp, stcb, SCTP_PCBFREE_FORCE, + SCTP_FROM_SCTP_OUTPUT + SCTP_LOC_5); hold_tcblock = 0; stcb = NULL; goto out_unlocked; @@ -13474,12 +13673,24 @@ sctp_lower_sosend(struct socket *so, SCTP_ASOC_CREATE_UNLOCK(inp); create_lock_applied = 0; } - if (asoc->stream_reset_outstanding) { + /* Is the stream no. valid? */ + if (srcv->sinfo_stream >= asoc->streamoutcnt) { + /* Invalid stream number */ + SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL); + error = EINVAL; + goto out_unlocked; + } + if ((asoc->strmout[srcv->sinfo_stream].state != SCTP_STREAM_OPEN) && + (asoc->strmout[srcv->sinfo_stream].state != SCTP_STREAM_OPENING)) { /* * Can't queue any data while stream reset is underway. */ - SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EAGAIN); - error = EAGAIN; + if (asoc->strmout[srcv->sinfo_stream].state > SCTP_STREAM_OPEN) { + error = EAGAIN; + } else { + error = EINVAL; + } + SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, error); goto out_unlocked; } if ((SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_WAIT) || @@ -13632,13 +13843,6 @@ sctp_lower_sosend(struct socket *so, SCTP_TCB_UNLOCK(stcb); hold_tcblock = 0; } - /* Is the stream no. valid? */ - if (srcv->sinfo_stream >= asoc->streamoutcnt) { - /* Invalid stream number */ - SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL); - error = EINVAL; - goto out_unlocked; - } if (asoc->strmout == NULL) { /* huh? software error */ SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EFAULT); @@ -13979,7 +14183,7 @@ skip_preblock: /*- * Ok, Nagle is set on and we have data outstanding. * Don't send anything and let SACKs drive out the - * data unless wen have a "full" segment to send. + * data unless we have a "full" segment to send. */ if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_NAGLE_LOGGING_ENABLE) { sctp_log_nagle_event(stcb, SCTP_NAGLE_APPLIED); @@ -14213,13 +14417,20 @@ dataless_eof: if (TAILQ_EMPTY(&asoc->send_queue) && TAILQ_EMPTY(&asoc->sent_queue) && (asoc->state & SCTP_STATE_PARTIAL_MSG_LEFT)) { + struct mbuf *op_err; + char msg[SCTP_DIAG_INFO_LEN]; + abort_anyway: if (free_cnt_applied) { atomic_add_int(&stcb->asoc.refcnt, -1); free_cnt_applied = 0; } + snprintf(msg, sizeof(msg), + "%s:%d at %s", __FILE__, __LINE__, __func__); + op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), + msg); sctp_abort_an_association(stcb->sctp_ep, stcb, - NULL, SCTP_SO_LOCKED); + op_err, SCTP_SO_LOCKED); /* now relock the stcb so everything is sane */ hold_tcblock = 0; stcb = NULL; @@ -14347,7 +14558,7 @@ out_unlocked: atomic_add_int(&stcb->asoc.refcnt, -1); } #ifdef INVARIANTS -#if !defined(__APPLE__) +#if defined(__FreeBSD__) if (stcb) { if (mtx_owned(&stcb->tcb_mtx)) { panic("Leaving with tcb mtx owned?"); @@ -14385,13 +14596,6 @@ out_unlocked: } } #endif -#ifdef INVARIANTS - if (inp) { - sctp_validate_no_locks(inp); - } else { - SCTP_PRINTF("Warning - inp is NULL so cant validate locks\n"); - } -#endif if (top) { sctp_m_freem(top); } diff --git a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_output.h b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_output.h index d03bead046f..f2d4248335a 100755 --- a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_output.h +++ b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_output.h @@ -32,7 +32,7 @@ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_output.h 272751 2014-10-08 15:30:59Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp_output.h 285837 2015-07-24 14:09:03Z rrs $"); #endif #ifndef _NETINET_SCTP_OUTPUT_H_ @@ -122,7 +122,7 @@ void sctp_send_shutdown_complete(struct sctp_tcb *, struct sctp_nets *, int); void sctp_send_shutdown_complete2(struct sockaddr *, struct sockaddr *, struct sctphdr *, #if defined(__FreeBSD__) - uint8_t, uint32_t, + uint8_t, uint32_t, uint16_t, #endif uint32_t, uint16_t); @@ -197,32 +197,35 @@ void sctp_send_cwr(struct sctp_tcb *, struct sctp_nets *, uint32_t, uint8_t); void -sctp_add_stream_reset_out(struct sctp_tmit_chunk *, - int, uint16_t *, uint32_t, uint32_t, uint32_t); +sctp_add_stream_reset_result(struct sctp_tmit_chunk *, uint32_t, uint32_t); void -sctp_add_stream_reset_result(struct sctp_tmit_chunk *, uint32_t, uint32_t); +sctp_send_deferred_reset_response(struct sctp_tcb *, + struct sctp_stream_reset_list *, + int); void sctp_add_stream_reset_result_tsn(struct sctp_tmit_chunk *, uint32_t, uint32_t, uint32_t, uint32_t); +int +sctp_send_stream_reset_out_if_possible(struct sctp_tcb *, int); int -sctp_send_str_reset_req(struct sctp_tcb *, uint16_t , uint16_t *, uint8_t, +sctp_send_str_reset_req(struct sctp_tcb *, uint16_t , uint16_t *, uint8_t, uint8_t, uint8_t, uint16_t, uint16_t, uint8_t); void sctp_send_abort(struct mbuf *, int, struct sockaddr *, struct sockaddr *, struct sctphdr *, uint32_t, struct mbuf *, #if defined(__FreeBSD__) - uint8_t, uint32_t, + uint8_t, uint32_t, uint16_t, #endif uint32_t, uint16_t); void sctp_send_operr_to(struct sockaddr *, struct sockaddr *, struct sctphdr *, uint32_t, struct mbuf *, #if defined(__FreeBSD__) - uint8_t, uint32_t, + uint8_t, uint32_t, uint16_t, #endif uint32_t, uint16_t); diff --git a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_pcb.c b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_pcb.c index 2970970250a..f623b512364 100755 --- a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_pcb.c +++ b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_pcb.c @@ -32,7 +32,7 @@ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_pcb.c 280459 2015-03-24 21:12:45Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp_pcb.c 291904 2015-12-06 16:17:57Z tuexen $"); #endif #include <netinet/sctp_os.h> @@ -1285,7 +1285,7 @@ sctp_tcb_special_locate(struct sctp_inpcb **inp_p, struct sockaddr *from, LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) { if (laddr->ifa == NULL) { - SCTPDBG(SCTP_DEBUG_PCB1, "%s: NULL ifa\n", __FUNCTION__); + SCTPDBG(SCTP_DEBUG_PCB1, "%s: NULL ifa\n", __func__); continue; } if (laddr->ifa->localifa_flags & SCTP_BEING_DELETED) { @@ -2084,7 +2084,7 @@ sctp_endpoint_probe(struct sockaddr *nam, struct sctppcbhead *head, LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) { if (laddr->ifa == NULL) { SCTPDBG(SCTP_DEBUG_PCB1, "%s: NULL ifa\n", - __FUNCTION__); + __func__); continue; } SCTPDBG(SCTP_DEBUG_PCB1, "Ok laddr->ifa:%p is possible, ", @@ -2693,7 +2693,7 @@ sctp_findassociation_ep_asconf(struct mbuf *m, int offset, &parm_buf, sizeof(struct sctp_paramhdr)); if (phdr == NULL) { SCTPDBG(SCTP_DEBUG_INPUT3, "%s: failed to get asconf lookup addr\n", - __FUNCTION__); + __func__); return NULL; } ptype = (int)((uint32_t) ntohs(phdr->param_type)); @@ -2713,7 +2713,7 @@ sctp_findassociation_ep_asconf(struct mbuf *m, int offset, &p6_buf.ph, sizeof(*p6)); if (p6 == NULL) { SCTPDBG(SCTP_DEBUG_INPUT3, "%s: failed to get asconf v6 lookup addr\n", - __FUNCTION__); + __func__); return (NULL); } sin6 = &remote_store.sin6; @@ -2742,7 +2742,7 @@ sctp_findassociation_ep_asconf(struct mbuf *m, int offset, &p4_buf.ph, sizeof(*p4)); if (p4 == NULL) { SCTPDBG(SCTP_DEBUG_INPUT3, "%s: failed to get asconf v4 lookup addr\n", - __FUNCTION__); + __func__); return (NULL); } sin = &remote_store.sin; @@ -2846,6 +2846,11 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id) inp->reconfig_supported = (uint8_t)SCTP_BASE_SYSCTL(sctp_reconfig_enable); inp->nrsack_supported = (uint8_t)SCTP_BASE_SYSCTL(sctp_nrsack_enable); inp->pktdrop_supported = (uint8_t)SCTP_BASE_SYSCTL(sctp_pktdrop_enable); +#if defined(__FreeBSD__) + inp->fibnum = so->so_fibnum; +#else + inp->fibnum = 0; +#endif #if defined(__Userspace__) inp->ulp_info = NULL; inp->recv_callback = NULL; @@ -2864,16 +2869,8 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id) } #ifdef IPSEC #if !(defined(__APPLE__)) - { - struct inpcbpolicy *pcb_sp = NULL; - - error = ipsec_init_policy(so, &pcb_sp); - /* Arrange to share the policy */ - inp->ip_inp.inp.inp_sp = pcb_sp; - ((struct in6pcb *)(&inp->ip_inp.inp))->in6p_sp = pcb_sp; - } + error = ipsec_init_policy(so, &inp->ip_inp.inp.inp_sp); #else - /* not sure what to do for openbsd here */ error = 0; #endif if (error != 0) { @@ -2927,6 +2924,9 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id) so->so_pcb = NULL; #if defined(__FreeBSD__) crfree(inp->ip_inp.inp.inp_cred); +#ifdef IPSEC + ipsec_delete_pcbpolicy(&inp->ip_inp.inp); +#endif #endif SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_ep), inp); return (EOPNOTSUPP); @@ -2949,6 +2949,9 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id) so->so_pcb = NULL; #if defined(__FreeBSD__) crfree(inp->ip_inp.inp.inp_cred); +#ifdef IPSEC + ipsec_delete_pcbpolicy(&inp->ip_inp.inp); +#endif #endif SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_ep), inp); return (ENOBUFS); @@ -2963,6 +2966,9 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id) SCTP_HASH_FREE(inp->sctp_tcbhash, inp->sctp_hashmark); #if defined(__FreeBSD__) crfree(inp->ip_inp.inp.inp_cred); +#ifdef IPSEC + ipsec_delete_pcbpolicy(&inp->ip_inp.inp); +#endif #endif SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_ep), inp); return (ENOBUFS); @@ -2984,6 +2990,9 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id) so->so_pcb = NULL; #if defined(__FreeBSD__) crfree(inp->ip_inp.inp.inp_cred); +#ifdef IPSEC + ipsec_delete_pcbpolicy(&inp->ip_inp.inp); +#endif #endif SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_ep), inp); SCTP_UNLOCK_EXC(SCTP_BASE_INFO(sctbinfo).ipi_lock); @@ -3926,7 +3935,7 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from) } /* First time through we have the socket lock, after that no more. */ sctp_timer_stop(SCTP_TIMER_TYPE_NEWCOOKIE, inp, NULL, NULL, - SCTP_FROM_SCTP_PCB+SCTP_LOC_1); + SCTP_FROM_SCTP_PCB + SCTP_LOC_1); if (inp->control) { sctp_m_freem(inp->control); @@ -3970,7 +3979,7 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from) */ /* Just abandon things in the front states */ if (sctp_free_assoc(inp, asoc, SCTP_PCBFREE_NOFORCE, - SCTP_FROM_SCTP_PCB+SCTP_LOC_2) == 0) { + SCTP_FROM_SCTP_PCB + SCTP_LOC_2) == 0) { cnt_in_sd++; } continue; @@ -3986,7 +3995,7 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from) struct mbuf *op_err; op_err = sctp_generate_cause(SCTP_CAUSE_USER_INITIATED_ABT, ""); - asoc->sctp_ep->last_abort_code = SCTP_FROM_SCTP_PCB+SCTP_LOC_3; + asoc->sctp_ep->last_abort_code = SCTP_FROM_SCTP_PCB + SCTP_LOC_3; sctp_send_abort_tcb(asoc, op_err, SCTP_SO_LOCKED); SCTP_STAT_INCR_COUNTER32(sctps_aborted); if ((SCTP_GET_STATE(&asoc->asoc) == SCTP_STATE_OPEN) || @@ -3994,7 +4003,7 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from) SCTP_STAT_DECR_GAUGE32(sctps_currestab); } if (sctp_free_assoc(inp, asoc, - SCTP_PCBFREE_NOFORCE, SCTP_FROM_SCTP_PCB+SCTP_LOC_4) == 0) { + SCTP_PCBFREE_NOFORCE, SCTP_FROM_SCTP_PCB + SCTP_LOC_4) == 0) { cnt_in_sd++; } continue; @@ -4056,7 +4065,7 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from) struct mbuf *op_err; abort_anyway: op_err = sctp_generate_cause(SCTP_CAUSE_USER_INITIATED_ABT, ""); - asoc->sctp_ep->last_abort_code = SCTP_FROM_SCTP_PCB+SCTP_LOC_5; + asoc->sctp_ep->last_abort_code = SCTP_FROM_SCTP_PCB + SCTP_LOC_5; sctp_send_abort_tcb(asoc, op_err, SCTP_SO_LOCKED); SCTP_STAT_INCR_COUNTER32(sctps_aborted); if ((SCTP_GET_STATE(&asoc->asoc) == SCTP_STATE_OPEN) || @@ -4065,7 +4074,7 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from) } if (sctp_free_assoc(inp, asoc, SCTP_PCBFREE_NOFORCE, - SCTP_FROM_SCTP_PCB+SCTP_LOC_6) == 0) { + SCTP_FROM_SCTP_PCB + SCTP_LOC_6) == 0) { cnt_in_sd++; } continue; @@ -4123,7 +4132,7 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from) struct mbuf *op_err; op_err = sctp_generate_cause(SCTP_CAUSE_USER_INITIATED_ABT, ""); - asoc->sctp_ep->last_abort_code = SCTP_FROM_SCTP_PCB+SCTP_LOC_7; + asoc->sctp_ep->last_abort_code = SCTP_FROM_SCTP_PCB + SCTP_LOC_7; sctp_send_abort_tcb(asoc, op_err, SCTP_SO_LOCKED); SCTP_STAT_INCR_COUNTER32(sctps_aborted); } else if (asoc->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) { @@ -4135,7 +4144,8 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from) (SCTP_GET_STATE(&asoc->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) { SCTP_STAT_DECR_GAUGE32(sctps_currestab); } - if (sctp_free_assoc(inp, asoc, SCTP_PCBFREE_FORCE, SCTP_FROM_SCTP_PCB+SCTP_LOC_8) == 0) { + if (sctp_free_assoc(inp, asoc, SCTP_PCBFREE_FORCE, + SCTP_FROM_SCTP_PCB + SCTP_LOC_8) == 0) { cnt++; } } @@ -4246,13 +4256,9 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from) * macro here since le_next will get freed as part of the * sctp_free_assoc() call. */ - if (so) { #ifdef IPSEC - ipsec_delete_pcbpolicy(ip_pcb); -#endif /* IPSEC */ - - /* Unlocks not needed since the socket is gone now */ - } + ipsec_delete_pcbpolicy(ip_pcb); +#endif #ifndef __Panda__ if (ip_pcb->inp_options) { (void)sctp_m_free(ip_pcb->inp_options); @@ -4453,13 +4459,9 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr, sin->sin_len = sizeof(struct sockaddr_in); #endif if (set_scope) { -#ifdef SCTP_DONT_DO_PRIVADDR_SCOPE - stcb->asoc.scope.ipv4_local_scope = 1; -#else if (IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) { stcb->asoc.scope.ipv4_local_scope = 1; } -#endif /* SCTP_DONT_DO_PRIVADDR_SCOPE */ } else { /* Validate the address is in scope */ if ((IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) && @@ -4658,7 +4660,9 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr, } #endif /* SCTP_EMBEDDED_V6_SCOPE */ #endif - SCTP_RTALLOC((sctp_route_t *)&net->ro, stcb->asoc.vrf_id); + SCTP_RTALLOC((sctp_route_t *)&net->ro, + stcb->asoc.vrf_id, + stcb->sctp_ep->fibnum); #if defined(__Userspace__) net->src_addr_selected = 0; @@ -4893,7 +4897,8 @@ sctp_aloc_a_assoc_id(struct sctp_inpcb *inp, struct sctp_tcb *stcb) */ struct sctp_tcb * sctp_aloc_assoc(struct sctp_inpcb *inp, struct sockaddr *firstaddr, - int *error, uint32_t override_tag, uint32_t vrf_id, + int *error, uint32_t override_tag, uint32_t vrf_id, + uint16_t o_streams, #if defined(__FreeBSD__) && __FreeBSD_version >= 500000 struct thread *p #elif defined(__Windows__) @@ -5089,7 +5094,7 @@ sctp_aloc_assoc(struct sctp_inpcb *inp, struct sockaddr *firstaddr, /* setup back pointer's */ stcb->sctp_ep = inp; stcb->sctp_socket = inp->sctp_socket; - if ((err = sctp_init_asoc(inp, stcb, override_tag, vrf_id))) { + if ((err = sctp_init_asoc(inp, stcb, override_tag, vrf_id, o_streams))) { /* failed */ SCTP_TCB_LOCK_DESTROY(stcb); SCTP_TCB_SEND_LOCK_DESTROY(stcb); @@ -6098,7 +6103,7 @@ sctp_update_ep_vflag(struct sctp_inpcb *inp) LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) { if (laddr->ifa == NULL) { SCTPDBG(SCTP_DEBUG_PCB1, "%s: NULL ifa\n", - __FUNCTION__); + __func__); continue; } @@ -6651,6 +6656,14 @@ sctp_pcb_init() } SCTP_BASE_VAR(sctp_pcb_initialized) = 1; +#if defined(SCTP_PROCESS_LEVEL_LOCKS) +#if !defined(__Userspace_os_Windows) + pthread_mutexattr_init(&SCTP_BASE_VAR(mtx_attr)); +#ifdef INVARIANTS + pthread_mutexattr_settype(&SCTP_BASE_VAR(mtx_attr), PTHREAD_MUTEX_ERRORCHECK); +#endif +#endif +#endif #if defined(SCTP_LOCAL_TRACE_BUF) #if defined(__Windows__) if (SCTP_BASE_SYSCTL(sctp_log) != NULL) { @@ -6863,7 +6876,7 @@ sctp_pcb_finish(void) struct sctp_laddr *wi, *nwi; int i; struct sctp_iterator *it, *nit; - + #if !defined(__FreeBSD__) /* Notify the iterator to exit. */ SCTP_IPI_ITERATOR_WQ_LOCK(); @@ -6914,6 +6927,7 @@ sctp_pcb_finish(void) DeleteConditionVariable(&sctp_it_ctl.iterator_wakeup); #else pthread_cond_destroy(&sctp_it_ctl.iterator_wakeup); + pthread_mutexattr_destroy(&SCTP_BASE_VAR(mtx_attr)); #endif #endif /* In FreeBSD the iterator thread never exits @@ -7283,9 +7297,17 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m, */ if (stcb_tmp) { if (SCTP_GET_STATE(&stcb_tmp->asoc) & SCTP_STATE_COOKIE_WAIT) { + struct mbuf *op_err; + char msg[SCTP_DIAG_INFO_LEN]; + /* in setup state we abort this guy */ + snprintf(msg, sizeof(msg), + "%s:%d at %s", __FILE__, __LINE__, __func__); + op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), + msg); sctp_abort_an_association(stcb_tmp->sctp_ep, - stcb_tmp, NULL, SCTP_SO_NOT_LOCKED); + stcb_tmp, op_err, + SCTP_SO_NOT_LOCKED); goto add_it_now; } SCTP_TCB_UNLOCK(stcb_tmp); @@ -7367,15 +7389,23 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m, * strange, address is in another * assoc? straighten out locks. */ - if (stcb_tmp) + if (stcb_tmp) { if (SCTP_GET_STATE(&stcb_tmp->asoc) & SCTP_STATE_COOKIE_WAIT) { + struct mbuf *op_err; + char msg[SCTP_DIAG_INFO_LEN]; + /* in setup state we abort this guy */ + snprintf(msg, sizeof(msg), + "%s:%d at %s", __FILE__, __LINE__, __func__); + op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), + msg); sctp_abort_an_association(stcb_tmp->sctp_ep, - stcb_tmp, NULL, SCTP_SO_NOT_LOCKED); + stcb_tmp, op_err, + SCTP_SO_NOT_LOCKED); goto add_it_now6; } - SCTP_TCB_UNLOCK(stcb_tmp); - + SCTP_TCB_UNLOCK(stcb_tmp); + } if (stcb->asoc.state == 0) { /* the assoc was freed? */ return (-21); diff --git a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_pcb.h b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_pcb.h index 0f124c7e412..3620bd526a8 100755 --- a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_pcb.h +++ b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_pcb.h @@ -32,7 +32,7 @@ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_pcb.h 279859 2015-03-10 19:49:25Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp_pcb.h 292060 2015-12-10 11:49:32Z tuexen $"); #endif #ifndef _NETINET_SCTP_PCB_H_ @@ -311,6 +311,7 @@ struct sctp_base_info { userland_thread_t timer_thread; uint8_t timer_thread_should_exit; #if !defined(__Userspace_os_Windows) + pthread_mutexattr_t mtx_attr; #if defined(INET) || defined(INET6) int userspace_route; userland_thread_t recvthreadroute; @@ -564,6 +565,7 @@ struct sctp_inpcb { uint32_t i_am_here_line; #endif uint32_t def_vrf_id; + uint16_t fibnum; #ifdef SCTP_MVRF uint32_t *m_vrf_ids; uint32_t num_vrfs; @@ -793,16 +795,16 @@ void sctp_inpcb_free(struct sctp_inpcb *, int, int); #if defined(__FreeBSD__) && __FreeBSD_version >= 500000 struct sctp_tcb * sctp_aloc_assoc(struct sctp_inpcb *, struct sockaddr *, - int *, uint32_t, uint32_t, struct thread *); + int *, uint32_t, uint32_t, uint16_t, struct thread *); #elif defined(__Windows__) struct sctp_tcb * sctp_aloc_assoc(struct sctp_inpcb *, struct sockaddr *, - int *, uint32_t, uint32_t, PKTHREAD); + int *, uint32_t, uint32_t, uint16_t, PKTHREAD); #else /* proc will be NULL for __Userspace__ */ struct sctp_tcb * sctp_aloc_assoc(struct sctp_inpcb *, struct sockaddr *, - int *, uint32_t, uint32_t, struct proc *); + int *, uint32_t, uint32_t, uint16_t, struct proc *); #endif int sctp_free_assoc(struct sctp_inpcb *, struct sctp_tcb *, int, int); @@ -872,10 +874,5 @@ sctp_queue_to_mcore(struct mbuf *m, int off, int cpu_to_use); #endif -#ifdef INVARIANTS -void -sctp_validate_no_locks(struct sctp_inpcb *inp); -#endif - #endif /* _KERNEL */ #endif /* !__sctp_pcb_h__ */ diff --git a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_peeloff.c b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_peeloff.c index 7f21f86f98c..7c55aa32cd3 100755 --- a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_peeloff.c +++ b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_peeloff.c @@ -277,7 +277,7 @@ sctp_get_peeloff(struct socket *head, sctp_assoc_t assoc_id, int *error) sctp_feature_off(n_inp, SCTP_PCB_FLAGS_AUTOCLOSE); n_inp->sctp_ep.auto_close_time = 0; sctp_timer_stop(SCTP_TIMER_TYPE_AUTOCLOSE, n_inp, stcb, NULL, - SCTP_FROM_SCTP_PEELOFF+SCTP_LOC_1); + SCTP_FROM_SCTP_PEELOFF + SCTP_LOC_1); } /* Turn off any non-blocking semantic. */ SCTP_CLEAR_SO_NBIO(newso); diff --git a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_peeloff.h b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_peeloff.h index 69f48065cd3..69f48065cd3 100755 --- a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_peeloff.h +++ b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_peeloff.h diff --git a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_process_lock.h b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_process_lock.h index 1d109857a22..22580183f9b 100755 --- a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_process_lock.h +++ b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_process_lock.h @@ -266,39 +266,62 @@ #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() \ + KASSERT(pthread_mutex_lock(&SCTP_BASE_INFO(wq_addr_mtx)) == 0, ("%s: wq_addr_mtx already locked", __func__)) +#define SCTP_WQ_ADDR_UNLOCK() \ + 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)) -#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)))) +#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_WLOCK() \ (void)pthread_mutex_lock(&SCTP_BASE_INFO(ipi_ep_mtx)) #define SCTP_INP_INFO_RUNLOCK() \ (void)pthread_mutex_unlock(&SCTP_BASE_INFO(ipi_ep_mtx)) #define SCTP_INP_INFO_WUNLOCK() \ (void)pthread_mutex_unlock(&SCTP_BASE_INFO(ipi_ep_mtx)) +#endif #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() \ + 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,87 +330,129 @@ * 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 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); \ +#ifdef INVARIANTS +#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);\ + 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); \ +#define SCTP_INP_WLOCK(_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);\ + KASSERT(pthread_mutex_lock(&(_inp)->inp_mtx) == 0, ("%s: inp_mtx already locked", __func__)) } while (0) - #else - -#define SCTP_INP_RLOCK(_inp) do { \ - (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, (struct sctp_tcb *)NULL, SCTP_LOG_LOCK_INP);\ + (void)pthread_mutex_lock(&(_inp)->inp_mtx); \ } while (0) -#define SCTP_INP_WLOCK(_inp) do { \ - (void)pthread_mutex_lock(&(_inp)->inp_mtx); \ +#define SCTP_INP_WLOCK(_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); \ } while (0) #endif - +#else +#ifdef INVARIANTS +#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__)) +#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 +#endif +#ifdef INVARIANTS +#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 +#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_TCB_SEND_LOCK_INIT(_tcb) \ - (void)pthread_mutex_init(&(_tcb)->tcb_send_mtx, NULL) - + (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) - -#define SCTP_TCB_SEND_LOCK(_tcb) do { \ - (void)pthread_mutex_lock(&(_tcb)->tcb_send_mtx); \ -} while (0) - +#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_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) \ + (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 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); \ +#ifdef INVARIANTS +#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); \ + 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) do { \ - (void)pthread_mutex_lock(&(_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, (struct sctp_tcb *)NULL, SCTP_LOG_LOCK_CREATE); \ + (void)pthread_mutex_lock(&(_inp)->inp_create_mtx); \ } while (0) #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) +#else +#ifdef INVARIANTS +#define SCTP_ASOC_CREATE_LOCK(_inp) \ + KASSERT(pthread_mutex_lock(&(_inp)->inp_create_mtx) == 0, ("%s: inp_create_mtx already locked", __func__)) +#else +#define SCTP_ASOC_CREATE_LOCK(_inp) \ + (void)pthread_mutex_lock(&(_inp)->inp_create_mtx) +#endif +#endif +#ifdef INVARIANTS +#define SCTP_ASOC_CREATE_UNLOCK(_inp) \ + KASSERT(pthread_mutex_unlock(&(_inp)->inp_create_mtx) == 0, ("%s: inp_create_mtx not locked", __func__)) +#else #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 @@ -398,27 +463,40 @@ */ #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 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); \ +#ifdef INVARIANTS +#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); \ +#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) #endif - +#else +#ifdef INVARIANTS +#define SCTP_TCB_LOCK(_tcb) \ + KASSERT(pthread_mutex_lock(&(_tcb)->tcb_mtx) == 0, ("%s: tcb_mtx already locked", __func__)) +#else +#define SCTP_TCB_LOCK(_tcb) \ + (void)pthread_mutex_lock(&(_tcb)->tcb_mtx) +#endif +#endif +#ifdef INVARIANTS +#define SCTP_TCB_UNLOCK(_tcb) \ + KASSERT(pthread_mutex_unlock(&(_tcb)->tcb_mtx) == 0, ("%s: tcb_mtx not locked", __func__)) +#else +#define SCTP_TCB_UNLOCK(_tcb) \ + (void)pthread_mutex_unlock(&(_tcb)->tcb_mtx) +#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) #endif @@ -445,9 +523,19 @@ #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 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: so_buf already locked", __func__)) +#define SOCKBUF_UNLOCK(_so_buf) \ + KASSERT(pthread_mutex_unlock(SOCKBUF_MTX(_so_buf)) == 0, ("%s: so_buf 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 #define SOCK_LOCK(_so) SOCKBUF_LOCK(&(_so)->so_rcv) #define SOCK_UNLOCK(_so) SOCKBUF_UNLOCK(&(_so)->so_rcv) #endif @@ -517,57 +605,65 @@ 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 { \ diff --git a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_sha1.c b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_sha1.c index c86517f91cc..c86517f91cc 100755 --- a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_sha1.c +++ b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_sha1.c diff --git a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_sha1.h b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_sha1.h index 01e3c2edc49..01e3c2edc49 100755 --- a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_sha1.h +++ b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_sha1.h diff --git a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_ss_functions.c b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_ss_functions.c index d6ccd933a93..d6ccd933a93 100755 --- a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_ss_functions.c +++ b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_ss_functions.c diff --git a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_structs.h b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_structs.h index 7047b418865..ef8ba6a2c85 100755 --- a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_structs.h +++ b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_structs.h @@ -32,7 +32,7 @@ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_structs.h 279859 2015-03-10 19:49:25Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp_structs.h 285792 2015-07-22 11:30:37Z rrs $"); #endif #ifndef _NETINET_SCTP_STRUCTS_H_ @@ -80,6 +80,7 @@ TAILQ_HEAD(sctpnetlisthead, sctp_nets); struct sctp_stream_reset_list { TAILQ_ENTRY(sctp_stream_reset_list) next_resp; + uint32_t seq; uint32_t tsn; uint32_t number_entries; uint16_t list_of_streams[]; @@ -629,11 +630,20 @@ union scheduling_parameters { struct ss_fb fb; }; +/* States for outgoing streams */ +#define SCTP_STREAM_CLOSED 0x00 +#define SCTP_STREAM_OPENING 0x01 +#define SCTP_STREAM_OPEN 0x02 +#define SCTP_STREAM_RESET_PENDING 0x03 +#define SCTP_STREAM_RESET_IN_FLIGHT 0x04 + +#define SCTP_MAX_STREAMS_AT_ONCE_RESET 200 + /* This struct is used to track the traffic on outbound streams */ struct sctp_stream_out { struct sctp_streamhead outqueue; union scheduling_parameters ss_params; - uint32_t chunks_on_queues; + uint32_t chunks_on_queues; /* send queue and sent queue */ #if defined(SCTP_DETAILED_STR_STATS) uint32_t abandoned_unsent[SCTP_PR_SCTP_MAX + 1]; uint32_t abandoned_sent[SCTP_PR_SCTP_MAX + 1]; @@ -645,6 +655,7 @@ struct sctp_stream_out { uint16_t stream_no; uint16_t next_sequence_send; /* next one I expect to send out */ uint8_t last_msg_incomplete; + uint8_t state; }; /* used to keep track of the addresses yet to try to add/delete */ @@ -1198,7 +1209,7 @@ struct sctp_association { uint8_t hb_random_idx; uint8_t default_dscp; uint8_t asconf_del_pending; /* asconf delete last addr pending */ - + uint8_t trigger_reset; /* * This value, plus all other ack'd but above cum-ack is added * together to cross check against the bit that we have yet to @@ -1224,7 +1235,6 @@ struct sctp_association { struct sctp_scoping scope; /* flags to handle send alternate net tracking */ - uint8_t used_alt_onsack; uint8_t used_alt_asconfack; uint8_t fast_retran_loss_recovery; uint8_t sat_t3_loss_recovery; diff --git a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_sysctl.c b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_sysctl.c index 43f59313e1b..e92776a74b8 100755 --- a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_sysctl.c +++ b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_sysctl.c @@ -32,7 +32,7 @@ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_sysctl.c 277424 2015-01-20 19:08:55Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp_sysctl.c 287282 2015-08-29 09:14:32Z tuexen $"); #endif #include <netinet/sctp_os.h> @@ -518,6 +518,9 @@ sctp_sysctl_handle_assoclist(SYSCTL_HANDLER_ARGS) xinpcb.total_recvs = inp->total_recvs; xinpcb.total_nospaces = inp->total_nospaces; xinpcb.fragmentation_point = inp->sctp_frag_point; +#if !(defined(__FreeBSD__) && (__FreeBSD_version < 1001517)) + xinpcb.socket = inp->sctp_socket; +#endif so = inp->sctp_socket; if ((so == NULL) || (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) { @@ -552,7 +555,7 @@ sctp_sysctl_handle_assoclist(SYSCTL_HANDLER_ARGS) if (stcb->asoc.primary_destination != NULL) xstcb.primary_addr = stcb->asoc.primary_destination->ro._l_addr; xstcb.heartbeat_interval = stcb->asoc.heart_beat_delay; - xstcb.state = SCTP_GET_STATE(&stcb->asoc); /* FIXME */ + xstcb.state = (uint32_t)sctp_map_assoc_state(stcb->asoc.state); #if defined(__FreeBSD__) #if __FreeBSD_version >= 800000 /* 7.0 does not support these */ @@ -618,10 +621,12 @@ sctp_sysctl_handle_assoclist(SYSCTL_HANDLER_ARGS) #if __FreeBSD_version >= 800000 xraddr.rtt = net->rtt / 1000; xraddr.heartbeat_interval = net->heart_beat_delay; + xraddr.ssthresh = net->ssthresh; #endif #else xraddr.rtt = net->rtt / 1000; xraddr.heartbeat_interval = net->heart_beat_delay; + xraddr.ssthresh = net->ssthresh; #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/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_sysctl.h b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_sysctl.h index 3a33b71f9ba..ea9b3e35243 100755 --- a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_sysctl.h +++ b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_sysctl.h @@ -32,7 +32,7 @@ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_sysctl.h 271204 2014-09-06 19:12:14Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp_sysctl.h 287529 2015-09-07 02:00:05Z allanjude $"); #endif #ifndef _NETINET_SCTP_SYSCTL_H_ @@ -308,10 +308,10 @@ struct sctp_sysctl { #define SCTPCTL_PMTU_RAISE_TIME_DEFAULT SCTP_DEF_PMTU_RAISE_SEC /* shutdown_guard_time: Default shutdown guard timer in seconds */ -#define SCTPCTL_SHUTDOWN_GUARD_TIME_DESC "Default shutdown guard timer in seconds" +#define SCTPCTL_SHUTDOWN_GUARD_TIME_DESC "Shutdown guard timer in seconds (0 means 5 times RTO.Max)" #define SCTPCTL_SHUTDOWN_GUARD_TIME_MIN 0 #define SCTPCTL_SHUTDOWN_GUARD_TIME_MAX 0xFFFFFFFF -#define SCTPCTL_SHUTDOWN_GUARD_TIME_DEFAULT SCTP_DEF_MAX_SHUTDOWN_SEC +#define SCTPCTL_SHUTDOWN_GUARD_TIME_DEFAULT 0 /* secret_lifetime: Default secret lifetime in seconds */ #define SCTPCTL_SECRET_LIFETIME_DESC "Default secret lifetime in seconds" @@ -566,7 +566,7 @@ struct sctp_sysctl { #define SCTPCTL_RTTVAR_DCCCECN_MAX 1 #define SCTPCTL_RTTVAR_DCCCECN_DEFAULT 1 /* 0 means disable feature */ -#define SCTPCTL_BLACKHOLE_DESC "Enable SCTP blackholing" +#define SCTPCTL_BLACKHOLE_DESC "Enable SCTP blackholing. See blackhole(4) man page for more details." #define SCTPCTL_BLACKHOLE_MIN 0 #define SCTPCTL_BLACKHOLE_MAX 2 #define SCTPCTL_BLACKHOLE_DEFAULT SCTPCTL_BLACKHOLE_MIN diff --git a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_timer.c b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_timer.c index 48ad4590287..bd13dd38f50 100755 --- a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_timer.c +++ b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_timer.c @@ -32,7 +32,7 @@ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_timer.c 279841 2015-03-10 09:16:31Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp_timer.c 291700 2015-12-03 15:19:29Z tuexen $"); #endif #define _IP_VHL @@ -120,7 +120,9 @@ sctp_threshold_management(struct sctp_inpcb *inp, struct sctp_tcb *stcb, net->dest_state |= SCTP_ADDR_PF; net->last_active = sctp_get_tick_count(); sctp_send_hb(stcb, net, SCTP_SO_NOT_LOCKED); - sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3); + sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, + stcb->sctp_ep, stcb, net, + SCTP_FROM_SCTP_TIMER + SCTP_LOC_1); sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net); } } @@ -161,9 +163,9 @@ sctp_threshold_management(struct sctp_inpcb *inp, struct sctp_tcb *stcb, /* Abort notification sends a ULP notify */ struct mbuf *op_err; - op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, + op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), "Association error counter exceeded"); - inp->last_abort_code = SCTP_FROM_SCTP_TIMER+SCTP_LOC_1; + inp->last_abort_code = SCTP_FROM_SCTP_TIMER + SCTP_LOC_2; sctp_abort_an_association(inp, stcb, op_err, SCTP_SO_NOT_LOCKED); return (1); } @@ -401,7 +403,11 @@ sctp_backoff_on_timeout(struct sctp_tcb *stcb, int num_marked, int num_abandoned) { if (net->RTO == 0) { - net->RTO = stcb->asoc.minrto; + if (net->RTO_measured) { + net->RTO = stcb->asoc.minrto; + } else { + net->RTO = stcb->asoc.initial_rto; + } } net->RTO <<= 1; if (net->RTO > stcb->asoc.maxrto) { @@ -431,6 +437,11 @@ sctp_recover_sent_list(struct sctp_tcb *stcb) asoc->strmout[chk->rec.data.stream_number].chunks_on_queues--; } } + if ((asoc->strmout[chk->rec.data.stream_number].chunks_on_queues == 0) && + (asoc->strmout[chk->rec.data.stream_number].state == SCTP_STREAM_RESET_PENDING) && + TAILQ_EMPTY(&asoc->strmout[chk->rec.data.stream_number].outqueue)) { + asoc->trigger_reset = 1; + } TAILQ_REMOVE(&asoc->sent_queue, chk, sctp_next); if (PR_SCTP_ENABLED(chk->flags)) { if (asoc->pr_sctp_cnt != 0) @@ -1050,9 +1061,9 @@ sctp_cookie_timer(struct sctp_inpcb *inp, /* FOOBAR! */ struct mbuf *op_err; - op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, + op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), "Cookie timer expired, but no cookie"); - inp->last_abort_code = SCTP_FROM_SCTP_TIMER+SCTP_LOC_4; + inp->last_abort_code = SCTP_FROM_SCTP_TIMER + SCTP_LOC_3; sctp_abort_an_association(inp, stcb, op_err, SCTP_SO_NOT_LOCKED); } else { #ifdef INVARIANTS @@ -1511,6 +1522,8 @@ sctp_pathmtu_timer(struct sctp_inpcb *inp, #endif if (mtu > next_mtu) { net->mtu = next_mtu; + } else { + net->mtu = mtu; } } } diff --git a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_timer.h b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_timer.h index 3662bd2c7a5..3662bd2c7a5 100755 --- a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_timer.h +++ b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_timer.h diff --git a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_uio.h b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_uio.h index 7cf02ed2523..104c30a341e 100755 --- a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_uio.h +++ b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_uio.h @@ -32,7 +32,7 @@ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_uio.h 269945 2014-08-13 15:50:16Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp_uio.h 290444 2015-11-06 14:00:26Z tuexen $"); #endif #ifndef _NETINET_SCTP_UIO_H_ @@ -164,19 +164,25 @@ struct sctp_extrcvinfo { #endif uint32_t sinfo_ppid; uint32_t sinfo_context; - uint32_t sinfo_timetolive; + uint32_t sinfo_timetolive; /* should have been sinfo_pr_value */ uint32_t sinfo_tsn; uint32_t sinfo_cumtsn; sctp_assoc_t sinfo_assoc_id; - uint16_t sreinfo_next_flags; - uint16_t sreinfo_next_stream; - uint32_t sreinfo_next_aid; - uint32_t sreinfo_next_length; - uint32_t sreinfo_next_ppid; + uint16_t serinfo_next_flags; + uint16_t serinfo_next_stream; + uint32_t serinfo_next_aid; + uint32_t serinfo_next_length; + uint32_t serinfo_next_ppid; uint16_t sinfo_keynumber; uint16_t sinfo_keynumber_valid; uint8_t __reserve_pad[SCTP_ALIGN_RESV_PAD_SHORT]; }; +#define sinfo_pr_value sinfo_timetolive +#define sreinfo_next_flags serinfo_next_flags +#define sreinfo_next_stream serinfo_next_stream +#define sreinfo_next_aid serinfo_next_aid +#define sreinfo_next_length serinfo_next_length +#define sreinfo_next_ppid serinfo_next_ppid struct sctp_sndinfo { uint16_t snd_sid; @@ -1197,10 +1203,19 @@ struct xsctp_inpcb { #if defined(__Windows__) uint16_t padding; #endif +#if !(defined(__FreeBSD__) && (__FreeBSD_version < 1001517)) + void *socket; +#endif #if defined(__FreeBSD__) && __FreeBSD_version < 1000048 uint32_t extra_padding[32]; /* future */ -#else +#elif defined(__FreeBSD__) && (__FreeBSD_version < 1001517) uint32_t extra_padding[31]; /* future */ +#else +#if defined(__LP64__) + uint32_t extra_padding[29]; /* future */ +#else + uint32_t extra_padding[30]; /* future */ +#endif #endif }; @@ -1270,12 +1285,14 @@ struct xsctp_raddr { #if __FreeBSD_version >= 800000 uint32_t rtt; uint32_t heartbeat_interval; - uint32_t extra_padding[31]; /* future */ + uint32_t ssthresh; + uint32_t extra_padding[30]; /* future */ #endif #else uint32_t rtt; uint32_t heartbeat_interval; - uint32_t extra_padding[31]; /* future */ + uint32_t ssthresh; + uint32_t extra_padding[30]; /* future */ #endif }; diff --git a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_userspace.c b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_userspace.c index 7841a89e1ed..de09a7a7d49 100755 --- a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_userspace.c +++ b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_userspace.c @@ -34,6 +34,50 @@ #pragma comment(lib, "IPHLPAPI.lib") #endif #include <netinet/sctp_os_userspace.h> +#if defined(__Userspace_os_FreeBSD) +#include <pthread_np.h> +#endif + +#if defined(__Userspace_os_Windows) +/* Adapter to translate Unix thread start routines to Windows thread start + * routines. + */ +static DWORD WINAPI +sctp_create_thread_adapter(void *arg) { + start_routine_t start_routine = (start_routine_t)arg; + return start_routine(NULL) == NULL; +} + +int +sctp_userspace_thread_create(userland_thread_t *thread, start_routine_t start_routine) +{ + *thread = CreateThread(NULL, 0, sctp_create_thread_adapter, + (void *)start_routine, 0, NULL); + if (*thread == NULL) + return GetLastError(); + return 0; +} +#else +int +sctp_userspace_thread_create(userland_thread_t *thread, start_routine_t start_routine) +{ + return pthread_create(thread, NULL, start_routine, NULL); +} +#endif + +void +sctp_userspace_set_threadname(const char *name) +{ +#if defined(__Userspace_os_Darwin) + pthread_setname_np(name); +#endif +#if defined(__Userspace_os_Linux) + pthread_setname_np(pthread_self(), name); +#endif +#if defined(__Userspace_os_FreeBSD) + pthread_set_name_np(pthread_self(), name); +#endif +} #if !defined(_WIN32) && !defined(__Userspace_os_NaCl) int @@ -42,6 +86,7 @@ sctp_userspace_get_mtu_from_ifn(uint32_t if_index, int af) struct ifreq ifr; int fd; + memset(&ifr, 0, sizeof(struct ifreq)); if_indextoname(if_index, ifr.ifr_name); /* TODO can I use the raw socket here and not have to open a new one with each query? */ if ((fd = socket(af, SOCK_DGRAM, 0)) < 0) diff --git a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_usrreq.c b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_usrreq.c index 408f705e9f4..22d7d007f80 100755 --- a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_usrreq.c +++ b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_usrreq.c @@ -32,7 +32,7 @@ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_usrreq.c 280634 2015-03-25 21:41:20Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp_usrreq.c 291904 2015-12-06 16:17:57Z tuexen $"); #endif #include <netinet/sctp_os.h> @@ -86,23 +86,6 @@ sctp_init(void) u_long sb_max_adj; #endif -#if defined(__Userspace__) -#if defined(__Userspace_os_Windows) -#if defined(INET) || defined(INET6) - WSADATA wsaData; - - if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) { - SCTP_PRINTF("WSAStartup failed\n"); - exit (-1); - } -#endif - InitializeConditionVariable(&accept_cond); - InitializeCriticalSection(&accept_mtx); -#else - pthread_cond_init(&accept_cond, NULL); - pthread_mutex_init(&accept_mtx, NULL); -#endif -#endif /* Initialize and modify the sysctled variables */ sctp_init_sysctls(); #if defined(__Userspace__) @@ -248,20 +231,8 @@ sctp_finish(void) #endif #endif sctp_pcb_finish(); -#if defined(__Userspace__) -#if defined(__Userspace_os_Windows) - DeleteConditionVariable(&accept_cond); - DeleteCriticalSection(&accept_mtx); -#else - pthread_cond_destroy(&accept_cond); - pthread_mutex_destroy(&accept_mtx); -#endif -#endif #if defined(__Windows__) sctp_finish_sysctls(); -#if defined(INET) || defined(INET6) - WSACleanup(); -#endif #endif } @@ -373,7 +344,7 @@ sctp_notify_mbuf(struct sctp_inpcb *inp, if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) { tmr_stopped = 1; sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net, - SCTP_FROM_SCTP_USRREQ+SCTP_LOC_1); + SCTP_FROM_SCTP_USRREQ + SCTP_LOC_1); } /* Adjust destination size limit */ if (net->mtu > nxtsz) { @@ -475,7 +446,8 @@ sctp_notify(struct sctp_inpcb *inp, SCTP_TCB_LOCK(stcb); atomic_subtract_int(&stcb->asoc.refcnt, 1); #endif - (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ+SCTP_LOC_2); + (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, + SCTP_FROM_SCTP_USRREQ + SCTP_LOC_2); #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) SCTP_SOCKET_UNLOCK(so, 1); /* SCTP_TCB_UNLOCK(stcb); MT: I think this is not needed.*/ @@ -743,9 +715,6 @@ sctp_attach(struct socket *so, int proto SCTP_UNUSED, struct proc *p SCTP_UNUSED #if !defined(__Panda__) && !defined(__Userspace__) uint32_t vrf_id = SCTP_DEFAULT_VRFID; #endif -#ifdef IPSEC - uint32_t flags; -#endif inp = (struct sctp_inpcb *)so->so_pcb; if (inp != 0) { @@ -768,35 +737,6 @@ sctp_attach(struct socket *so, int proto SCTP_UNUSED, struct proc *p SCTP_UNUSED ip_inp = &inp->ip_inp.inp; ip_inp->inp_vflag |= INP_IPV4; ip_inp->inp_ip_ttl = MODULE_GLOBAL(ip_defttl); -#ifdef IPSEC -#if !(defined(__APPLE__)) - error = ipsec_init_policy(so, &ip_inp->inp_sp); -#ifdef SCTP_LOG_CLOSING - sctp_log_closing(inp, NULL, 17); -#endif - if (error != 0) { - try_again: - flags = inp->sctp_flags; - if (((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) && - (atomic_cmpset_int(&inp->sctp_flags, flags, (flags | SCTP_PCB_FLAGS_SOCKET_GONE | SCTP_PCB_FLAGS_CLOSE_IP)))) { -#ifdef SCTP_LOG_CLOSING - sctp_log_closing(inp, NULL, 15); -#endif - SCTP_INP_WUNLOCK(inp); - sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT, - SCTP_CALLED_AFTER_CMPSET_OFCLOSE); - } else { - flags = inp->sctp_flags; - if ((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) { - goto try_again; - } else { - SCTP_INP_WUNLOCK(inp); - } - } - return (error); - } -#endif -#endif /* IPSEC */ SCTP_INP_WUNLOCK(inp); return (0); } @@ -1220,7 +1160,8 @@ sctp_disconnect(struct socket *so) (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) { SCTP_STAT_DECR_GAUGE32(sctps_currestab); } - (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ+SCTP_LOC_3); + (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, + SCTP_FROM_SCTP_USRREQ + SCTP_LOC_3); /* No unlock tcb assoc is gone */ return (0); } @@ -1294,7 +1235,7 @@ sctp_disconnect(struct socket *so) struct mbuf *op_err; abort_anyway: op_err = sctp_generate_cause(SCTP_CAUSE_USER_INITIATED_ABT, ""); - stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_USRREQ+SCTP_LOC_4; + stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_USRREQ + SCTP_LOC_4; sctp_send_abort_tcb(stcb, op_err, SCTP_SO_LOCKED); SCTP_STAT_INCR_COUNTER32(sctps_aborted); if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) || @@ -1302,7 +1243,8 @@ sctp_disconnect(struct socket *so) SCTP_STAT_DECR_GAUGE32(sctps_currestab); } SCTP_INP_RUNLOCK(inp); - (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ+SCTP_LOC_5); + (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, + SCTP_FROM_SCTP_USRREQ + SCTP_LOC_5); return (0); } else { sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_CLOSING, SCTP_SO_LOCKED); @@ -1399,14 +1341,15 @@ sctp_shutdown(struct socket *so) SCTP_INP_RUNLOCK(inp); SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP); return (EOPNOTSUPP); - } - /* - * Ok if we reach here its the TCP model and it is either a SHUT_WR - * or SHUT_RDWR. This means we put the shutdown flag against it. - */ - { + } else { + /* + * Ok, if we reach here its the TCP model and it is either + * a SHUT_WR or SHUT_RDWR. + * This means we put the shutdown flag against it. + */ struct sctp_tcb *stcb; struct sctp_association *asoc; + struct sctp_nets *netp; if ((so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING|SS_ISDISCONNECTING)) == 0) { @@ -1418,7 +1361,7 @@ sctp_shutdown(struct socket *so) stcb = LIST_FIRST(&inp->sctp_asoc_list); if (stcb == NULL) { /* - * Ok we hit the case that the shutdown call was + * Ok, we hit the case that the shutdown call was * made after an abort or something. Nothing to do * now. */ @@ -1427,62 +1370,58 @@ sctp_shutdown(struct socket *so) } SCTP_TCB_LOCK(stcb); asoc = &stcb->asoc; - if (TAILQ_EMPTY(&asoc->send_queue) && + if (asoc->state & SCTP_STATE_ABOUT_TO_BE_FREED) { + SCTP_TCB_UNLOCK(stcb); + SCTP_INP_RUNLOCK(inp); + return (0); + } + if ((SCTP_GET_STATE(asoc) != SCTP_STATE_COOKIE_WAIT) && + (SCTP_GET_STATE(asoc) != SCTP_STATE_COOKIE_ECHOED) && + (SCTP_GET_STATE(asoc) != SCTP_STATE_OPEN)) { + /* If we are not in or before ESTABLISHED, there is + * no protocol action required. + */ + SCTP_TCB_UNLOCK(stcb); + SCTP_INP_RUNLOCK(inp); + return (0); + } + if (stcb->asoc.alternate) { + netp = stcb->asoc.alternate; + } else { + netp = stcb->asoc.primary_destination; + } + if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) && + TAILQ_EMPTY(&asoc->send_queue) && TAILQ_EMPTY(&asoc->sent_queue) && (asoc->stream_queue_cnt == 0)) { if (asoc->locked_on_sending) { goto abort_anyway; } /* there is nothing queued to send, so I'm done... */ - if (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT) { - /* only send SHUTDOWN the first time through */ - struct sctp_nets *netp; - - if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) || - (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) { - SCTP_STAT_DECR_GAUGE32(sctps_currestab); - } - SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT); - SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING); - sctp_stop_timers_for_shutdown(stcb); - if (stcb->asoc.alternate) { - netp = stcb->asoc.alternate; - } else { - netp = stcb->asoc.primary_destination; - } - sctp_send_shutdown(stcb, netp); - sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN, - stcb->sctp_ep, stcb, netp); - sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, - stcb->sctp_ep, stcb, netp); - sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_LOCKED); - } + SCTP_STAT_DECR_GAUGE32(sctps_currestab); + SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT); + SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING); + sctp_stop_timers_for_shutdown(stcb); + sctp_send_shutdown(stcb, netp); + sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN, + stcb->sctp_ep, stcb, netp); } else { /* - * we still got (or just got) data to send, so set - * SHUTDOWN_PENDING + * We still got (or just got) data to send, so set + * SHUTDOWN_PENDING. */ - struct sctp_nets *netp; - if (stcb->asoc.alternate) { - netp = stcb->asoc.alternate; - } else { - netp = stcb->asoc.primary_destination; - } - - asoc->state |= SCTP_STATE_SHUTDOWN_PENDING; - sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, stcb->sctp_ep, stcb, - netp); - + SCTP_ADD_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING); if (asoc->locked_on_sending) { /* Locked to send out the data */ struct sctp_stream_queue_pending *sp; + sp = TAILQ_LAST(&asoc->locked_on_sending->outqueue, sctp_streamhead); if (sp == NULL) { SCTP_PRINTF("Error, sp is NULL, locked on sending is non-null strm:%d\n", asoc->locked_on_sending->stream_no); } else { if ((sp->length == 0) && (sp-> msg_is_complete == 0)) { - asoc->state |= SCTP_STATE_PARTIAL_MSG_LEFT; + SCTP_ADD_SUBSTATE(asoc, SCTP_STATE_PARTIAL_MSG_LEFT); } } } @@ -1492,19 +1431,20 @@ sctp_shutdown(struct socket *so) struct mbuf *op_err; abort_anyway: op_err = sctp_generate_cause(SCTP_CAUSE_USER_INITIATED_ABT, ""); - stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_USRREQ+SCTP_LOC_6; + stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_USRREQ + SCTP_LOC_6; sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_LOCKED); - goto skip_unlock; - } else { - sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_CLOSING, SCTP_SO_LOCKED); + SCTP_INP_RUNLOCK(inp); + return (0); } } + sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, stcb->sctp_ep, stcb, netp); + /* XXX: Why do this in the case where we have still data queued? */ + sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_CLOSING, SCTP_SO_LOCKED); SCTP_TCB_UNLOCK(stcb); + SCTP_INP_RUNLOCK(inp); + return (0); } - skip_unlock: - SCTP_INP_RUNLOCK(inp); - return (0); } /* @@ -2119,6 +2059,7 @@ sctp_do_connect_x(struct socket *so, struct sctp_inpcb *inp, void *optval, /* We are GOOD to go */ stcb = sctp_aloc_assoc(inp, sa, &error, 0, vrf_id, + inp->sctp_ep.pre_open_stream_count, #if defined(__FreeBSD__) && __FreeBSD_version >= 500000 (struct thread *)p #elif defined(__Windows__) @@ -2157,7 +2098,8 @@ sctp_do_connect_x(struct socket *so, struct sctp_inpcb *inp, void *optval, sctp_connectx_helper_add(stcb, sa, (totaddr-1), &error); /* Fill in the return id */ if (error) { - (void)sctp_free_assoc(inp, stcb, SCTP_PCBFREE_FORCE, SCTP_FROM_SCTP_USRREQ+SCTP_LOC_6); + (void)sctp_free_assoc(inp, stcb, SCTP_PCBFREE_FORCE, + SCTP_FROM_SCTP_USRREQ + SCTP_LOC_7); goto out_now; } a_id = (sctp_assoc_t *)optval; @@ -3086,16 +3028,23 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize, /* Applies to the specific association */ paddrp->spp_flags = 0; if (net != NULL) { - int ovh; - if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) { - ovh = SCTP_MED_OVERHEAD; - } else { - ovh = SCTP_MED_V4_OVERHEAD; - } - paddrp->spp_hbinterval = net->heart_beat_delay; paddrp->spp_pathmaxrxt = net->failure_threshold; - paddrp->spp_pathmtu = net->mtu - ovh; + paddrp->spp_pathmtu = net->mtu; + switch (net->ro._l_addr.sa.sa_family) { +#ifdef INET + case AF_INET: + paddrp->spp_pathmtu -= SCTP_MIN_V4_OVERHEAD; + break; +#endif +#ifdef INET6 + case AF_INET6: + paddrp->spp_pathmtu -= SCTP_MIN_V4_OVERHEAD; + break; +#endif + default: + break; + } /* get flags for HB */ if (net->dest_state & SCTP_ADDR_NOHB) { paddrp->spp_flags |= SPP_HB_DISABLE; @@ -3104,9 +3053,9 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize, } /* get flags for PMTU */ if (net->dest_state & SCTP_ADDR_NO_PMTUD) { - paddrp->spp_flags |= SPP_PMTUD_ENABLE; - } else { paddrp->spp_flags |= SPP_PMTUD_DISABLE; + } else { + paddrp->spp_flags |= SPP_PMTUD_ENABLE; } if (net->dscp & 0x01) { paddrp->spp_dscp = net->dscp & 0xfc; @@ -3125,7 +3074,7 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize, * value */ paddrp->spp_pathmaxrxt = stcb->asoc.def_net_failure; - paddrp->spp_pathmtu = sctp_get_frag_point(stcb, &stcb->asoc); + paddrp->spp_pathmtu = 0; if (stcb->asoc.default_dscp & 0x01) { paddrp->spp_dscp = stcb->asoc.default_dscp & 0xfc; paddrp->spp_flags |= SPP_DSCP; @@ -3256,6 +3205,20 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize, paddri->spinfo_rto = net->RTO; paddri->spinfo_assoc_id = sctp_get_associd(stcb); paddri->spinfo_mtu = net->mtu; + switch (addr->sa_family) { +#if defined(INET) + case AF_INET: + paddri->spinfo_mtu -= SCTP_MIN_V4_OVERHEAD; + break; +#endif +#if defined(INET6) + case AF_INET6: + paddri->spinfo_mtu -= SCTP_MIN_OVERHEAD; + break; +#endif + default: + break; + } SCTP_TCB_UNLOCK(stcb); *optsize = sizeof(struct sctp_paddrinfo); } else { @@ -3289,12 +3252,7 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize, error = EINVAL; break; } - /* - * I think passing the state is fine since - * sctp_constants.h will be available to the user - * land. - */ - sstat->sstat_state = stcb->asoc.state; + sstat->sstat_state = sctp_map_assoc_state(stcb->asoc.state); sstat->sstat_assoc_id = sctp_get_associd(stcb); sstat->sstat_rwnd = stcb->asoc.peers_rwnd; sstat->sstat_unackdata = stcb->asoc.sent_queue_cnt; @@ -3344,6 +3302,20 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize, sstat->sstat_primary.spinfo_srtt = net->lastsa >> SCTP_RTT_SHIFT; sstat->sstat_primary.spinfo_rto = net->RTO; sstat->sstat_primary.spinfo_mtu = net->mtu; + switch (stcb->asoc.primary_destination->ro._l_addr.sa.sa_family) { +#if defined(INET) + case AF_INET: + sstat->sstat_primary.spinfo_mtu -= SCTP_MIN_V4_OVERHEAD; + break; +#endif +#if defined(INET6) + case AF_INET6: + sstat->sstat_primary.spinfo_mtu -= SCTP_MIN_OVERHEAD; + break; +#endif + default: + break; + } sstat->sstat_primary.spinfo_assoc_id = sctp_get_associd(stcb); SCTP_TCB_UNLOCK(stcb); *optsize = sizeof(struct sctp_status); @@ -5389,18 +5361,24 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, SCTP_TCB_UNLOCK(stcb); break; } - if (stcb->asoc.stream_reset_outstanding) { - SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY); - error = EALREADY; - SCTP_TCB_UNLOCK(stcb); - break; - } if (strrst->srs_flags & SCTP_STREAM_RESET_INCOMING) { send_in = 1; + if (stcb->asoc.stream_reset_outstanding) { + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY); + error = EALREADY; + SCTP_TCB_UNLOCK(stcb); + break; + } } if (strrst->srs_flags & SCTP_STREAM_RESET_OUTGOING) { send_out = 1; } + if ((strrst->srs_number_streams > SCTP_MAX_STREAMS_AT_ONCE_RESET) && send_in) { + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM); + error = ENOMEM; + SCTP_TCB_UNLOCK(stcb); + break; + } if ((send_in == 0) && (send_out == 0)) { SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); error = EINVAL; @@ -5425,11 +5403,44 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, SCTP_TCB_UNLOCK(stcb); break; } - error = sctp_send_str_reset_req(stcb, strrst->srs_number_streams, - strrst->srs_stream_list, - send_out, send_in, 0, 0, 0, 0, 0); - - sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ, SCTP_SO_LOCKED); + if (send_out) { + int cnt; + uint16_t strm; + if (strrst->srs_number_streams) { + for (i = 0, cnt = 0; i < strrst->srs_number_streams; i++) { + strm = strrst->srs_stream_list[i]; + if (stcb->asoc.strmout[strm].state == SCTP_STREAM_OPEN) { + stcb->asoc.strmout[strm].state = SCTP_STREAM_RESET_PENDING; + cnt++; + } + } + } else { + /* Its all */ + for (i = 0, cnt = 0; i < stcb->asoc.streamoutcnt; i++) { + if (stcb->asoc.strmout[i].state == SCTP_STREAM_OPEN) { + stcb->asoc.strmout[i].state = SCTP_STREAM_RESET_PENDING; + cnt++; + } + } + } + } + if (send_in) { + error = sctp_send_str_reset_req(stcb, strrst->srs_number_streams, + strrst->srs_stream_list, + send_in, 0, 0, 0, 0, 0); + } else { + error = sctp_send_stream_reset_out_if_possible(stcb, SCTP_SO_LOCKED); + } + if (error == 0) { + sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ, SCTP_SO_LOCKED); + } else { + /* + * For outgoing streams don't report any problems in + * sending the request to the application. + * XXX: Double check resetting incoming streams. + */ + error = 0; + } SCTP_TCB_UNLOCK(stcb); break; } @@ -5496,7 +5507,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, goto skip_stuff; } } - error = sctp_send_str_reset_req(stcb, 0, NULL, 0, 0, 0, addstream, add_o_strmcnt, add_i_strmcnt, 0); + error = sctp_send_str_reset_req(stcb, 0, NULL, 0, 0, addstream, add_o_strmcnt, add_i_strmcnt, 0); sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ, SCTP_SO_LOCKED); skip_stuff: SCTP_TCB_UNLOCK(stcb); @@ -5504,6 +5515,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, } case SCTP_RESET_ASSOC: { + int i; uint32_t *value; SCTP_CHECK_AND_CAST(value, optval, uint32_t, optsize); @@ -5528,7 +5540,22 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, SCTP_TCB_UNLOCK(stcb); break; } - error = sctp_send_str_reset_req(stcb, 0, NULL, 0, 0, 1, 0, 0, 0, 0); + /* Is there any data pending in the send or sent queues? */ + if (!TAILQ_EMPTY(&stcb->asoc.send_queue) || + !TAILQ_EMPTY(&stcb->asoc.sent_queue)) { + busy_out: + error = EBUSY; + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error); + SCTP_TCB_UNLOCK(stcb); + break; + } + /* Do any streams have data queued? */ + for ( i = 0; i< stcb->asoc.streamoutcnt; i++) { + if (!TAILQ_EMPTY(&stcb->asoc.strmout[i].outqueue)) { + goto busy_out; + } + } + error = sctp_send_str_reset_req(stcb, 0, NULL, 0, 1, 0, 0, 0, 0); sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ, SCTP_SO_LOCKED); SCTP_TCB_UNLOCK(stcb); break; @@ -5586,7 +5613,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, (void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered); sctp_timer_stop(SCTP_TIMER_TYPE_INIT, inp, stcb, stcb->asoc.primary_destination, - SCTP_FROM_SCTP_USRREQ+SCTP_LOC_9); + SCTP_FROM_SCTP_USRREQ + SCTP_LOC_8); sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED); } else { /* @@ -5998,26 +6025,13 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, if (stcb != NULL) { /************************TCB SPECIFIC SET ******************/ - /* - * do we change the timer for HB, we run - * only one? - */ - int ovh = 0; - - if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) { - ovh = SCTP_MED_OVERHEAD; - } else { - ovh = SCTP_MED_V4_OVERHEAD; - } - - /* network sets ? */ if (net != NULL) { /************************NET SPECIFIC SET ******************/ if (paddrp->spp_flags & SPP_HB_DISABLE) { if (!(net->dest_state & SCTP_ADDR_UNCONFIRMED) && !(net->dest_state & SCTP_ADDR_NOHB)) { sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net, - SCTP_FROM_SCTP_USRREQ+SCTP_LOC_10); + SCTP_FROM_SCTP_USRREQ + SCTP_LOC_9); } net->dest_state |= SCTP_ADDR_NOHB; } @@ -6028,7 +6042,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, net->heart_beat_delay = 0; } sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net, - SCTP_FROM_SCTP_USRREQ+SCTP_LOC_10); + SCTP_FROM_SCTP_USRREQ + SCTP_LOC_10); sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net); net->dest_state &= ~SCTP_ADDR_NOHB; } @@ -6041,10 +6055,24 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, if ((paddrp->spp_flags & SPP_PMTUD_DISABLE) && (paddrp->spp_pathmtu >= SCTP_SMALLEST_PMTU)) { if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) { sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net, - SCTP_FROM_SCTP_USRREQ+SCTP_LOC_10); + SCTP_FROM_SCTP_USRREQ + SCTP_LOC_11); } net->dest_state |= SCTP_ADDR_NO_PMTUD; - net->mtu = paddrp->spp_pathmtu + ovh; + net->mtu = paddrp->spp_pathmtu; + 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 + default: + break; + } if (net->mtu < stcb->asoc.smallest_mtu) { sctp_pathmtu_adjustment(stcb, net->mtu); } @@ -6065,7 +6093,9 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, (net->error_count > net->pf_threshold)) { net->dest_state |= SCTP_ADDR_PF; sctp_send_hb(stcb, net, SCTP_SO_LOCKED); - sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3); + sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, + stcb->sctp_ep, stcb, net, + SCTP_FROM_SCTP_USRREQ + SCTP_LOC_12); sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net); } } @@ -6108,7 +6138,9 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, (net->error_count > net->pf_threshold)) { net->dest_state |= SCTP_ADDR_PF; sctp_send_hb(stcb, net, SCTP_SO_LOCKED); - sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3); + sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, + stcb->sctp_ep, stcb, net, + SCTP_FROM_SCTP_USRREQ + SCTP_LOC_13); sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net); } } @@ -6144,7 +6176,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, net->dest_state &= ~SCTP_ADDR_NOHB; } sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net, - SCTP_FROM_SCTP_USRREQ+SCTP_LOC_10); + SCTP_FROM_SCTP_USRREQ + SCTP_LOC_14); sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net); } sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_DONOT_HEARTBEAT); @@ -6154,7 +6186,9 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, if (!(net->dest_state & SCTP_ADDR_NOHB)) { net->dest_state |= SCTP_ADDR_NOHB; if (!(net->dest_state & SCTP_ADDR_UNCONFIRMED)) { - sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net, SCTP_FROM_SCTP_USRREQ+SCTP_LOC_10); + sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, + inp, stcb, net, + SCTP_FROM_SCTP_USRREQ + SCTP_LOC_15); } } } @@ -6164,10 +6198,24 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) { sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net, - SCTP_FROM_SCTP_USRREQ+SCTP_LOC_10); + SCTP_FROM_SCTP_USRREQ + SCTP_LOC_16); } net->dest_state |= SCTP_ADDR_NO_PMTUD; - net->mtu = paddrp->spp_pathmtu + ovh; + net->mtu = paddrp->spp_pathmtu; + 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 + default: + break; + } if (net->mtu < stcb->asoc.smallest_mtu) { sctp_pathmtu_adjustment(stcb, net->mtu); } @@ -6430,16 +6478,23 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, } if ((stcb != NULL) && (net != NULL)) { - if ((net != stcb->asoc.primary_destination) && - (!(net->dest_state & SCTP_ADDR_UNCONFIRMED))) { - /* Ok we need to set it */ - if (sctp_set_primary_addr(stcb, (struct sockaddr *)NULL, net) == 0) { - if ((stcb->asoc.alternate) && - (!(net->dest_state & SCTP_ADDR_PF)) && - (net->dest_state & SCTP_ADDR_REACHABLE)) { - sctp_free_remote_addr(stcb->asoc.alternate); - stcb->asoc.alternate = NULL; + if (net != stcb->asoc.primary_destination) { + if (!(net->dest_state & SCTP_ADDR_UNCONFIRMED)) { + /* Ok we need to set it */ + if (sctp_set_primary_addr(stcb, (struct sockaddr *)NULL, net) == 0) { + if ((stcb->asoc.alternate) && + (!(net->dest_state & SCTP_ADDR_PF)) && + (net->dest_state & SCTP_ADDR_REACHABLE)) { + sctp_free_remote_addr(stcb->asoc.alternate); + stcb->asoc.alternate = NULL; + } + } else { + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); + error = EINVAL; } + } else { + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); + error = EINVAL; } } } else { @@ -6546,7 +6601,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) { if (laddr->ifa == NULL) { SCTPDBG(SCTP_DEBUG_OUTPUT1, "%s: NULL ifa\n", - __FUNCTION__); + __func__); continue; } if (laddr->ifa == ifa) { @@ -7074,7 +7129,9 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, (net->error_count <= net->failure_threshold)) { net->dest_state |= SCTP_ADDR_PF; sctp_send_hb(stcb, net, SCTP_SO_LOCKED); - sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3); + sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, + stcb->sctp_ep, stcb, net, + SCTP_FROM_SCTP_USRREQ + SCTP_LOC_17); sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net); } } @@ -7103,7 +7160,9 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, (net->error_count <= net->failure_threshold)) { net->dest_state |= SCTP_ADDR_PF; sctp_send_hb(stcb, net, SCTP_SO_LOCKED); - sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3); + sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, + stcb->sctp_ep, stcb, net, + SCTP_FROM_SCTP_USRREQ + SCTP_LOC_18); sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net); } } @@ -7527,7 +7586,24 @@ sctp_ctloutput(struct socket *so, struct sockopt *sopt) size_t optsize = 0; void *p; int error = 0; +#if defined(__FreeBSD__) + struct sctp_inpcb *inp; +#endif +#if defined(__FreeBSD__) + if ((sopt->sopt_level == SOL_SOCKET) && + (sopt->sopt_name == SO_SETFIB)) { + inp = (struct sctp_inpcb *)so->so_pcb; + if (inp == NULL) { + SCTP_LTRACE_ERR_RET(so->so_pcb, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOBUFS); + return (EINVAL); + } + SCTP_INP_WLOCK(inp); + inp->fibnum = so->so_fibnum; + SCTP_INP_WUNLOCK(inp); + return (0); + } +#endif if (sopt->sopt_level != IPPROTO_SCTP) { /* wrong proto level... send back up to IP */ #ifdef INET6 @@ -7769,7 +7845,7 @@ sctp_connect(struct socket *so, struct mbuf *nam, struct proc *p) } #endif /* We are GOOD to go */ - stcb = sctp_aloc_assoc(inp, addr, &error, 0, vrf_id, p); + stcb = sctp_aloc_assoc(inp, addr, &error, 0, vrf_id, inp->sctp_ep.pre_open_stream_count, p); if (stcb == NULL) { /* Gak! no memory */ goto out_now; @@ -7934,7 +8010,7 @@ sctpconn_connect(struct socket *so, struct sockaddr *addr) } #endif /* We are GOOD to go */ - stcb = sctp_aloc_assoc(inp, addr, &error, 0, vrf_id, p); + stcb = sctp_aloc_assoc(inp, addr, &error, 0, vrf_id, inp->sctp_ep.pre_open_stream_count, p); if (stcb == NULL) { /* Gak! no memory */ goto out_now; @@ -8376,7 +8452,8 @@ sctp_accept(struct socket *so, struct mbuf *nam) } if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) { SCTP_TCB_LOCK(stcb); - sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ+SCTP_LOC_7); + sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, + SCTP_FROM_SCTP_USRREQ + SCTP_LOC_19); } return (0); } diff --git a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_var.h b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_var.h index fcc954ebdcf..8441d1869bf 100755 --- a/chromium/third_party/usrsctp/usrsctplib/netinet/sctp_var.h +++ b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctp_var.h @@ -32,7 +32,7 @@ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctp_var.h 275427 2014-12-02 20:29:29Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctp_var.h 284384 2015-06-14 17:48:44Z tuexen $"); #endif #ifndef _NETINET_SCTP_VAR_H_ @@ -183,6 +183,7 @@ extern struct pr_usrreqs sctp_usrreqs; if (SCTP_DECREMENT_AND_CHECK_REFCOUNT(&(__net)->ref_count)) { \ (void)SCTP_OS_TIMER_STOP(&(__net)->rxt_timer.timer); \ (void)SCTP_OS_TIMER_STOP(&(__net)->pmtu_timer.timer); \ + (void)SCTP_OS_TIMER_STOP(&(__net)->hb_timer.timer); \ if ((__net)->ro.ro_rt) { \ RTFREE((__net)->ro.ro_rt); \ (__net)->ro.ro_rt = NULL; \ diff --git a/chromium/third_party/usrsctp/usrsctplib/netinet/sctputil.c b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctputil.c index 6d0c66a2d9e..fb0aea965b3 100755 --- a/chromium/third_party/usrsctp/usrsctplib/netinet/sctputil.c +++ b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctputil.c @@ -32,7 +32,7 @@ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctputil.c 280439 2015-03-24 14:51:46Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctputil.c 291904 2015-12-06 16:17:57Z tuexen $"); #endif #include <netinet/sctp_os.h> @@ -960,9 +960,52 @@ sctp_select_a_tag(struct sctp_inpcb *inp, uint16_t lport, uint16_t rport, int ch return (x); } +int32_t +sctp_map_assoc_state(int kernel_state) +{ + int32_t user_state; + + if (kernel_state & SCTP_STATE_WAS_ABORTED) { + user_state = SCTP_CLOSED; + } else if (kernel_state & SCTP_STATE_SHUTDOWN_PENDING) { + user_state = SCTP_SHUTDOWN_PENDING; + } else { + switch (kernel_state & SCTP_STATE_MASK) { + case SCTP_STATE_EMPTY: + user_state = SCTP_CLOSED; + break; + case SCTP_STATE_INUSE: + user_state = SCTP_CLOSED; + break; + case SCTP_STATE_COOKIE_WAIT: + user_state = SCTP_COOKIE_WAIT; + break; + case SCTP_STATE_COOKIE_ECHOED: + user_state = SCTP_COOKIE_ECHOED; + break; + case SCTP_STATE_OPEN: + user_state = SCTP_ESTABLISHED; + break; + case SCTP_STATE_SHUTDOWN_SENT: + user_state = SCTP_SHUTDOWN_SENT; + break; + case SCTP_STATE_SHUTDOWN_RECEIVED: + user_state = SCTP_SHUTDOWN_RECEIVED; + break; + case SCTP_STATE_SHUTDOWN_ACK_SENT: + user_state = SCTP_SHUTDOWN_ACK_SENT; + break; + default: + user_state = SCTP_CLOSED; + break; + } + } + return (user_state); +} + int sctp_init_asoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, - uint32_t override_tag, uint32_t vrf_id) + uint32_t override_tag, uint32_t vrf_id, uint16_t o_strms) { struct sctp_association *asoc; /* @@ -1134,7 +1177,7 @@ sctp_init_asoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, * that we request by default. */ asoc->strm_realoutsize = asoc->streamoutcnt = asoc->pre_open_streams = - inp->sctp_ep.pre_open_stream_count; + o_strms; SCTP_MALLOC(asoc->strmout, struct sctp_stream_out *, asoc->streamoutcnt * sizeof(struct sctp_stream_out), SCTP_M_STRMO); @@ -1166,6 +1209,7 @@ sctp_init_asoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, #endif asoc->strmout[i].stream_no = i; asoc->strmout[i].last_msg_incomplete = 0; + asoc->strmout[i].state = SCTP_STREAM_OPENING; asoc->ss_functions.sctp_ss_init_stream(&asoc->strmout[i], NULL); } asoc->ss_functions.sctp_ss_init(stcb, asoc, 0); @@ -1536,10 +1580,11 @@ sctp_timeout_handler(void *t) struct sctp_tcb *stcb; struct sctp_nets *net; struct sctp_timer *tmr; + struct mbuf *op_err; #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) struct socket *so; #endif - int did_output, type; + int did_output; tmr = (struct sctp_timer *)t; inp = (struct sctp_inpcb *)tmr->ep; @@ -1586,7 +1631,6 @@ sctp_timeout_handler(void *t) } /* if this is an iterator timeout, get the struct and clear inp */ tmr->stopped_from = 0xa003; - type = tmr->type; if (inp) { SCTP_INP_INCR_REF(inp); if ((inp->sctp_socket == NULL) && @@ -1862,7 +1906,9 @@ sctp_timeout_handler(void *t) break; } SCTP_STAT_INCR(sctps_timoshutdownguard); - sctp_abort_an_association(inp, stcb, NULL, SCTP_SO_NOT_LOCKED); + op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), + "Shutdown guard timer expired"); + sctp_abort_an_association(inp, stcb, op_err, SCTP_SO_NOT_LOCKED); /* no need to unlock on tcb its gone */ goto out_decr; @@ -1915,7 +1961,8 @@ sctp_timeout_handler(void *t) SCTP_STAT_INCR(sctps_timoassockill); /* Can we free it yet? */ SCTP_INP_DECR_REF(inp); - sctp_timer_stop(SCTP_TIMER_TYPE_ASOCKILL, inp, stcb, NULL, SCTP_FROM_SCTPUTIL+SCTP_LOC_1); + sctp_timer_stop(SCTP_TIMER_TYPE_ASOCKILL, inp, stcb, NULL, + SCTP_FROM_SCTPUTIL + SCTP_LOC_1); #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) so = SCTP_INP_SO(inp); atomic_add_int(&stcb->asoc.refcnt, 1); @@ -1924,7 +1971,8 @@ sctp_timeout_handler(void *t) SCTP_TCB_LOCK(stcb); atomic_subtract_int(&stcb->asoc.refcnt, 1); #endif - (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTPUTIL+SCTP_LOC_2); + (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, + SCTP_FROM_SCTPUTIL + SCTP_LOC_2); #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) SCTP_SOCKET_UNLOCK(so, 1); #endif @@ -1944,7 +1992,8 @@ sctp_timeout_handler(void *t) * killer */ SCTP_INP_DECR_REF(inp); - sctp_timer_stop(SCTP_TIMER_TYPE_INPKILL, inp, NULL, NULL, SCTP_FROM_SCTPUTIL+SCTP_LOC_3); + sctp_timer_stop(SCTP_TIMER_TYPE_INPKILL, inp, NULL, NULL, + SCTP_FROM_SCTPUTIL + SCTP_LOC_3); #if defined(__APPLE__) SCTP_SOCKET_LOCK(SCTP_INP_SO(inp), 1); #endif @@ -1987,7 +2036,7 @@ out_decr: out_no_decr: SCTPDBG(SCTP_DEBUG_TIMER1, "Timer now complete (type %d)\n", - type); + tmr->type); #if defined(__FreeBSD__) && __FreeBSD_version >= 801000 CURVNET_RESTORE(); #endif @@ -2190,7 +2239,11 @@ sctp_timer_start(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb, if (stcb == NULL) { return; } - to_ticks = inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_MAXSHUTDOWN]; + if (inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_MAXSHUTDOWN] == 0) { + to_ticks = 5 * MSEC_TO_TICKS(stcb->asoc.maxrto); + } else { + to_ticks = inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_MAXSHUTDOWN]; + } tmr = &stcb->asoc.shut_guard_timer; break; case SCTP_TIMER_TYPE_STRRESET: @@ -2246,13 +2299,13 @@ sctp_timer_start(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb, break; default: SCTPDBG(SCTP_DEBUG_TIMER1, "%s: Unknown timer type %d\n", - __FUNCTION__, t_type); + __func__, t_type); return; break; } if ((to_ticks <= 0) || (tmr == NULL)) { SCTPDBG(SCTP_DEBUG_TIMER1, "%s: %d:software error to_ticks:%d tmr:%p not set ??\n", - __FUNCTION__, t_type, to_ticks, (void *)tmr); + __func__, t_type, to_ticks, (void *)tmr); return; } if (SCTP_OS_TIMER_PENDING(&tmr->timer)) { @@ -2412,7 +2465,7 @@ sctp_timer_stop(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb, break; default: SCTPDBG(SCTP_DEBUG_TIMER1, "%s: Unknown timer type %d\n", - __FUNCTION__, t_type); + __func__, t_type); break; } if (tmr == NULL) { @@ -2729,6 +2782,9 @@ sctp_notify_assoc_change(uint16_t state, struct sctp_tcb *stcb, struct socket *so; #endif + if (stcb == NULL) { + return; + } if (sctp_stcb_is_feature_on(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVASSOCEVNT)) { notif_len = sizeof(struct sctp_assoc_change); if (abort != NULL) { @@ -3886,7 +3942,7 @@ sctp_ulp_notify(uint32_t notification, struct sctp_tcb *stcb, break; default: SCTPDBG(SCTP_DEBUG_UTIL1, "%s: unknown notification %xh (%u)\n", - __FUNCTION__, notification, notification); + __func__, notification, notification); break; } /* end switch */ } @@ -4073,7 +4129,7 @@ sctp_abort_association(struct sctp_inpcb *inp, struct sctp_tcb *stcb, } sctp_send_abort(m, iphlen, src, dst, sh, vtag, op_err, #if defined(__FreeBSD__) - mflowtype, mflowid, + mflowtype, mflowid, inp->fibnum, #endif vrf_id, port); if (stcb != NULL) { @@ -4091,7 +4147,8 @@ sctp_abort_association(struct sctp_inpcb *inp, struct sctp_tcb *stcb, (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) { SCTP_STAT_DECR_GAUGE32(sctps_currestab); } - (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTPUTIL+SCTP_LOC_4); + (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, + SCTP_FROM_SCTPUTIL + SCTP_LOC_4); #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) SCTP_SOCKET_UNLOCK(so, 1); #endif @@ -4228,7 +4285,8 @@ sctp_abort_an_association(struct sctp_inpcb *inp, struct sctp_tcb *stcb, atomic_subtract_int(&stcb->asoc.refcnt, 1); } #endif - (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTPUTIL+SCTP_LOC_5); + (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, + SCTP_FROM_SCTPUTIL + SCTP_LOC_5); #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) if (!so_locked) { SCTP_SOCKET_UNLOCK(so, 1); @@ -4242,7 +4300,7 @@ sctp_handle_ootb(struct mbuf *m, int iphlen, int offset, struct sctphdr *sh, struct sctp_inpcb *inp, struct mbuf *cause, #if defined(__FreeBSD__) - uint8_t mflowtype, uint32_t mflowid, + uint8_t mflowtype, uint32_t mflowid, uint16_t fibnum, #endif uint32_t vrf_id, uint16_t port) { @@ -4292,7 +4350,7 @@ sctp_handle_ootb(struct mbuf *m, int iphlen, int offset, case SCTP_SHUTDOWN_ACK: sctp_send_shutdown_complete2(src, dst, sh, #if defined(__FreeBSD__) - mflowtype, mflowid, + mflowtype, mflowid, fibnum, #endif vrf_id, port); return; @@ -4308,7 +4366,7 @@ sctp_handle_ootb(struct mbuf *m, int iphlen, int offset, (contains_init_chunk == 0))) { sctp_send_abort(m, iphlen, src, dst, sh, 0, cause, #if defined(__FreeBSD__) - mflowtype, mflowid, + mflowtype, mflowid, fibnum, #endif vrf_id, port); } @@ -4756,10 +4814,11 @@ sctp_add_to_readq(struct sctp_inpcb *inp, control->end_added = 1; } #if defined(__Userspace__) - if (inp->recv_callback) { + if (inp->recv_callback != NULL) { if (inp_read_lock_held == 0) SCTP_INP_READ_UNLOCK(inp); - if (control->end_added == 1) { + if ((control->end_added == 1) && + (stcb != NULL) && (stcb->sctp_socket != NULL)) { struct socket *so; struct mbuf *m; char *buffer; @@ -4978,7 +5037,7 @@ sctp_append_to_readq(struct sctp_inpcb *inp, */ control->sinfo_tsn = control->sinfo_cumtsn = ctls_cumack; #if defined(__Userspace__) - if (inp->recv_callback) { + if ((inp != NULL) && (inp->recv_callback != NULL)) { uint32_t pd_point, length; length = control->length; @@ -4988,7 +5047,8 @@ sctp_append_to_readq(struct sctp_inpcb *inp, } else { pd_point = inp->partial_delivery_point; } - if ((control->end_added == 1) || (length >= pd_point)) { + if (((control->end_added == 1) || (length >= pd_point)) && + ((stcb != NULL) && (stcb->sctp_socket))) { struct socket *so; char *buffer; struct sctp_rcvinfo rcv; @@ -5662,7 +5722,8 @@ sctp_user_rcvd(struct sctp_tcb *stcb, uint32_t *freed_so_far, int hold_rlock, sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_USR_RCVD, SCTP_SO_LOCKED); /* make sure no timer is running */ - sctp_timer_stop(SCTP_TIMER_TYPE_RECV, stcb->sctp_ep, stcb, NULL, SCTP_FROM_SCTPUTIL+SCTP_LOC_6); + sctp_timer_stop(SCTP_TIMER_TYPE_RECV, stcb->sctp_ep, stcb, NULL, + SCTP_FROM_SCTPUTIL + SCTP_LOC_6); SCTP_TCB_UNLOCK(stcb); } else { /* Update how much we have pending */ @@ -5699,7 +5760,7 @@ sctp_sorecvmsg(struct socket *so, */ struct sctp_inpcb *inp = NULL; int my_len = 0; - int cp_len = 0, error = 0; + int cp_len = 0, error = 0; struct sctp_queued_to_read *control = NULL, *ctl = NULL, *nxt = NULL; struct mbuf *m = NULL; struct sctp_tcb *stcb = NULL; @@ -6145,20 +6206,20 @@ sctp_sorecvmsg(struct socket *so, s_extra = (struct sctp_extrcvinfo *)sinfo; if ((nxt) && (nxt->length)) { - s_extra->sreinfo_next_flags = SCTP_NEXT_MSG_AVAIL; + s_extra->serinfo_next_flags = SCTP_NEXT_MSG_AVAIL; if (nxt->sinfo_flags & SCTP_UNORDERED) { - s_extra->sreinfo_next_flags |= SCTP_NEXT_MSG_IS_UNORDERED; + s_extra->serinfo_next_flags |= SCTP_NEXT_MSG_IS_UNORDERED; } if (nxt->spec_flags & M_NOTIFICATION) { - s_extra->sreinfo_next_flags |= SCTP_NEXT_MSG_IS_NOTIFICATION; + s_extra->serinfo_next_flags |= SCTP_NEXT_MSG_IS_NOTIFICATION; } - s_extra->sreinfo_next_aid = nxt->sinfo_assoc_id; - s_extra->sreinfo_next_length = nxt->length; - s_extra->sreinfo_next_ppid = nxt->sinfo_ppid; - s_extra->sreinfo_next_stream = nxt->sinfo_stream; + s_extra->serinfo_next_aid = nxt->sinfo_assoc_id; + s_extra->serinfo_next_length = nxt->length; + s_extra->serinfo_next_ppid = nxt->sinfo_ppid; + s_extra->serinfo_next_stream = nxt->sinfo_stream; if (nxt->tail_mbuf != NULL) { if (nxt->end_added) { - s_extra->sreinfo_next_flags |= SCTP_NEXT_MSG_ISCOMPLETE; + s_extra->serinfo_next_flags |= SCTP_NEXT_MSG_ISCOMPLETE; } } } else { @@ -6167,11 +6228,11 @@ sctp_sorecvmsg(struct socket *so, * that is on the control's structure :-D */ nxt = NULL; - s_extra->sreinfo_next_flags = SCTP_NO_NEXT_MSG; - s_extra->sreinfo_next_aid = 0; - s_extra->sreinfo_next_length = 0; - s_extra->sreinfo_next_ppid = 0; - s_extra->sreinfo_next_stream = 0; + s_extra->serinfo_next_flags = SCTP_NO_NEXT_MSG; + s_extra->serinfo_next_aid = 0; + s_extra->serinfo_next_length = 0; + s_extra->serinfo_next_ppid = 0; + s_extra->serinfo_next_stream = 0; } } /* @@ -6354,7 +6415,7 @@ sctp_sorecvmsg(struct socket *so, /* been through it all, must hold sb lock ok to null tail */ if (control->data == NULL) { #ifdef INVARIANTS -#if !defined(__APPLE__) +#if defined(__FreeBSD__) if ((control->end_added == 0) || (TAILQ_NEXT(control, next) == NULL)) { /* If the end is not added, OR the @@ -6720,7 +6781,7 @@ sctp_sorecvmsg(struct socket *so, sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVNXTINFO))) { struct sctp_extrcvinfo *s_extra; s_extra = (struct sctp_extrcvinfo *)sinfo; - s_extra->sreinfo_next_flags = SCTP_NO_NEXT_MSG; + s_extra->serinfo_next_flags = SCTP_NO_NEXT_MSG; } if (hold_rlock == 1) { SCTP_INP_READ_UNLOCK(inp); @@ -7109,14 +7170,16 @@ sctp_connectx_helper_add(struct sctp_tcb *stcb, struct sockaddr *addr, (sin->sin_addr.s_addr == INADDR_BROADCAST) || IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) { SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, EINVAL); - (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ+SCTP_LOC_7); + (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, + SCTP_FROM_SCTPUTIL + SCTP_LOC_7); *error = EINVAL; goto out_now; } if (sctp_add_remote_addr(stcb, sa, NULL, SCTP_DONOT_SETSCOPE, SCTP_ADDR_IS_CONFIRMED)) { /* assoc gone no un-lock */ SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ENOBUFS); - (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ+SCTP_LOC_7); + (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, + SCTP_FROM_SCTPUTIL + SCTP_LOC_8); *error = ENOBUFS; goto out_now; } @@ -7130,14 +7193,16 @@ sctp_connectx_helper_add(struct sctp_tcb *stcb, struct sockaddr *addr, if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) || IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) { SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, EINVAL); - (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ+SCTP_LOC_8); + (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, + SCTP_FROM_SCTPUTIL + SCTP_LOC_9); *error = EINVAL; goto out_now; } if (sctp_add_remote_addr(stcb, sa, NULL, SCTP_DONOT_SETSCOPE, SCTP_ADDR_IS_CONFIRMED)) { /* assoc gone no un-lock */ SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ENOBUFS); - (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ+SCTP_LOC_8); + (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, + SCTP_FROM_SCTPUTIL + SCTP_LOC_10); *error = ENOBUFS; goto out_now; } @@ -7150,7 +7215,8 @@ sctp_connectx_helper_add(struct sctp_tcb *stcb, struct sockaddr *addr, if (sctp_add_remote_addr(stcb, sa, NULL, SCTP_DONOT_SETSCOPE, SCTP_ADDR_IS_CONFIRMED)) { /* assoc gone no un-lock */ SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ENOBUFS); - (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ+SCTP_LOC_8); + (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, + SCTP_FROM_SCTPUTIL + SCTP_LOC_11); *error = ENOBUFS; goto out_now; } @@ -7738,7 +7804,7 @@ sctp_log_trace(uint32_t subsys, const char *str SCTP_UNUSED, uint32_t a, uint32_ #if defined(__FreeBSD__) #if __FreeBSD_version >= 800044 static void -sctp_recv_udp_tunneled_packet(struct mbuf *m, int off, struct inpcb *ignored, +sctp_recv_udp_tunneled_packet(struct mbuf *m, int off, struct inpcb *inp, const struct sockaddr *sa SCTP_UNUSED, void *ctx SCTP_UNUSED) { struct ip *iph; @@ -7784,6 +7850,26 @@ sctp_recv_udp_tunneled_packet(struct mbuf *m, int off, struct inpcb *ignored, for (last = m; last->m_next; last = last->m_next); last->m_next = sp; m->m_pkthdr.len += sp->m_pkthdr.len; + /* + * The CSUM_DATA_VALID flags indicates that the HW checked the + * UDP checksum and it was valid. + * Since CSUM_DATA_VALID == CSUM_SCTP_VALID this would imply that + * the HW also verified the SCTP checksum. Therefore, clear the bit. + */ +#if __FreeBSD_version > 1000049 + SCTPDBG(SCTP_DEBUG_CRCOFFLOAD, + "sctp_recv_udp_tunneled_packet(): Packet of length %d received on %s with csum_flags 0x%b.\n", + m->m_pkthdr.len, + if_name(m->m_pkthdr.rcvif), + (int)m->m_pkthdr.csum_flags, CSUM_BITS); +#else + SCTPDBG(SCTP_DEBUG_CRCOFFLOAD, + "sctp_recv_udp_tunneled_packet(): Packet of length %d received on %s with csum_flags 0x%x.\n", + m->m_pkthdr.len, + if_name(m->m_pkthdr.rcvif), + m->m_pkthdr.csum_flags); +#endif + m->m_pkthdr.csum_flags &= ~CSUM_DATA_VALID; iph = mtod(m, struct ip *); switch (iph->ip_v) { #ifdef INET diff --git a/chromium/third_party/usrsctp/usrsctplib/netinet/sctputil.h b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctputil.h index cca915bb450..2276177e933 100755 --- a/chromium/third_party/usrsctp/usrsctplib/netinet/sctputil.h +++ b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet/sctputil.h @@ -32,7 +32,7 @@ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet/sctputil.h 276914 2015-01-10 20:49:57Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet/sctputil.h 291904 2015-12-06 16:17:57Z tuexen $"); #endif #ifndef _NETINET_SCTP_UTIL_H_ @@ -66,6 +66,9 @@ sctp_log_trace(uint32_t fr, const char *str SCTP_UNUSED, uint32_t a, uint32_t b, /* * Function prototypes */ +int32_t +sctp_map_assoc_state(int); + uint32_t sctp_get_ifa_hash_val(struct sockaddr *addr); @@ -79,7 +82,7 @@ uint32_t sctp_select_initial_TSN(struct sctp_pcb *); uint32_t sctp_select_a_tag(struct sctp_inpcb *, uint16_t lport, uint16_t rport, int); -int sctp_init_asoc(struct sctp_inpcb *, struct sctp_tcb *, uint32_t, uint32_t); +int sctp_init_asoc(struct sctp_inpcb *, struct sctp_tcb *, uint32_t, uint32_t, uint16_t); void sctp_fill_random_store(struct sctp_pcb *); @@ -206,7 +209,7 @@ void sctp_handle_ootb(struct mbuf *, int, int, struct sctphdr *, struct sctp_inpcb *, struct mbuf *, #if defined(__FreeBSD__) - uint8_t, uint32_t, + uint8_t, uint32_t, uint16_t, #endif uint32_t, uint16_t); diff --git a/chromium/third_party/usrsctp/usrsctplib/netinet6/sctp6_usrreq.c b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet6/sctp6_usrreq.c index 4adb6719667..25eebbf5323 100644 --- a/chromium/third_party/usrsctp/usrsctplib/netinet6/sctp6_usrreq.c +++ b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet6/sctp6_usrreq.c @@ -32,7 +32,7 @@ #ifdef __FreeBSD__ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: head/sys/netinet6/sctp6_usrreq.c 276914 2015-01-10 20:49:57Z tuexen $"); +__FBSDID("$FreeBSD: head/sys/netinet6/sctp6_usrreq.c 291904 2015-12-06 16:17:57Z tuexen $"); #endif #include <netinet/sctp_os.h> @@ -43,9 +43,7 @@ __FBSDID("$FreeBSD: head/sys/netinet6/sctp6_usrreq.c 276914 2015-01-10 20:49:57Z #include <netinet/sctp_pcb.h> #include <netinet/sctp_header.h> #include <netinet/sctp_var.h> -#ifdef INET6 #include <netinet6/sctp6_var.h> -#endif #include <netinet/sctp_sysctl.h> #include <netinet/sctp_output.h> #include <netinet/sctp_uio.h> @@ -59,6 +57,7 @@ __FBSDID("$FreeBSD: head/sys/netinet6/sctp6_usrreq.c 276914 2015-01-10 20:49:57Z #include <netinet/sctp_bsd_addr.h> #include <netinet/sctp_crc32.h> #if !defined(__Userspace_os_Windows) +#include <netinet/icmp6.h> #include <netinet/udp.h> #endif @@ -67,9 +66,7 @@ __FBSDID("$FreeBSD: head/sys/netinet6/sctp6_usrreq.c 276914 2015-01-10 20:49:57Z #endif #ifdef IPSEC #include <netipsec/ipsec.h> -#ifdef INET6 #include <netipsec/ipsec6.h> -#endif /* INET6 */ #endif /* IPSEC */ #if !defined(__Userspace__) @@ -163,6 +160,7 @@ sctp6_input(struct mbuf **i_pak, int *offp, int proto) #if defined(__FreeBSD__) uint32_t mflowid; uint8_t mflowtype; + uint16_t fibnum; #endif #if !(defined(__APPLE__) || defined (__FreeBSD__)) uint16_t port = 0; @@ -233,7 +231,8 @@ sctp6_input(struct mbuf **i_pak, int *offp, int proto) #if defined(__FreeBSD__) mflowid = m->m_pkthdr.flowid; mflowtype = M_HASHTYPE_GET(m); - #endif + fibnum = M_GETFIB(m); +#endif SCTP_STAT_INCR(sctps_recvpackets); SCTP_STAT_INCR_COUNTER64(sctps_inpackets); /* Get IP, SCTP, and first chunk header together in the first mbuf. */ @@ -324,7 +323,7 @@ sctp6_input(struct mbuf **i_pak, int *offp, int proto) #endif ecn_bits, #if defined(__FreeBSD__) - mflowtype, mflowid, + mflowtype, mflowid, fibnum, #endif vrf_id, port); out: @@ -380,7 +379,8 @@ sctp6_notify_mbuf(struct sctp_inpcb *inp, struct icmp6_hdr *icmp6, */ nxtsz = ntohl(icmp6->icmp6_mtu); /* Stop any PMTU timer */ - sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, NULL, SCTP_FROM_SCTP6_USRREQ+SCTP_LOC_1); + sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, NULL, + SCTP_FROM_SCTP6_USRREQ + SCTP_LOC_1); /* Adjust destination size limit */ if (net->mtu > nxtsz) { @@ -510,7 +510,8 @@ sctp6_notify(struct sctp_inpcb *inp, SCTP_TCB_LOCK(stcb); atomic_subtract_int(&stcb->asoc.refcnt, 1); #endif - (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ+SCTP_LOC_2); + (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, + SCTP_FROM_SCTP6_USRREQ + SCTP_LOC_2); #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) SCTP_SOCKET_UNLOCK(so, 1); /* SCTP_TCB_UNLOCK(stcb); MT: I think this is not needed.*/ @@ -1311,7 +1312,7 @@ sctp6_connect(struct socket *so, struct mbuf *nam, struct proc *p) return (EALREADY); } /* We are GOOD to go */ - stcb = sctp_aloc_assoc(inp, addr, &error, 0, vrf_id, p); + stcb = sctp_aloc_assoc(inp, addr, &error, 0, vrf_id, inp->sctp_ep.pre_open_stream_count, p); SCTP_ASOC_CREATE_UNLOCK(inp); if (stcb == NULL) { /* Gak! no memory */ diff --git a/chromium/third_party/usrsctp/usrsctplib/netinet6/sctp6_var.h b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet6/sctp6_var.h index 3402bc08cd7..3402bc08cd7 100755 --- a/chromium/third_party/usrsctp/usrsctplib/netinet6/sctp6_var.h +++ b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/netinet6/sctp6_var.h diff --git a/chromium/third_party/usrsctp/usrsctplib/user_atomic.h b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/user_atomic.h index 33659cd2265..b8415c6047e 100755 --- a/chromium/third_party/usrsctp/usrsctplib/user_atomic.h +++ b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/user_atomic.h @@ -76,12 +76,12 @@ *addr = 0; \ } \ } +#endif #if defined(__Userspace_os_Windows) static void atomic_init() {} /* empty when we are not using atomic_mtx */ #else static inline void atomic_init() {} /* empty when we are not using atomic_mtx */ #endif -#endif #else /* Using gcc built-in functions for atomic memory operations @@ -188,16 +188,31 @@ static inline void atomic_unlock() { } #else static inline void atomic_init() { - (void)pthread_mutex_init(&atomic_mtx, NULL); + pthread_mutexattr_t mutex_attr; + + pthread_mutexattr_init(&mutex_attr); +#ifdef INVARIANTS + pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_ERRORCHECK); +#endif + pthread_mutex_init(&accept_mtx, &mutex_attr); + pthread_mutexattr_destroy(&mutex_attr); } static inline void atomic_destroy() { (void)pthread_mutex_destroy(&atomic_mtx); } static inline void atomic_lock() { +#ifdef INVARIANTS + KASSERT(pthread_mutex_lock(&atomic_mtx) == 0, ("atomic_lock: atomic_mtx already locked")) +#else (void)pthread_mutex_lock(&atomic_mtx); +#endif } static inline void atomic_unlock() { +#ifdef INVARIANTS + KASSERT(pthread_mutex_unlock(&atomic_mtx) == 0, ("atomic_unlock: atomic_mtx not locked")) +#else (void)pthread_mutex_unlock(&atomic_mtx); +#endif } #endif /* diff --git a/chromium/third_party/usrsctp/usrsctplib/user_environment.c b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/user_environment.c index 6830a2368b8..6830a2368b8 100755 --- a/chromium/third_party/usrsctp/usrsctplib/user_environment.c +++ b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/user_environment.c diff --git a/chromium/third_party/usrsctp/usrsctplib/user_environment.h b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/user_environment.h index 6de9d9a5a3e..306ff6b55b4 100755 --- a/chromium/third_party/usrsctp/usrsctplib/user_environment.h +++ b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/user_environment.h @@ -85,20 +85,26 @@ extern u_short ip_id; #if defined(__Userspace_os_Linux) #define IPV6_VERSION 0x60 #endif + #if defined(INVARIANTS) -#define panic(args...) \ - do { \ - SCTP_PRINTF(args);\ - exit(1); \ +#include <stdlib.h> + +static inline void +terminate_non_graceful(void) { + abort(); +} + +#define panic(...) \ + do { \ + SCTP_PRINTF(__VA_ARGS__);\ + SCTP_PRINTF("\n"); \ + terminate_non_graceful();\ } while (0) -#endif -#if defined(INVARIANTS) #define KASSERT(cond, args) \ do { \ if (!(cond)) { \ - printf args ;\ - exit(1); \ + panic args ;\ } \ } while (0) #else diff --git a/chromium/third_party/usrsctp/usrsctplib/user_inpcb.h b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/user_inpcb.h index c557cd0a13c..c557cd0a13c 100755 --- a/chromium/third_party/usrsctp/usrsctplib/user_inpcb.h +++ b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/user_inpcb.h diff --git a/chromium/third_party/usrsctp/usrsctplib/user_ip6_var.h b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/user_ip6_var.h index f5e4a60e4f2..f5e4a60e4f2 100755 --- a/chromium/third_party/usrsctp/usrsctplib/user_ip6_var.h +++ b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/user_ip6_var.h diff --git a/chromium/third_party/usrsctp/usrsctplib/user_ip_icmp.h b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/user_ip_icmp.h index e713417da89..e713417da89 100755 --- a/chromium/third_party/usrsctp/usrsctplib/user_ip_icmp.h +++ b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/user_ip_icmp.h diff --git a/chromium/third_party/usrsctp/usrsctplib/user_malloc.h b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/user_malloc.h index 4ea954898e0..73904ca5b47 100755 --- a/chromium/third_party/usrsctp/usrsctplib/user_malloc.h +++ b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/user_malloc.h @@ -195,7 +195,7 @@ Start copy: Copied code for __Userspace__ */ #define MALLOC(space, cast, size, type, flags) \ ((space) = (cast)malloc((u_long)(size))); \ do { \ - if(flags & M_ZERO) { \ + if (flags & M_ZERO) { \ memset(space,0,size); \ } \ } while (0); diff --git a/chromium/third_party/usrsctp/usrsctplib/user_mbuf.c b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/user_mbuf.c index de8f0fbc8c9..ddc371c3c8f 100755 --- a/chromium/third_party/usrsctp/usrsctplib/user_mbuf.c +++ b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/user_mbuf.c @@ -1080,6 +1080,8 @@ int m_dup_pkthdr(struct mbuf *to, struct mbuf *from, int how) { + KASSERT(to, ("m_dup_pkthdr: to is NULL")); + KASSERT(from, ("m_dup_pkthdr: from is NULL")); to->m_flags = (from->m_flags & M_COPYFLAGS) | (to->m_flags & M_EXT); if ((to->m_flags & M_EXT) == 0) to->m_data = to->m_pktdat; @@ -1198,7 +1200,7 @@ m_prepend(struct mbuf *m, int len, int how) M_MOVE_PKTHDR(mn, m); mn->m_next = m; m = mn; - if(m->m_flags & M_PKTHDR) { + if (m->m_flags & M_PKTHDR) { if (len < MHLEN) MH_ALIGN(m, len); } else { diff --git a/chromium/third_party/usrsctp/usrsctplib/user_mbuf.h b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/user_mbuf.h index f3717407e14..7893ea95166 100755 --- a/chromium/third_party/usrsctp/usrsctplib/user_mbuf.h +++ b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/user_mbuf.h @@ -267,7 +267,6 @@ struct mbuf { #define M_PROTO3 0x0040 /* protocol-specific */ #define M_PROTO4 0x0080 /* protocol-specific */ #define M_PROTO5 0x0100 /* protocol-specific */ -#define M_SKIP_FIREWALL 0x4000 /* skip firewall processing */ #define M_FREELIST 0x8000 /* mbuf is on the free list */ @@ -275,7 +274,7 @@ struct mbuf { * Flags copied when copying m_pkthdr. */ #define M_COPYFLAGS (M_PKTHDR|M_EOR|M_RDONLY|M_PROTO1|M_PROTO1|M_PROTO2|\ - M_PROTO3|M_PROTO4|M_PROTO5|M_SKIP_FIREWALL|\ + M_PROTO3|M_PROTO4|M_PROTO5|\ M_BCAST|M_MCAST|M_FRAG|M_FIRSTFRAG|M_LASTFRAG|\ M_VLANTAG|M_PROMISC) diff --git a/chromium/third_party/usrsctp/usrsctplib/user_queue.h b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/user_queue.h index 44f89949026..44f89949026 100755 --- a/chromium/third_party/usrsctp/usrsctplib/user_queue.h +++ b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/user_queue.h diff --git a/chromium/third_party/usrsctp/usrsctplib/user_recv_thread.c b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/user_recv_thread.c index 7b2ff584647..650029964c7 100755 --- a/chromium/third_party/usrsctp/usrsctplib/user_recv_thread.c +++ b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/user_recv_thread.c @@ -154,6 +154,8 @@ recv_function_route(void *arg) char rt_buffer[1024]; struct sockaddr *sa, *rti_info[RTAX_MAX]; + sctp_userspace_set_threadname("SCTP addr mon"); + while (1) { bzero(rt_buffer, sizeof(rt_buffer)); ret = recv(SCTP_BASE_VAR(userspace_route), rt_buffer, sizeof(rt_buffer), 0); @@ -237,7 +239,7 @@ recv_function_route(void *arg) if (nh->nlmsg_type == RTM_NEWADDR || nh->nlmsg_type == RTM_DELADDR) { rtmsg = (struct ifaddrmsg *)NLMSG_DATA(nh); rtatp = (struct rtattr *)IFA_RTA(rtmsg); - if(rtatp->rta_type == IFA_ADDRESS) { + if (rtatp->rta_type == IFA_ADDRESS) { inp = (struct in_addr *)RTA_DATA(rtatp); switch (rtmsg->ifa_family) { #ifdef INET @@ -294,7 +296,6 @@ recv_function_raw(void *arg) struct sockaddr_in from; int fromlen; #endif - /*Initially the entire set of mbufs is to be allocated. to_fill indicates this amount. */ int to_fill = MAXLEN_MBUF_CHAIN; @@ -304,6 +305,8 @@ recv_function_raw(void *arg) int want_ext = (iovlen > MLEN)? 1 : 0; int want_header = 0; + sctp_userspace_set_threadname("SCTP/IP4 rcv"); + bzero((void *)&src, sizeof(struct sockaddr_in)); bzero((void *)&dst, sizeof(struct sockaddr_in)); @@ -406,10 +409,12 @@ recv_function_raw(void *arg) /* SCTP does not allow broadcasts or multicasts */ if (IN_MULTICAST(ntohl(dst.sin_addr.s_addr))) { - return (NULL); + m_freem(recvmbuf[0]); + continue; } if (SCTP_IS_IT_BROADCAST(dst.sin_addr, recvmbuf[0])) { - return (NULL); + m_freem(recvmbuf[0]); + continue; } port = 0; @@ -474,7 +479,6 @@ recv_function_raw6(void *arg) struct sctphdr *sh; int offset; struct sctp_chunkhdr *ch; - /*Initially the entire set of mbufs is to be allocated. to_fill indicates this amount. */ int to_fill = MAXLEN_MBUF_CHAIN; @@ -487,6 +491,8 @@ recv_function_raw6(void *arg) int want_ext = (iovlen > MLEN)? 1 : 0; int want_header = 0; + sctp_userspace_set_threadname("SCTP/IP6 rcv"); + recvmbuf6 = malloc(sizeof(struct mbuf *) * MAXLEN_MBUF_CHAIN); for (;;) { @@ -586,6 +592,12 @@ recv_function_raw6(void *arg) } } + /* SCTP does not allow broadcasts or multicasts */ + if (IN6_IS_ADDR_MULTICAST(&dst.sin6_addr)) { + m_freem(recvmbuf6[0]); + continue; + } + sh = mtod(recvmbuf6[0], struct sctphdr *); ch = (struct sctp_chunkhdr *)((caddr_t)sh + sizeof(struct sctphdr)); offset = sizeof(struct sctphdr); @@ -674,6 +686,8 @@ recv_function_udp(void *arg) WSACMSGHDR *cmsgptr; #endif + sctp_userspace_set_threadname("SCTP/UDP/IP4 rcv"); + udprecvmbuf = malloc(sizeof(struct mbuf *) * MAXLEN_MBUF_CHAIN); while (1) { @@ -796,10 +810,12 @@ recv_function_udp(void *arg) /* SCTP does not allow broadcasts or multicasts */ if (IN_MULTICAST(ntohl(dst.sin_addr.s_addr))) { - return (NULL); + m_freem(udprecvmbuf[0]); + continue; } if (SCTP_IS_IT_BROADCAST(dst.sin_addr, udprecvmbuf[0])) { - return (NULL); + m_freem(udprecvmbuf[0]); + continue; } /*offset = sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr);*/ @@ -878,6 +894,8 @@ recv_function_udp6(void *arg) WSACMSGHDR *cmsgptr; #endif + sctp_userspace_set_threadname("SCTP/UDP/IP6 rcv"); + udprecvmbuf6 = malloc(sizeof(struct mbuf *) * MAXLEN_MBUF_CHAIN); while (1) { for (i = 0; i < to_fill; i++) { @@ -990,7 +1008,8 @@ recv_function_udp6(void *arg) /* SCTP does not allow broadcasts or multicasts */ if (IN6_IS_ADDR_MULTICAST(&dst.sin6_addr)) { - return (NULL); + m_freem(udprecvmbuf6[0]); + continue; } sh = mtod(udprecvmbuf6[0], struct sctphdr *); @@ -1081,6 +1100,7 @@ recv_thread_init(void) #if !defined(__Userspace_os_Windows) struct timeval timeout; + memset(&timeout, 0, sizeof(struct timeval)); timeout.tv_sec = (SOCKET_TIMEOUT / 1000); timeout.tv_usec = (SOCKET_TIMEOUT % 1000) * 1000; #else @@ -1386,13 +1406,12 @@ recv_thread_init(void) } } #endif -#if !defined(__Userspace_os_Windows) #if defined(__Userspace_os_Darwin) || defined(__Userspace_os_DragonFly) || defined(__Userspace_os_FreeBSD) #if defined(INET) || defined(INET6) if (SCTP_BASE_VAR(userspace_route) != -1) { int rc; - if ((rc = pthread_create(&SCTP_BASE_VAR(recvthreadroute), NULL, &recv_function_route, NULL))) { + if ((rc = sctp_userspace_thread_create(&SCTP_BASE_VAR(recvthreadroute), &recv_function_route))) { SCTPDBG(SCTP_DEBUG_USR, "Can't start routing thread (%d).\n", rc); close(SCTP_BASE_VAR(userspace_route)); SCTP_BASE_VAR(userspace_route) = -1; @@ -1404,18 +1423,26 @@ recv_thread_init(void) if (SCTP_BASE_VAR(userspace_rawsctp) != -1) { int rc; - if ((rc = pthread_create(&SCTP_BASE_VAR(recvthreadraw), NULL, &recv_function_raw, NULL))) { + if ((rc = sctp_userspace_thread_create(&SCTP_BASE_VAR(recvthreadraw), &recv_function_raw))) { SCTPDBG(SCTP_DEBUG_USR, "Can't start SCTP/IPv4 recv thread (%d).\n", rc); +#if defined(__Userspace_os_Windows) + closesocket(SCTP_BASE_VAR(userspace_rawsctp)); +#else close(SCTP_BASE_VAR(userspace_rawsctp)); +#endif SCTP_BASE_VAR(userspace_rawsctp) = -1; } } if (SCTP_BASE_VAR(userspace_udpsctp) != -1) { int rc; - if ((rc = pthread_create(&SCTP_BASE_VAR(recvthreadudp), NULL, &recv_function_udp, NULL))) { + if ((rc = sctp_userspace_thread_create(&SCTP_BASE_VAR(recvthreadudp), &recv_function_udp))) { SCTPDBG(SCTP_DEBUG_USR, "Can't start SCTP/UDP/IPv4 recv thread (%d).\n", rc); +#if defined(__Userspace_os_Windows) + closesocket(SCTP_BASE_VAR(userspace_udpsctp)); +#else close(SCTP_BASE_VAR(userspace_udpsctp)); +#endif SCTP_BASE_VAR(userspace_udpsctp) = -1; } } @@ -1424,56 +1451,30 @@ recv_thread_init(void) if (SCTP_BASE_VAR(userspace_rawsctp6) != -1) { int rc; - if ((rc = pthread_create(&SCTP_BASE_VAR(recvthreadraw6), NULL, &recv_function_raw6, NULL))) { + if ((rc = sctp_userspace_thread_create(&SCTP_BASE_VAR(recvthreadraw6), &recv_function_raw6))) { SCTPDBG(SCTP_DEBUG_USR, "Can't start SCTP/IPv6 recv thread (%d).\n", rc); +#if defined(__Userspace_os_Windows) + closesocket(SCTP_BASE_VAR(userspace_rawsctp6)); +#else close(SCTP_BASE_VAR(userspace_rawsctp6)); +#endif SCTP_BASE_VAR(userspace_rawsctp6) = -1; } } if (SCTP_BASE_VAR(userspace_udpsctp6) != -1) { int rc; - if ((rc = pthread_create(&SCTP_BASE_VAR(recvthreadudp6), NULL, &recv_function_udp6, NULL))) { + if ((rc = sctp_userspace_thread_create(&SCTP_BASE_VAR(recvthreadudp6), &recv_function_udp6))) { SCTPDBG(SCTP_DEBUG_USR, "Can't start SCTP/UDP/IPv6 recv thread (%d).\n", rc); - close(SCTP_BASE_VAR(userspace_udpsctp6)); - SCTP_BASE_VAR(userspace_udpsctp6) = -1; - } - } -#endif +#if defined(__Userspace_os_Windows) + closesocket(SCTP_BASE_VAR(userspace_udpsctp6)); #else -#if defined(INET) - if (SCTP_BASE_VAR(userspace_rawsctp) != -1) { - if ((SCTP_BASE_VAR(recvthreadraw) = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&recv_function_raw, NULL, 0, NULL)) == NULL) { - SCTPDBG(SCTP_DEBUG_USR, "Can't start SCTP/IPv4 recv thread.\n"); - closesocket(SCTP_BASE_VAR(userspace_rawsctp)); - SCTP_BASE_VAR(userspace_rawsctp) = -1; - } - } - if (SCTP_BASE_VAR(userspace_udpsctp) != -1) { - if ((SCTP_BASE_VAR(recvthreadudp) = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&recv_function_udp, NULL, 0, NULL)) == NULL) { - SCTPDBG(SCTP_DEBUG_USR, "Can't start SCTP/UDP/IPv4 recv thread.\n"); - closesocket(SCTP_BASE_VAR(userspace_udpsctp)); - SCTP_BASE_VAR(userspace_udpsctp) = -1; - } - } + close(SCTP_BASE_VAR(userspace_udpsctp6)); #endif -#if defined(INET6) - if (SCTP_BASE_VAR(userspace_rawsctp6) != -1) { - if ((SCTP_BASE_VAR(recvthreadraw6) = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&recv_function_raw6, NULL, 0, NULL)) == NULL) { - SCTPDBG(SCTP_DEBUG_USR, "Can't start SCTP/IPv6 recv thread.\n"); - closesocket(SCTP_BASE_VAR(userspace_rawsctp6)); - SCTP_BASE_VAR(userspace_rawsctp6) = -1; - } - } - if (SCTP_BASE_VAR(userspace_udpsctp6) != -1) { - if ((SCTP_BASE_VAR(recvthreadudp6) = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&recv_function_udp6, NULL, 0, NULL)) == NULL) { - SCTPDBG(SCTP_DEBUG_USR, "Can't start SCTP/UDP/IPv6 recv thread.\n"); - closesocket(SCTP_BASE_VAR(userspace_udpsctp6)); SCTP_BASE_VAR(userspace_udpsctp6) = -1; } } #endif -#endif } void diff --git a/chromium/third_party/usrsctp/usrsctplib/user_recv_thread.h b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/user_recv_thread.h index 61cdf172112..61cdf172112 100755 --- a/chromium/third_party/usrsctp/usrsctplib/user_recv_thread.h +++ b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/user_recv_thread.h diff --git a/chromium/third_party/usrsctp/usrsctplib/user_route.h b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/user_route.h index 82b07d769a9..82b07d769a9 100755 --- a/chromium/third_party/usrsctp/usrsctplib/user_route.h +++ b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/user_route.h diff --git a/chromium/third_party/usrsctp/usrsctplib/user_socket.c b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/user_socket.c index 7134001fe77..9f13cb249e3 100755 --- a/chromium/third_party/usrsctp/usrsctplib/user_socket.c +++ b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/user_socket.c @@ -42,6 +42,9 @@ #ifdef INET6 #include <netinet6/sctp6_var.h> #endif +#if defined(__Userspace_os_FreeBSD) +#include <sys/param.h> +#endif #if defined(__Userspace_os_Linux) #define __FAVOR_BSD /* (on Ubuntu at least) enables UDP header field names like BSD in RFC 768 */ #endif @@ -67,7 +70,8 @@ MALLOC_DEFINE(M_SONAME, "sctp_soname", "sctp soname"); /* Prototypes */ extern int sctp_sosend(struct socket *so, struct sockaddr *addr, struct uio *uio, struct mbuf *top, struct mbuf *control, int flags, - /* proc is a dummy in __Userspace__ and will not be passed to sctp_lower_sosend */ struct proc *p); + /* proc is a dummy in __Userspace__ and will not be passed to sctp_lower_sosend */ + struct proc *p); extern int sctp_attach(struct socket *so, int proto, uint32_t vrf_id); extern int sctpconn_attach(struct socket *so, int proto, uint32_t vrf_id); @@ -77,6 +81,28 @@ usrsctp_init(uint16_t port, int (*conn_output)(void *addr, void *buffer, size_t length, uint8_t tos, uint8_t set_df), void (*debug_printf)(const char *format, ...)) { +#if defined(__Userspace_os_Windows) +#if defined(INET) || defined(INET6) + WSADATA wsaData; + + if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) { + SCTP_PRINTF("WSAStartup failed\n"); + exit (-1); + } +#endif + InitializeConditionVariable(&accept_cond); + InitializeCriticalSection(&accept_mtx); +#else + pthread_mutexattr_t mutex_attr; + + pthread_mutexattr_init(&mutex_attr); +#ifdef INVARIANTS + pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_ERRORCHECK); +#endif + pthread_mutex_init(&accept_mtx, &mutex_attr); + pthread_mutexattr_destroy(&mutex_attr); + pthread_cond_init(&accept_cond, NULL); +#endif sctp_init(port, conn_output, debug_printf); } @@ -274,11 +300,9 @@ sofree(struct socket *so) /* Taken from /src/sys/kern/uipc_socket.c */ -int -soabort(so) - struct socket *so; +void +soabort(struct socket *so) { - int error; #if defined(INET6) struct sctp_inpcb *inp; #endif @@ -286,24 +310,18 @@ soabort(so) #if defined(INET6) inp = (struct sctp_inpcb *)so->so_pcb; if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) { - error = sctp6_abort(so); + sctp6_abort(so); } else { #if defined(INET) - error = sctp_abort(so); -#else - error = EAFNOSUPPORT; + sctp_abort(so); #endif } #elif defined(INET) - error = sctp_abort(so); -#else - error = EAFNOSUPPORT; + sctp_abort(so); #endif - if (error) { - sofree(so); - return error; - } - return (0); + ACCEPT_LOCK(); + SOCK_LOCK(so); + sofree(so); } @@ -509,7 +527,7 @@ sonewconn(struct socket *head, int connstatus) /* * Keep removing sockets from the head until there's room for * us to insert on the tail. In pre-locking revisions, this - * was a simple if(), but as we could be racing with other + * was a simple if (), but as we could be racing with other * threads and soabort() requires dropping locks, we must * loop waiting for the condition to be true. */ @@ -720,7 +738,7 @@ userspace_sctp_sendmsg(struct socket *so, /* Perform error checks on destination (to) */ - if (tolen > SOCK_MAXADDRLEN){ + if (tolen > SOCK_MAXADDRLEN) { errno = ENAMETOOLONG; return (-1); } @@ -729,6 +747,10 @@ userspace_sctp_sendmsg(struct socket *so, errno = EINVAL; return (-1); } + if (data == NULL) { + errno = EFAULT; + return (-1); + } /* Adding the following as part of defensive programming, in case the application does not do it when preparing the destination address.*/ #ifdef HAVE_SA_LEN @@ -775,6 +797,10 @@ usrsctp_sendv(struct socket *so, errno = EBADF; return (-1); } + if (data == NULL) { + errno = EFAULT; + return (-1); + } memset(&sinfo, 0, sizeof(struct sctp_sndrcvinfo)); use_sinfo = 0; switch (infotype) { @@ -912,7 +938,7 @@ sendmsg_return: /* TODO: Needs a condition for non-blocking when error is EWOULDBLOCK */ if (0 == error) retvalsendmsg = len; - else if(error == EWOULDBLOCK) { + else if (error == EWOULDBLOCK) { errno = EWOULDBLOCK; retvalsendmsg = (-1); } else { @@ -1851,7 +1877,7 @@ accept1(struct socket *so, struct sockaddr *aname, socklen_t *anamelen, struct s struct socket * usrsctp_accept(struct socket *so, struct sockaddr *aname, socklen_t *anamelen) { - struct socket *accept_return_sock; + struct socket *accept_return_sock = NULL; errno = accept1(so, aname, anamelen, &accept_return_sock); if (errno) { @@ -2153,6 +2179,16 @@ usrsctp_finish(void) return (-1); } sctp_finish(); +#if defined(__Userspace_os_Windows) + DeleteConditionVariable(&accept_cond); + DeleteCriticalSection(&accept_mtx); +#if defined(INET) || defined(INET6) + WSACleanup(); +#endif +#else + pthread_cond_destroy(&accept_cond); + pthread_mutex_destroy(&accept_mtx); +#endif return (0); } @@ -2833,7 +2869,7 @@ sctp_userspace_ip_output(int *result, struct mbuf *o_pak, SCTP_PRINTF("Why did the SCTP implementation did not choose a source address?\n"); } /* TODO need to worry about ro->ro_dst as in ip_output? */ -#if defined(__Userspace_os_Linux) || defined (__Userspace_os_Windows) +#if defined(__Userspace_os_Linux) || defined (__Userspace_os_Windows) || (defined(__Userspace_os_FreeBSD) && (__FreeBSD_version >= 1100030)) /* need to put certain fields into network order for Linux */ ip->ip_len = htons(ip->ip_len); ip->ip_off = 0; @@ -3130,7 +3166,7 @@ usrsctp_deregister_address(void *addr) #define TRAILER "# SCTP_PACKET\n" char * -usrsctp_dumppacket(void *buf, size_t len, int outbound) +usrsctp_dumppacket(const void *buf, size_t len, int outbound) { size_t i, pos; char *dump_buf, *packet; diff --git a/chromium/third_party/usrsctp/usrsctplib/user_socketvar.h b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/user_socketvar.h index 5c3d9eee7c8..6adf23e1b44 100755 --- a/chromium/third_party/usrsctp/usrsctplib/user_socketvar.h +++ b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/user_socketvar.h @@ -248,14 +248,21 @@ extern userland_cond_t accept_cond; #define ACCEPT_UNLOCK_ASSERT() #else extern userland_mutex_t accept_mtx; + extern userland_cond_t accept_cond; -#define ACCEPT_LOCK_ASSERT() KASSERT(pthread_mutex_trylock(&accept_mtx) == EBUSY, ("%s: accept_mtx not locked", __func__)) -#define ACCEPT_LOCK() (void)pthread_mutex_lock(&accept_mtx) -#define ACCEPT_UNLOCK() (void)pthread_mutex_unlock(&accept_mtx) -#define ACCEPT_UNLOCK_ASSERT() do{ \ - KASSERT(pthread_mutex_trylock(&accept_mtx) == 0, ("%s: accept_mtx locked", __func__)); \ - (void)pthread_mutex_unlock(&accept_mtx); \ -} while (0) +#ifdef INVARIANTS +#define ACCEPT_LOCK() KASSERT(pthread_mutex_lock(&accept_mtx) == 0, ("%s: accept_mtx already locked", __func__)) +#define ACCEPT_UNLOCK() KASSERT(pthread_mutex_unlock(&accept_mtx) == 0, ("%s: accept_mtx not locked", __func__)) +#else +#define ACCEPT_LOCK() (void)pthread_mutex_lock(&accept_mtx) +#define ACCEPT_UNLOCK() (void)pthread_mutex_unlock(&accept_mtx) +#endif +#define ACCEPT_LOCK_ASSERT() \ + KASSERT(pthread_mutex_trylock(&accept_mtx) == EBUSY, ("%s: accept_mtx not locked", __func__)) +#define ACCEPT_UNLOCK_ASSERT() do { \ + KASSERT(pthread_mutex_trylock(&accept_mtx) == 0, ("%s: accept_mtx locked", __func__)); \ + (void)pthread_mutex_unlock(&accept_mtx); \ + } while (0) #endif /* @@ -273,8 +280,19 @@ extern userland_cond_t accept_cond; #define SOCK_COND_DESTROY(_so) DeleteConditionVariable((&(_so)->timeo_cond)) #define SOCK_COND(_so) (&(_so)->timeo_cond) #else +#ifdef INVARIANTS +#define SOCKBUF_LOCK_INIT(_sb, _name) do { \ + pthread_mutexattr_t mutex_attr; \ + \ + pthread_mutexattr_init(&mutex_attr); \ + pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_ERRORCHECK); \ + pthread_mutex_init(SOCKBUF_MTX(_sb), &mutex_attr); \ + pthread_mutexattr_destroy(&mutex_attr); \ +} while (0) +#else #define SOCKBUF_LOCK_INIT(_sb, _name) \ pthread_mutex_init(SOCKBUF_MTX(_sb), NULL) +#endif #define SOCKBUF_LOCK_DESTROY(_sb) pthread_mutex_destroy(SOCKBUF_MTX(_sb)) #define SOCKBUF_COND_INIT(_sb) pthread_cond_init((&(_sb)->sb_cond), NULL) #define SOCKBUF_COND_DESTROY(_sb) pthread_cond_destroy((&(_sb)->sb_cond)) diff --git a/chromium/third_party/usrsctp/usrsctplib/user_uma.h b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/user_uma.h index 1bdefdb8096..1bdefdb8096 100755 --- a/chromium/third_party/usrsctp/usrsctplib/user_uma.h +++ b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/user_uma.h diff --git a/chromium/third_party/usrsctp/usrsctplib/usrsctp.h b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/usrsctp.h index 48b1e43926d..b897f44742d 100644 --- a/chromium/third_party/usrsctp/usrsctplib/usrsctp.h +++ b/chromium/third_party/usrsctp/usrsctplib/usrsctplib/usrsctp.h @@ -532,6 +532,9 @@ struct sctp_event_subscribe { #define SCTP_LOCAL_AUTH_CHUNKS 0x00000103 #define SCTP_GET_ASSOC_NUMBER 0x00000104 #define SCTP_GET_ASSOC_ID_LIST 0x00000105 +#define SCTP_TIMEOUTS 0x00000106 +#define SCTP_PR_STREAM_STATUS 0x00000107 +#define SCTP_PR_ASSOC_STATUS 0x00000108 /* * write-only options @@ -788,6 +791,13 @@ struct sctp_timeouts { uint32_t stimo_shutdownack; }; +struct sctp_prstatus { + sctp_assoc_t sprstat_assoc_id; + uint16_t sprstat_sid; + uint16_t sprstat_policy; + uint64_t sprstat_abandoned_unsent; + uint64_t sprstat_abandoned_sent; +}; /* Standard TCP Congestion Control */ #define SCTP_CC_RFC2581 0x00000000 @@ -961,7 +971,7 @@ usrsctp_set_ulpinfo(struct socket *, void *); #define SCTP_DUMP_INBOUND 0 char * -usrsctp_dumppacket(void *, size_t, int); +usrsctp_dumppacket(const void *, size_t, int); void usrsctp_freedumpbuffer(char *); |