Module Name:    src
Committed By:   rjs
Date:           Thu Aug  2 08:40:48 UTC 2018

Modified Files:
        src/distrib/sets/lists/base: shl.mi
        src/distrib/sets/lists/comp: mi
        src/distrib/sets/lists/debug: shl.mi
        src/lib/libc: shlib_version
        src/lib/libc/net: Makefile.inc
Added Files:
        src/lib/libc/net: sctp_bindx.3 sctp_connectx.3 sctp_freepaddrs.3
            sctp_getaddrlen.3 sctp_getassocid.3 sctp_getpaddrs.3
            sctp_opt_info.3 sctp_peeloff.3 sctp_send.3 sctp_sendmsg.3
            sctp_sys_calls.c

Log Message:
Add userland support for SCTP and manpages.


To generate a diff of this commit:
cvs rdiff -u -r1.843 -r1.844 src/distrib/sets/lists/base/shl.mi
cvs rdiff -u -r1.2214 -r1.2215 src/distrib/sets/lists/comp/mi
cvs rdiff -u -r1.202 -r1.203 src/distrib/sets/lists/debug/shl.mi
cvs rdiff -u -r1.280 -r1.281 src/lib/libc/shlib_version
cvs rdiff -u -r1.87 -r1.88 src/lib/libc/net/Makefile.inc
cvs rdiff -u -r0 -r1.1 src/lib/libc/net/sctp_bindx.3 \
    src/lib/libc/net/sctp_connectx.3 src/lib/libc/net/sctp_freepaddrs.3 \
    src/lib/libc/net/sctp_getaddrlen.3 src/lib/libc/net/sctp_getassocid.3 \
    src/lib/libc/net/sctp_getpaddrs.3 src/lib/libc/net/sctp_opt_info.3 \
    src/lib/libc/net/sctp_peeloff.3 src/lib/libc/net/sctp_send.3 \
    src/lib/libc/net/sctp_sendmsg.3 src/lib/libc/net/sctp_sys_calls.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/distrib/sets/lists/base/shl.mi
diff -u src/distrib/sets/lists/base/shl.mi:1.843 src/distrib/sets/lists/base/shl.mi:1.844
--- src/distrib/sets/lists/base/shl.mi:1.843	Tue Jul 31 13:04:09 2018
+++ src/distrib/sets/lists/base/shl.mi	Thu Aug  2 08:40:47 2018
@@ -1,4 +1,4 @@
-# $NetBSD: shl.mi,v 1.843 2018/07/31 13:04:09 rjs Exp $
+# $NetBSD: shl.mi,v 1.844 2018/08/02 08:40:47 rjs Exp $
 #
 # Note:	Don't delete entries from here - mark them as "obsolete" instead,
 #	unless otherwise stated below.
@@ -18,7 +18,7 @@
 ./lib/libblacklist.so.0.0			base-sys-shlib		dynamicroot
 ./lib/libc.so					base-sys-shlib		dynamicroot
 ./lib/libc.so.12				base-sys-shlib		dynamicroot
-./lib/libc.so.12.210				base-sys-shlib		dynamicroot
+./lib/libc.so.12.211				base-sys-shlib		dynamicroot
 ./lib/libcrypt.so				base-sys-shlib		dynamicroot
 ./lib/libcrypt.so.1				base-sys-shlib		dynamicroot
 ./lib/libcrypt.so.1.0				base-sys-shlib		dynamicroot
@@ -221,7 +221,7 @@
 ./usr/lib/libc++.so.1.0				base-sys-shlib		compatfile,libcxx
 ./usr/lib/libc.so				base-sys-shlib		compatfile
 ./usr/lib/libc.so.12				base-sys-shlib		compatfile
-./usr/lib/libc.so.12.210			base-sys-shlib		compatfile
+./usr/lib/libc.so.12.211			base-sys-shlib		compatfile
 ./usr/lib/libcdk.so				base-obsolete		compatfile,obsolete
 ./usr/lib/libcom_err.so				base-krb5-shlib		compatfile,kerberos
 ./usr/lib/libcom_err.so.8			base-krb5-shlib		compatfile,kerberos

Index: src/distrib/sets/lists/comp/mi
diff -u src/distrib/sets/lists/comp/mi:1.2214 src/distrib/sets/lists/comp/mi:1.2215
--- src/distrib/sets/lists/comp/mi:1.2214	Tue Jul 31 16:44:28 2018
+++ src/distrib/sets/lists/comp/mi	Thu Aug  2 08:40:47 2018
@@ -1,4 +1,4 @@
-#	$NetBSD: mi,v 1.2214 2018/07/31 16:44:28 khorben Exp $
+#	$NetBSD: mi,v 1.2215 2018/08/02 08:40:47 rjs Exp $
 #
 # Note: don't delete entries from here - mark them as "obsolete" instead.
 ./etc/mtree/set.comp				comp-sys-root
@@ -16992,6 +16992,17 @@
 ./usr/share/man/html3/scrl.html			comp-c-htmlman		html
 ./usr/share/man/html3/scroll.html		comp-c-htmlman		html
 ./usr/share/man/html3/scrollok.html		comp-c-htmlman		html
+./usr/share/man/html3/sctp_bindx.html		comp-c-htmlman		html
+./usr/share/man/html3/sctp_connectx.html	comp-c-htmlman		html
+./usr/share/man/html3/sctp_freepaddrs.html	comp-c-htmlman		html
+./usr/share/man/html3/sctp_getaddrlen.html	comp-c-htmlman		html
+./usr/share/man/html3/sctp_getassocid.html	comp-c-htmlman		html
+./usr/share/man/html3/sctp_getpaddrs.html	comp-c-htmlman		html
+./usr/share/man/html3/sctp_opt_info.html	comp-c-htmlman		html
+./usr/share/man/html3/sctp_peeloff.html		comp-c-htmlman		html
+./usr/share/man/html3/sctp_recvmsg.html		comp-c-htmlman		html
+./usr/share/man/html3/sctp_send.html		comp-c-htmlman		html
+./usr/share/man/html3/sctp_sendmsg.html		comp-c-htmlman		html
 ./usr/share/man/html3/sdp.html			comp-c-htmlman		html
 ./usr/share/man/html3/sdp_attr2desc.html	comp-obsolete		obsolete
 ./usr/share/man/html3/sdp_change_service.html	comp-obsolete		obsolete
@@ -24777,6 +24788,17 @@
 ./usr/share/man/man3/scrl.3			comp-c-man		.man
 ./usr/share/man/man3/scroll.3			comp-c-man		.man
 ./usr/share/man/man3/scrollok.3			comp-c-man		.man
+./usr/share/man/man3/sctp_bindx.3		comp-c-man		.man
+./usr/share/man/man3/sctp_connectx.3		comp-c-man		.man
+./usr/share/man/man3/sctp_freepaddrs.3		comp-c-man		.man
+./usr/share/man/man3/sctp_getaddrlen.3		comp-c-man		.man
+./usr/share/man/man3/sctp_getassocid.3		comp-c-man		.man
+./usr/share/man/man3/sctp_getpaddrs.3		comp-c-man		.man
+./usr/share/man/man3/sctp_opt_info.3		comp-c-man		.man
+./usr/share/man/man3/sctp_peeloff.3		comp-c-man		.man
+./usr/share/man/man3/sctp_recvmsg.3		comp-c-man		.man
+./usr/share/man/man3/sctp_send.3		comp-c-man		.man
+./usr/share/man/man3/sctp_sendmsg.3		comp-c-man		.man
 ./usr/share/man/man3/sdp.3			comp-c-man		.man
 ./usr/share/man/man3/sdp_attr2desc.3		comp-obsolete		obsolete
 ./usr/share/man/man3/sdp_change_service.3	comp-obsolete		obsolete

Index: src/distrib/sets/lists/debug/shl.mi
diff -u src/distrib/sets/lists/debug/shl.mi:1.202 src/distrib/sets/lists/debug/shl.mi:1.203
--- src/distrib/sets/lists/debug/shl.mi:1.202	Tue Jul 31 22:29:55 2018
+++ src/distrib/sets/lists/debug/shl.mi	Thu Aug  2 08:40:48 2018
@@ -1,8 +1,8 @@
-# $NetBSD: shl.mi,v 1.202 2018/07/31 22:29:55 kre Exp $
+# $NetBSD: shl.mi,v 1.203 2018/08/02 08:40:48 rjs Exp $
 ./usr/lib/libbfd_g.a						comp-c-debuglib	debuglib,compatfile,binutils
 ./usr/libdata/debug/lib						base-sys-usr	debug,dynamicroot,compatdir
 ./usr/libdata/debug/lib/libblacklist.so.0.0.debug		comp-sys-debug	debug,dynamicroot
-./usr/libdata/debug/lib/libc.so.12.210.debug			comp-sys-debug	debug,dynamicroot
+./usr/libdata/debug/lib/libc.so.12.211.debug			comp-sys-debug	debug,dynamicroot
 ./usr/libdata/debug/lib/libcrypt.so.1.0.debug			comp-sys-debug	debug,dynamicroot
 ./usr/libdata/debug/lib/libcrypto.so.12.0.debug			comp-sys-debug	debug,dynamicroot,openssl=10
 ./usr/libdata/debug/lib/libcrypto.so.13.0.debug			comp-sys-debug	debug,dynamicroot,openssl=11
@@ -72,7 +72,7 @@
 ./usr/libdata/debug/usr/lib/libbsdmalloc.so.0.0.debug		comp-sys-debug	debug,compatfile
 ./usr/libdata/debug/usr/lib/libbz2.so.1.1.debug			comp-sys-debug	debug,compatfile
 ./usr/libdata/debug/usr/lib/libc++.so.1.0.debug			comp-sys-debug	debug,compatfile,libcxx
-./usr/libdata/debug/usr/lib/libc.so.12.210.debug		comp-sys-debug	debug,compatfile
+./usr/libdata/debug/usr/lib/libc.so.12.211.debug		comp-sys-debug	debug,compatfile
 ./usr/libdata/debug/usr/lib/libcom_err.so.8.0.debug		comp-krb5-debug	debug,compatfile,kerberos
 ./usr/libdata/debug/usr/lib/libcrypt.so.1.0.debug		comp-sys-debug	debug,compatfile
 ./usr/libdata/debug/usr/lib/libcrypto.so.12.0.debug		comp-crypto-debug	debug,compatfile,openssl=10

Index: src/lib/libc/shlib_version
diff -u src/lib/libc/shlib_version:1.280 src/lib/libc/shlib_version:1.281
--- src/lib/libc/shlib_version:1.280	Tue Jul 31 13:04:10 2018
+++ src/lib/libc/shlib_version	Thu Aug  2 08:40:48 2018
@@ -1,4 +1,4 @@
-#	$NetBSD: shlib_version,v 1.280 2018/07/31 13:04:10 rjs Exp $
+#	$NetBSD: shlib_version,v 1.281 2018/08/02 08:40:48 rjs Exp $
 #	Remember to update distrib/sets/lists/base/shl.* when changing
 #
 # things we wish to do on next major version bump:
@@ -53,4 +53,4 @@
 # - move environ and __ps_strings from crt0.o into libc.
 # - move statfs() to libcompat since we have statvfs()
 major=12
-minor=210
+minor=211

Index: src/lib/libc/net/Makefile.inc
diff -u src/lib/libc/net/Makefile.inc:1.87 src/lib/libc/net/Makefile.inc:1.88
--- src/lib/libc/net/Makefile.inc:1.87	Sun Jun 18 04:03:44 2017
+++ src/lib/libc/net/Makefile.inc	Thu Aug  2 08:40:48 2018
@@ -1,4 +1,4 @@
-#	$NetBSD: Makefile.inc,v 1.87 2017/06/18 04:03:44 manu Exp $
+#	$NetBSD: Makefile.inc,v 1.88 2018/08/02 08:40:48 rjs Exp $
 #	@(#)Makefile.inc	8.2 (Berkeley) 9/5/93
 
 # net sources
@@ -13,7 +13,7 @@ SRCS+=	base64.c ethers.c gethnamaddr.c g
 	iso_addr.c linkaddr.c \
 	nsdispatch.c nslexer.l nsparser.y nsap_addr.c \
 	rcmd.c recv.c send.c sethostent.c \
-	sockatmark.c
+	sctp_sys_calls.c sockatmark.c
 
 .if (${MKHESIOD} != "no")
 SRCS+=	hesiod.c
@@ -145,3 +145,8 @@ MLINKS+=getaddrinfo.3 freeaddrinfo.3 \
 	inet6_rth_space.3 inet6_rth_getaddr.3 \
 	rcmd.3 rcmd_af.3 rcmd.3 iruserok_sa.3 rcmd.3 rresvport_af.3 \
 	rcmd.3 orcmd_af.3
+
+# SCTP
+MAN+=	sctp_bindx.3 sctp_connectx.3 sctp_freepaddrs.3 sctp_getaddrlen.3 \
+	sctp_getassocid.3 sctp_getpaddrs.3 sctp_opt_info.3 sctp_peeloff.3 \
+	sctp_recvmsg.3 sctp_send.3 sctp_sendmsg.3

Added files:

Index: src/lib/libc/net/sctp_bindx.3
diff -u /dev/null src/lib/libc/net/sctp_bindx.3:1.1
--- /dev/null	Thu Aug  2 08:40:48 2018
+++ src/lib/libc/net/sctp_bindx.3	Thu Aug  2 08:40:48 2018
@@ -0,0 +1,120 @@
+.\"	$NetBSD: sctp_bindx.3,v 1.1 2018/08/02 08:40:48 rjs Exp $
+.\"
+.\" Copyright (c) 1983, 1991, 1993
+.\"	The Regents of the University of California.  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 University 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 REGENTS 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 REGENTS 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.
+.\"
+.\"     From: @(#)send.2	8.2 (Berkeley) 2/21/94
+.\"
+.Dd August 1, 2018
+.Dt SCTP_BINDX 3
+.Os
+.Sh NAME
+.Nm sctp_bindx
+.Nd bind or unbind an SCTP socket to a list of addresses.
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/socket.h
+.In netinet/sctp.h
+.Ft int
+.Fn sctp_bindx "int s" "struct sockaddr *addrs" "int num" "int type"
+.Sh DESCRIPTION
+The
+.Fn sctp_bindx
+call binds or unbinds a address or a list of addresses to an
+SCTP endpoint.
+This allows a user to bind a subset of
+addresses.
+The
+.Fn sctp_bindx
+call operates similarly to
+.Fn bind
+but allows a list of addresses and also allows a bind or an
+unbind.
+The argument
+.Fa s
+must be a valid SCTP socket descriptor.
+The argument
+.Fa addrs
+is a list of addresses (where the list may be only 1 in
+length) that the user wishes to bind or unbind to the
+socket.
+The argument
+.Fa type
+must be one of the following values.
+.Pp
+.Dv SCTP_BINDX_ADD_ADDR
+This value indicates that the listed address(es) need to
+be added to the endpoint.
+.Pp
+.Dv SCTP_BINDX_DEL_ADDR
+This value indicates that the listed address(es) need to
+be removed from the endpoint.
+.Pp
+Note that when a user adds or deletes an address to an
+association if the dynamic address flag
+.Va net.inet.sctp.auto_asconf
+is enabled any associations in the endpoint will attempt to
+have the address(es) added dynamically to the existing
+association.
+.Sh RETURN VALUES
+The call returns 0 on success and -1 upon failure.
+.Sh ERRORS
+The
+.Fn sctp_bindx
+function can return the following errors:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+This value is returned if the
+.Fa type
+field is not one of the allowed values (see above).
+.It Bq Er ENOMEM
+This value is returned if the number of addresses
+being added causes a memory allocation failure in
+the call.
+.It Bq Er EBADF
+The argument
+.Fa s
+is not a valid descriptor.
+.It Bq Er ENOTSOCK
+The argument
+.Fa s
+is not a socket.
+.El
+.Sh SEE ALSO
+.Xr bind 2 ,
+.Xr sctp 4
+.Rs
+.%R RFC
+.%N 6458
+.%T "Sockets API Extensions for the Stream Control Transmission Protocol (SCTP)"
+.%D December 2011
+.Re 
+.Sh HISTORY
+This function first appeared in
+.Nx 9.0 .
Index: src/lib/libc/net/sctp_connectx.3
diff -u /dev/null src/lib/libc/net/sctp_connectx.3:1.1
--- /dev/null	Thu Aug  2 08:40:48 2018
+++ src/lib/libc/net/sctp_connectx.3	Thu Aug  2 08:40:48 2018
@@ -0,0 +1,111 @@
+.\"	$NetBSD: sctp_connectx.3,v 1.1 2018/08/02 08:40:48 rjs Exp $
+.\"
+.\" Copyright (c) 1983, 1991, 1993
+.\"	The Regents of the University of California.  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 University 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 REGENTS 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 REGENTS 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.
+.\"
+.Dd August 1, 2018
+.Dt SCTP_CONNECTX 3
+.Os
+.Sh NAME
+.Nm sctp_connectx
+.Nd connect an SCTP socket with multiple destination addresses
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/socket.h
+.In netinet/sctp.h
+.Ft int
+.Fn sctp_connectx "int sd" "struct sockaddr *addrs" "int addrcnt" "sctp_assoc_t *id"
+.Sh DESCRIPTION
+The
+.Fn sctp_connectx
+call attempts to initiate an association to a peer SCTP
+endpoint.
+The call operates similarly to
+.Fn connect
+but it also provides the ability to specify multiple destination
+addresses for the peer.
+This allows a fault tolerant method
+of initiating an association.
+When one of the peers addresses
+is unreachable, the subsequent listed addresses will also be used
+to set up the association with the peer.
+.Pp
+The user also needs to consider that any address listed in an
+.Fn sctp_connectx
+call is also considered "confirmed".
+A confirmed address is one in
+which the SCTP transport will trust is a part of the association
+and it will not send a confirmation heartbeat to it with
+a random nonce.
+.Pp
+If the peer SCTP stack does not list one or more of
+the provided addresses in its response message then
+the extra addresses sent in the
+.Fn sctp_connectx
+call will be silently discarded from the association.
+On
+successful completion the provided
+.Fa id
+will be
+filled in with the association identification of the newly
+forming association.
+.Sh RETURN VALUES
+The call returns 0 on success and -1 upon failure.
+.Sh ERRORS
+The
+.Fn sctp_connectx
+function can return the following errors:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+An address listed has an invalid family or no
+addresses were provided.
+.It Bq Er E2BIG
+The size of the address list exceeds the amount of
+data provided.
+.It Bq Er EBADF
+The argument
+.Fa s
+is not a valid descriptor.
+.It Bq Er ENOTSOCK
+The argument
+.Fa s
+is not a socket.
+.El
+.Sh SEE ALSO
+.Xr connect 2 ,
+.Xr sctp 4
+.Rs
+.%R RFC
+.%N 6458
+.%T "Sockets API Extensions for the Stream Control Transmission Protocol (SCTP)"
+.%D December 2011
+.Re 
+.Sh HISTORY
+This function first appeared in
+.Nx 9.0 .
Index: src/lib/libc/net/sctp_freepaddrs.3
diff -u /dev/null src/lib/libc/net/sctp_freepaddrs.3:1.1
--- /dev/null	Thu Aug  2 08:40:48 2018
+++ src/lib/libc/net/sctp_freepaddrs.3	Thu Aug  2 08:40:48 2018
@@ -0,0 +1,75 @@
+.\"	$NetBSD: sctp_freepaddrs.3,v 1.1 2018/08/02 08:40:48 rjs Exp $
+.\"
+.\" Copyright (c) 1983, 1991, 1993
+.\"	The Regents of the University of California.  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 University 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 REGENTS 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 REGENTS 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.
+.\"
+.\"     From: @(#)send.2	8.2 (Berkeley) 2/21/94
+.\"
+.Dd August 1, 2018
+.Dt SCTP_FREEPADDRS 3
+.Os
+.Sh NAME
+.Nm sctp_freepaddrs ,
+.Nm sctp_freeladdrs
+.Nd release the memory returned from a previous call
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/socket.h
+.In netinet/sctp.h
+.Ft void
+.Fn sctp_freepaddrs "struct sockaddr *"
+.Ft void
+.Fn sctp_freeladdrs "struct sockaddr *"
+.Sh DESCRIPTION
+The
+.Fn sctp_freepaddrs
+and
+.Fn sctp_freeladdrs
+functions are used to release the memory allocated by previous
+calls to
+.Fn sctp_getpaddrs
+or
+.Fn sctp_getladdrs
+respectively.
+.Sh RETURN VALUES
+none.
+.Sh SEE ALSO
+.Xr sctp_getladdrs 3 ,
+.Xr sctp_getpaddrs 3 ,
+.Xr sctp 4
+.Rs
+.%R RFC
+.%N 6458
+.%T "Sockets API Extensions for the Stream Control Transmission Protocol (SCTP)"
+.%D December 2011
+.Re 
+.Sh HISTORY
+These functions first appeared in
+.Nx 9.0 .
+
Index: src/lib/libc/net/sctp_getaddrlen.3
diff -u /dev/null src/lib/libc/net/sctp_getaddrlen.3:1.1
--- /dev/null	Thu Aug  2 08:40:48 2018
+++ src/lib/libc/net/sctp_getaddrlen.3	Thu Aug  2 08:40:48 2018
@@ -0,0 +1,93 @@
+.\"	$NetBSD: sctp_getaddrlen.3,v 1.1 2018/08/02 08:40:48 rjs Exp $
+.\"
+.\" Copyright (c) 1983, 1991, 1993
+.\"	The Regents of the University of California.  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 University 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 REGENTS 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 REGENTS 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.
+.\"
+.\"     From: @(#)send.2	8.2 (Berkeley) 2/21/94
+.\"
+.Dd August 1, 2018
+.Dt SCTP_GETADDRLEN 3
+.Os
+.Sh NAME
+.Nm sctp_getaddrlen
+.Nd return the address length of an address family
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/socket.h
+.In netinet/sctp.h
+.Ft int
+.Fn sctp_getaddrlen "sa_family_t family"
+.Sh DESCRIPTION
+The
+.Fn sctp_getaddrlen
+function returns the size of a specific address family.
+This function
+is provided for application binary compatibility since it
+provides the application with the size the operating system
+thinks the specific address family is.
+Note that the function
+will actually create an SCTP socket and then gather the
+information via a
+.Fn getsockopt
+system calls.
+If for some reason a SCTP socket cannot
+be created or the
+.Fn getsockopt
+call fails, an error will be returned
+with
+.Va errno
+set as specified in the
+.Fn socket
+or
+.Fn getsockopt
+system call.
+.Sh RETURN VALUES
+The call returns the number of bytes that the operating
+system expects for the specific address family or -1.
+.Sh ERRORS
+The
+.Fn sctp_getaddrlen
+function can return the following errors:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The address family specified does NOT exist.
+.El
+.Sh SEE ALSO
+.Xr getsockopt 2 ,
+.Xr socket 2 ,
+.Xr sctp 4
+.Rs
+.%R RFC
+.%N 6458
+.%T "Sockets API Extensions for the Stream Control Transmission Protocol (SCTP)"
+.%D December 2011
+.Re 
+.Sh HISTORY
+This function first appeared in
+.Nx 9.0 .
Index: src/lib/libc/net/sctp_getassocid.3
diff -u /dev/null src/lib/libc/net/sctp_getassocid.3:1.1
--- /dev/null	Thu Aug  2 08:40:48 2018
+++ src/lib/libc/net/sctp_getassocid.3	Thu Aug  2 08:40:48 2018
@@ -0,0 +1,79 @@
+.\"	$NetBSD: sctp_getassocid.3,v 1.1 2018/08/02 08:40:48 rjs Exp $
+.\"
+.\" Copyright (c) 1983, 1991, 1993
+.\"	The Regents of the University of California.  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 University 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 REGENTS 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 REGENTS 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.
+.\"
+.Dd August 1, 2018
+.Dt SCTP_GETASSOCID 3
+.Os
+.Sh NAME
+.Nm sctp_getassocid
+.Nd return an association id for a specified socket address.
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/socket.h
+.In netinet/sctp.h
+.Ft sctp_assoc_t
+.Fn sctp_getassocid "int s" "struct sockaddr *addr"
+.Sh DESCRIPTION
+The
+.Fn sctp_getassocid
+call attempts to look up the specified socket address
+.Fa addr
+and find the respective association identification.
+.Sh RETURN VALUES
+The call returns the association id upon success and
+0 is returned upon failure.
+.Sh ERRORS
+The
+.Fn sctp_getassocid
+function can return the following errors:
+.Bl -tag -width Er
+.It Bq Er ENOENT
+The address does not have an association setup to it.
+.It Bq Er EBADF
+The argument
+.Fa s
+is not a valid descriptor.
+.It Bq Er ENOTSOCK
+The argument
+.Fa s
+is not a socket.
+.El
+.Sh SEE ALSO
+.Xr sctp 4
+.Rs
+.%R RFC
+.%N 6458
+.%T "Sockets API Extensions for the Stream Control Transmission Protocol (SCTP)"
+.%D December 2011
+.Re 
+.Sh HISTORY
+This function first appeared in
+.Nx 9.0 .
Index: src/lib/libc/net/sctp_getpaddrs.3
diff -u /dev/null src/lib/libc/net/sctp_getpaddrs.3:1.1
--- /dev/null	Thu Aug  2 08:40:48 2018
+++ src/lib/libc/net/sctp_getpaddrs.3	Thu Aug  2 08:40:48 2018
@@ -0,0 +1,106 @@
+.\"	$NetBSD: sctp_getpaddrs.3,v 1.1 2018/08/02 08:40:48 rjs Exp $
+.\"
+.\" Copyright (c) 1983, 1991, 1993
+.\"	The Regents of the University of California.  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 University 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 REGENTS 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 REGENTS 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.
+.\"
+.\"     From: @(#)send.2	8.2 (Berkeley) 2/21/94
+.\"
+.Dd August 1, 2018
+.Dt SCTP_GETPADDRS 3
+.Os
+.Sh NAME
+.Nm sctp_getpaddrs ,
+.Nm sctp_getladdrs
+.Nd return a list of addresses to the caller
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/socket.h
+.In netinet/sctp.h
+.Ft int
+.Fn sctp_getpaddrs "int s" "sctp_assoc_t asocid" "struct sockaddr **addrs"
+.Ft int
+.Fn sctp_getladdrs "int s" "sctp_assoc_t asocid" "struct sockaddr **addrs"
+.Sh DESCRIPTION
+The
+.Fn sctp_getpaddrs
+function is used to get the list of the peers addresses.
+The
+.Fn sctp_getladdrs
+function is used to get the list of the local addresses.
+The association of interest is identified by the
+.Fa asocid
+argument.
+The addresses are returned in a newly allocated
+array of socket addresses returned in the argument
+.Fa addrs
+upon success.
+.Pp
+After the caller is finished, the function
+.Fn sctp_freepaddrs
+or
+.Fn sctp_freeladdrs
+should be used to release the memory allocated by these
+calls.
+.Sh RETURN VALUES
+The call returns -1 upon failure and a count of
+the number of addresses returned in
+.Fa addrs
+upon success.
+.Sh ERRORS
+The functions can return the following errors:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+An address listed has an invalid family or no
+addresses were provided.
+.It Bq Er ENOMEM
+The call cannot allocate memory to hold the
+socket addresses.
+.It Bq Er EBADF
+The argument
+.Fa s
+is not a valid descriptor.
+.It Bq Er ENOTSOCK
+The argument
+.Fa s
+is not a socket.
+.El
+.Sh SEE ALSO
+.Xr getsockopt 2 ,
+.Xr sctp_freeladdrs 3 ,
+.Xr sctp_freepaddrs 3 ,
+.Xr sctp 4
+.Rs
+.%R RFC
+.%N 6458
+.%T "Sockets API Extensions for the Stream Control Transmission Protocol (SCTP)"
+.%D December 2011
+.Re 
+.Sh HISTORY
+These functions first appeared in
+.Nx 9.0 .
Index: src/lib/libc/net/sctp_opt_info.3
diff -u /dev/null src/lib/libc/net/sctp_opt_info.3:1.1
--- /dev/null	Thu Aug  2 08:40:48 2018
+++ src/lib/libc/net/sctp_opt_info.3	Thu Aug  2 08:40:48 2018
@@ -0,0 +1,129 @@
+.\"	$NetBSD: sctp_opt_info.3,v 1.1 2018/08/02 08:40:48 rjs Exp $
+.\"
+.\" Copyright (c) 1983, 1991, 1993
+.\"	The Regents of the University of California.  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 University 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 REGENTS 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 REGENTS 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.
+.\"
+.\"     From: @(#)send.2	8.2 (Berkeley) 2/21/94
+.\"
+.Dd August 1, 2018
+.Dt SCTP_OPT_INFO 3
+.Os
+.Sh NAME
+.Nm sctp_opt_info
+.Nd get SCTP socket information
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/socket.h
+.In netinet/sctp.h
+.Ft int
+.Fn sctp_opt_info "int sd" "sctp_assoc_t id" "int opt" "void *arg" "socklen_t *size"
+.Sh DESCRIPTION
+The
+.Fn sctp_opt_info
+call provides a multi-os compatible method for getting
+specific
+.Fn getsockopt
+data where an association identification needs to be passed
+into the operating system.
+For those
+who wish to write portable code amongst multiple operating systems
+this call should be used for the following SCTP
+socket options.
+.Pp
+.Dv SCTP_RTOINFO
+.Pp
+.Dv SCTP_ASSOCINFO
+.Pp
+.Dv SCTP_PRIMARY_ADDR
+.Pp
+.Dv SCTP_PEER_ADDR_PARAMS
+.Pp
+.Dv SCTP_DEFAULT_SEND_PARAM
+.Pp
+.Dv SCTP_MAX_SEG
+.Pp
+.Dv SCTP_AUTH_ACTIVE_KEY
+.Pp
+.Dv SCTP_DELAYED_SACK
+.Pp
+.Dv SCTP_MAX_BURST
+.Pp
+.Dv SCTP_CONTEXT
+.Pp
+.Dv SCTP_EVENT
+.Pp
+.Dv SCTP_DEFAULT_SNDINFO
+.Pp
+.Dv SCTP_DEFAULT_PRINFO
+.Pp
+.Dv SCTP_STATUS
+.Pp
+.Dv SCTP_GET_PEER_ADDR_INFO
+.Pp
+.Dv SCTP_PEER_AUTH_CHUNKS
+.Pp
+.Dv SCTP_LOCAL_AUTH_CHUNKS
+.Sh RETURN VALUES
+The call returns 0 on success and -1 upon error.
+.Sh ERRORS
+The
+.Fn sctp_opt_info
+function can return the following errors:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The argument
+.Fa arg
+value was invalid.
+.It Bq Er EOPNOTSUPP
+The argument
+.Fa opt
+was not one of the above listed SCTP socket
+options.
+.It Bq Er EBADF
+The argument
+.Fa s
+is not a valid descriptor.
+.It Bq Er ENOTSOCK
+The argument
+.Fa s
+is not a socket.
+.El
+.Sh SEE ALSO
+.Xr getsockopt 2 ,
+.Xr getsockopt2 2,
+.Xr sctp 4
+.Rs
+.%R RFC
+.%N 6458
+.%T "Sockets API Extensions for the Stream Control Transmission Protocol (SCTP)"
+.%D December 2011
+.Re 
+.Sh HISTORY
+This function first appeared in
+.Nx 9.0 .
Index: src/lib/libc/net/sctp_peeloff.3
diff -u /dev/null src/lib/libc/net/sctp_peeloff.3:1.1
--- /dev/null	Thu Aug  2 08:40:48 2018
+++ src/lib/libc/net/sctp_peeloff.3	Thu Aug  2 08:40:48 2018
@@ -0,0 +1,85 @@
+.\" $NetBSD: sctp_peeloff.3,v 1.1 2018/08/02 08:40:48 rjs Exp $
+.\"
+.\" Copyright (c) 1983, 1991, 1993
+.\"	The Regents of the University of California.  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 University 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 REGENTS 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 REGENTS 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.
+.\"
+.Dd August 1, 2018
+.Dt SCTP_PEELOFF 3
+.Os
+.Sh NAME
+.Nm sctp_peeloff
+.Nd detach an association from a one-to-many socket to its own fd
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/socket.h
+.In netinet/sctp.h
+.Ft int
+.Fn sctp_peeloff "int s" "sctp_assoc_t id"
+.Sh DESCRIPTION
+The
+.Fn sctp_peeloff
+function attempts detach the association specified by
+.Fa id
+into its own separate socket.
+.Sh RETURN VALUES
+The call returns -1 on failure and the new socket descriptor
+upon success.
+.Sh ERRORS
+The
+.Fn sctp_peeloff
+function can return the following errors:
+.Bl -tag -width Er
+.It Bq Er ENOTCONN
+The
+.Fa id
+given to the call does not map to a valid
+association.
+.It Bq Er E2BIG
+The size of the address list exceeds the amount of
+data provided.
+.It Bq Er EBADF
+The argument
+.Fa s
+is not a valid descriptor.
+.It Bq Er ENOTSOCK
+The argument
+.Fa s
+is not a socket.
+.El
+.Sh SEE ALSO
+.Xr sctp 4
+.Rs
+.%R RFC
+.%N 6458
+.%T "Sockets API Extensions for the Stream Control Transmission Protocol (SCTP)"
+.%D December 2011
+.Re 
+.Sh HISTORY
+This function first appeared in
+.Nx 9.0 .
Index: src/lib/libc/net/sctp_send.3
diff -u /dev/null src/lib/libc/net/sctp_send.3:1.1
--- /dev/null	Thu Aug  2 08:40:48 2018
+++ src/lib/libc/net/sctp_send.3	Thu Aug  2 08:40:48 2018
@@ -0,0 +1,359 @@
+.\"	$NetBSD: sctp_send.3,v 1.1 2018/08/02 08:40:48 rjs Exp $
+.\"
+.\" Copyright (c) 1983, 1991, 1993
+.\"	The Regents of the University of California.  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 University 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 REGENTS 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 REGENTS 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.
+.\"
+.Dd August 1, 2018
+.Dt SCTP_SEND 3
+.Os
+.Sh NAME
+.Nm sctp_send ,
+.Nm sctp_sendx
+.Nd send a message from an SCTP socket
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/socket.h
+.In netinet/sctp.h
+.Ft ssize_t
+.Fo sctp_send
+.Fa "int sd" "const void *msg" "size_t len"
+.Fa "const struct sctp_sndrcvinfo *sinfo" "int flags"
+.Fc
+.Ft ssize_t
+.Fo sctp_sendx
+.Fa "int sd" "const void *msg" "size_t len" "struct sockaddr *addrs"
+.Fa "int addrcnt" "const struct sctp_sndrcvinfo *sinfo" "int flags"
+.Fc
+.Sh DESCRIPTION
+The
+.Fn sctp_send
+system call
+is used to transmit a message to another SCTP endpoint.
+.Fn sctp_send
+may be used to send data to an existing association for both
+one-to-many (SOCK_SEQPACKET) and one-to-one (SOCK_STREAM) socket types.
+The length of the message
+.Fa msg
+is given by
+.Fa len .
+If the message is too long to pass atomically through the
+underlying protocol,
+.Va errno
+is set to
+.Er EMSGSIZE ,
+-1 is returned, and
+the message is not transmitted.
+.Pp
+No indication of failure to deliver is implicit in a
+.Fn sctp_send .
+Locally detected errors are indicated by a return value of -1.
+.Pp
+If no space is available at the socket to hold
+the message to be transmitted, then
+.Fn sctp_send
+normally blocks, unless the socket has been placed in
+non-blocking I/O mode.
+The
+.Xr select 2
+system call may be used to determine when it is possible to
+send more data on one-to-one type (SOCK_STREAM) sockets.
+.Pp
+The
+.Fa sinfo
+structure is used to control various SCTP features
+and has the following format:
+.Bd -literal
+struct sctp_sndrcvinfo {
+	uint16_t sinfo_stream;  /* Stream sending to */
+	uint16_t sinfo_ssn;     /* valid for recv only */
+	uint16_t sinfo_flags;   /* flags to control sending */
+	uint32_t sinfo_ppid;    /* ppid field */
+	uint32_t sinfo_context; /* context field */
+	uint32_t sinfo_timetolive; /* timetolive for PR-SCTP */
+	uint32_t sinfo_tsn;        /* valid for recv only */
+	uint32_t sinfo_cumtsn;     /* valid for recv only */
+	sctp_assoc_t sinfo_assoc_id; /* The association id */
+};
+.Ed
+.Pp
+The
+.Fa sinfo->sinfo_ppid
+argument is an opaque 32 bit value that is passed transparently
+through the stack to the peer endpoint. It will be available on
+reception of a message (see
+.Xr sctp_recvmsg 3 ) .
+Note that the stack passes this value without regard to byte
+order.
+.Pp
+The
+.Fa sinfo->sinfo_flags
+argument may include one or more of the following:
+.Bd -literal
+#define SCTP_EOF 	  0x0100	/* Start a shutdown procedures */
+#define SCTP_ABORT	  0x0200	/* Send an ABORT to peer */
+#define SCTP_UNORDERED 	  0x0400	/* Message is un-ordered */
+#define SCTP_ADDR_OVER	  0x0800	/* Override the primary-address */
+#define SCTP_SENDALL      0x1000	/* Send this on all associations */
+					/* for the endpoint */
+/* The lower byte is an enumeration of PR-SCTP policies */
+#define SCTP_PR_SCTP_TTL  0x0001	/* Time based PR-SCTP */
+#define SCTP_PR_SCTP_BUF  0x0002	/* Buffer based PR-SCTP */
+#define SCTP_PR_SCTP_RTX  0x0003	/* Number of retransmissions based PR-SCTP */
+.Ed
+.Pp
+The flag
+.Dv SCTP_EOF
+is used to instruct the SCTP stack to queue this message
+and then start a graceful shutdown of the association.
+All
+remaining data in queue will be sent after which the association
+will be shut down.
+.Pp
+.Dv SCTP_ABORT
+is used to immediately terminate an association.
+An abort
+is sent to the peer and the local TCB is destroyed.
+.Pp
+.Dv SCTP_UNORDERED
+is used to specify that the message being sent has no
+specific order and should be delivered to the peer application
+as soon as possible.
+When this flag is absent messages
+are delivered in order within the stream they are sent, but without
+respect to order to peer streams.
+.Pp
+The flag
+.Dv SCTP_ADDR_OVER
+is used to specify that a specific address should be used.
+Normally
+SCTP will use only one of a multi-homed peers addresses as the primary
+address to send to.
+By default, no matter what the
+.Fa to
+argument is, this primary address is used to send data.
+By specifying
+this flag, the user is asking the stack to ignore the primary address
+and instead use the specified address not only as a lookup mechanism
+to find the association but also as the actual address to send to.
+.Pp
+For a one-to-many type (SOCK_SEQPACKET) socket the flag
+.Dv SCTP_SENDALL
+can be used as a convenient way to make one send call and have
+all associations that are under the socket get a copy of the message.
+Note that this mechanism is quite efficient and makes only one actual
+copy of the data which is shared by all the associations for sending.
+.Pp
+The remaining flags are used for the partial reliability extension (RFC3758)
+and will only be effective if the peer endpoint supports this extension.
+This option specifies what local policy the local endpoint should use
+in skipping data.
+If none of these options are set, then data is
+never skipped over.
+.Pp
+.Dv SCTP_PR_SCTP_TTL
+is used to indicate that a time based lifetime is being applied
+to the data.
+The
+.Fa sinfo->sinfo_timetolive
+argument is then a number of milliseconds for which the data is
+attempted to be transmitted.
+If that many milliseconds elapse
+and the peer has not acknowledged the data, the data will be
+skipped and no longer transmitted.
+Note that this policy does
+not even assure that the data will ever be sent.
+In times of a congestion
+with large amounts of data being queued, the
+.Fa sinfo->sinfo_timetolive
+may expire before the first transmission is ever made.
+.Pp
+The
+.Dv SCTP_PR_SCTP_BUF
+based policy transforms the
+.Fa sinfo->sinfo_timetolive
+field into a total number of bytes allowed on the outbound
+send queue.
+If that number or more bytes are in queue, then
+other buffer-based sends are looked to be removed and
+skipped.
+Note that this policy may also result in the data
+never being sent if no buffer based sends are in queue and
+the maximum specified by
+.Fa timetolive
+bytes is in queue.
+.Pp
+The
+.Dv SCTP_PR_SCTP_RTX
+policy transforms the
+.Fa sinfo->sinfo_timetolive
+into a number of retransmissions to allow.
+This policy
+always assures that at a minimum one send attempt is
+made of the data.
+After which no more than
+.Fa sinfo->sinfo_timetolive
+retransmissions will be made before the data is skipped.
+.Pp
+.Fa sinfo->sinfo_stream
+is the SCTP stream that you wish to send the
+message on.
+Streams in SCTP are reliable (or partially reliable) flows of ordered
+messages.
+.Pp
+The
+.Fa sinfo->sinfo_assoc_id
+field is used to
+select the association to send to on a one-to-many socket.
+For a one-to-one socket, this field is ignored.
+.Pp
+The
+.Fa sinfo->sinfo_context
+field is used only in the event the message cannot be sent.
+This is an opaque
+value that the stack retains and will give to the user when a failed send
+is given if that notification is enabled (see
+.Xr sctp 4 ) .
+Normally a user process can use this value to index some application
+specific data structure when a send cannot be fulfilled.
+.Pp
+The
+.Fa flags
+argument holds the same meaning and values as those found in
+.Xr sendmsg 2
+but is generally ignored by SCTP.
+.Pp
+The fields
+.Fa sinfo->sinfo_ssn ,
+.Fa sinfo->sinfo_tsn ,
+and
+.Fa sinfo->sinfo_cumtsn
+are used only when receiving messages and are thus ignored by
+.Fn sctp_send .
+The function
+.Fn sctp_sendx
+has the same properties as
+.Fn sctp_send
+with the additional arguments of an array of sockaddr structures
+passed in.
+With the
+.Fa addrs
+argument being given as an array of addresses to be sent to and
+the
+.Fa addrcnt
+argument indicating how many socket addresses are in the passed
+in array.
+Note that all of the addresses will only be used
+when an implicit association is being set up.
+This allows the
+user the equivalent behavior as doing a
+.Fn sctp_connectx
+followed by a
+.Fn sctp_send
+to the association.
+Note that if the
+.Fa sinfo->sinfo_assoc_id
+field is 0, then the first address will be used to look up
+the association in place of the association id.
+If both
+an address and an association id are specified, the association
+id has priority.
+.Sh RETURN VALUES
+The call returns the number of characters sent, or -1
+if an error occurred.
+.Sh ERRORS
+The
+.Fn sctp_send
+system call
+fails if:
+.Bl -tag -width Er
+.It Bq Er EBADF
+An invalid descriptor was specified.
+.It Bq Er ENOTSOCK
+The argument
+.Fa s
+is not a socket.
+.It Bq Er EFAULT
+An invalid user space address was specified for an argument.
+.It Bq Er EMSGSIZE
+The socket requires that message be sent atomically,
+and the size of the message to be sent made this impossible.
+.It Bq Er EAGAIN
+The socket is marked non-blocking and the requested operation
+would block.
+.It Bq Er ENOBUFS
+The system was unable to allocate an internal buffer.
+The operation may succeed when buffers become available.
+.It Bq Er ENOBUFS
+The output queue for a network interface was full.
+This generally indicates that the interface has stopped sending,
+but may be caused by transient congestion.
+.It Bq Er EHOSTUNREACH
+The remote host was unreachable.
+.It Bq Er ENOTCONN
+On a one-to-one style socket no association exists.
+.It Bq Er ECONNRESET
+An abort was received by the stack while the user was
+attempting to send data to the peer.
+.It Bq Er ENOENT
+On a one-to-many style socket no address is specified
+so that the association cannot be located or the
+SCTP_ABORT flag was specified on a non-existing association.
+.It Bq Er EPIPE
+The socket is unable to send anymore data
+.Dv ( SBS_CANTSENDMORE
+has been set on the socket).
+This typically means that the socket
+is not connected and is a one-to-one style socket.
+.El
+.Sh SEE ALSO
+.Xr getsockopt 2 ,
+.Xr recv 2 ,
+.Xr select 2 ,
+.Xr sendmsg 2 ,
+.Xr socket 2 ,
+.Xr write 2
+.Xr sctp_connectx 3 ,
+.Xr sctp_recvmsg 3 ,
+.Xr sctp_sendmsg 3 ,
+.Xr sctp 4
+.Rs
+.%R RFC
+.%N 6458
+.%T "Sockets API Extensions for the Stream Control Transmission Protocol (SCTP)"
+.%D December 2011
+.Re 
+.Sh HISTORY
+These functions first appeared in
+.Nx 9.0 .
+.Sh BUGS
+Because
+.Fn sctp_send
+may have multiple associations under one endpoint, a
+select on write will only work for a one-to-one style
+socket.
Index: src/lib/libc/net/sctp_sendmsg.3
diff -u /dev/null src/lib/libc/net/sctp_sendmsg.3:1.1
--- /dev/null	Thu Aug  2 08:40:48 2018
+++ src/lib/libc/net/sctp_sendmsg.3	Thu Aug  2 08:40:48 2018
@@ -0,0 +1,339 @@
+.\"	$NetBSD: sctp_sendmsg.3,v 1.1 2018/08/02 08:40:48 rjs Exp $
+.\"
+.\" Copyright (c) 1983, 1991, 1993
+.\"	The Regents of the University of California.  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 University 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 REGENTS 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 REGENTS 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.
+.\"
+.\"     From: @(#)send.2	8.2 (Berkeley) 2/21/94
+.\"
+.Dd August 1, 2018
+.Dt SCTP_SENDMSG 3
+.Os
+.Sh NAME
+.Nm sctp_sendmsg ,
+.Nm sctp_sendmsgx
+.Nd send a message from an SCTP socket
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/socket.h
+.In netinet/sctp.h
+.Ft ssize_t
+.Fo sctp_sendmsg
+.Fa "int s" "const void *msg" "size_t len" "const struct sockaddr *to"
+.Fa "socklen_t tolen" "uint32_t ppid" "uint32_t flags" "uint16_t stream_no"
+.Fa "uint32_t timetolive" "uint32_t context"
+.Fc
+.Ft ssize_t
+.Fo sctp_sendmsgx
+.Fa "int s" "const void *msg" "size_t len" "const struct sockaddr *to"
+.Fa "int addrcnt" "uint32_t ppid" "uint32_t flags" "uint16_t stream_no"
+.Fa "uint32_t timetolive" "uint32_t context"
+.Fc
+.Sh DESCRIPTION
+The
+.Fn sctp_sendmsg
+system call
+is used to transmit a message to another SCTP endpoint.
+The
+.Fn sctp_sendmsg
+may be used at any time.
+If the socket is a one-to-many type (SOCK_SEQPACKET)
+socket then an attempt to send to an address that no association exists to will
+implicitly create a new association.
+Data sent in such an instance will result in
+the data being sent on the third leg of the SCTP four-way handshake.
+Note that if
+the socket is a one-to-one type (SOCK_STREAM) socket then an association must
+be in existence (by use of the
+.Xr connect 2
+system call).
+Calling
+.Fn sctp_sendmsg
+or
+.Fn sctp_sendmsgx
+on a non-connected one-to-one socket will result in
+.Va errno
+being set to
+.Er ENOTCONN ,
+-1 being returned, and the message not being transmitted.
+.Pp
+The address of the target is given by
+.Fa to
+with
+.Fa tolen
+specifying its size.
+The length of the message
+.Fa msg
+is given by
+.Fa len .
+If the message is too long to pass atomically through the
+underlying protocol,
+.Va errno
+is set to
+.Er EMSGSIZE ,
+-1 is returned, and
+the message is not transmitted.
+.Pp
+No indication of failure to deliver is implicit in a
+.Xr sctp_sendmsg 3
+call.
+Locally detected errors are indicated by a return value of -1.
+.Pp
+If no space is available at the socket to hold
+the message to be transmitted, then
+.Xr sctp_sendmsg 3
+normally blocks, unless the socket has been placed in
+non-blocking I/O mode.
+The
+.Xr select 2
+system call may be used to determine when it is possible to
+send more data on one-to-one type (SOCK_STREAM) sockets.
+.Pp
+The
+.Fa ppid
+argument is an opaque 32 bit value that is passed transparently
+through the stack to the peer endpoint.
+It will be available on
+reception of a message (see
+.Xr sctp_recvmsg 3 ) .
+Note that the stack passes this value without regard to byte
+order.
+.Pp
+The
+.Fa flags
+argument may include one or more of the following:
+.Bd -literal
+#define SCTP_EOF 	  0x0100	/* Start a shutdown procedures */
+#define SCTP_ABORT	  0x0200	/* Send an ABORT to peer */
+#define SCTP_UNORDERED 	  0x0400	/* Message is un-ordered */
+#define SCTP_ADDR_OVER	  0x0800	/* Override the primary-address */
+#define SCTP_SENDALL      0x1000	/* Send this on all associations */
+					/* for the endpoint */
+/* The lower byte is an enumeration of PR-SCTP policies */
+#define SCTP_PR_SCTP_TTL  0x0001	/* Time based PR-SCTP */
+#define SCTP_PR_SCTP_BUF  0x0002	/* Buffer based PR-SCTP */
+#define SCTP_PR_SCTP_RTX  0x0003	/* Number of retransmissions based PR-SCTP */
+.Ed
+.Pp
+The flag
+.Dv SCTP_EOF
+is used to instruct the SCTP stack to queue this message
+and then start a graceful shutdown of the association.
+All
+remaining data in queue will be sent after which the association
+will be shut down.
+.Pp
+.Dv SCTP_ABORT
+is used to immediately terminate an association.
+An abort
+is sent to the peer and the local TCB is destroyed.
+.Pp
+.Dv SCTP_UNORDERED
+is used to specify that the message being sent has no
+specific order and should be delivered to the peer application
+as soon as possible.
+When this flag is absent messages
+are delivered in order within the stream they are sent, but without
+respect to order to peer streams.
+.Pp
+The flag
+.Dv SCTP_ADDR_OVER
+is used to specify that an specific address should be used.
+Normally
+SCTP will use only one of a multi-homed peers addresses as the primary
+address to send to.
+By default, no matter what the
+.Fa to
+argument is, this primary address is used to send data.
+By specifying
+this flag, the user is asking the stack to ignore the primary address
+and instead use the specified address not only as a lookup mechanism
+to find the association but also as the actual address to send to.
+.Pp
+For a one-to-many type (SOCK_SEQPACKET) socket the flag
+.Dv SCTP_SENDALL
+can be used as a convenient way to make one send call and have
+all associations that are under the socket get a copy of the message.
+Note that this mechanism is quite efficient and makes only one actual
+copy of the data which is shared by all the associations for sending.
+.Pp
+The remaining flags are used for the partial reliability extension (RFC3758)
+and will only be effective if the peer endpoint supports this extension.
+This option specifies what local policy the local endpoint should use
+in skipping data.
+If none of these options are set, then data is
+never skipped over.
+.Pp
+.Dv SCTP_PR_SCTP_TTL
+is used to indicate that a time based lifetime is being applied
+to the data.
+The
+.Fa timetolive
+argument is then a number of milliseconds for which the data is
+attempted to be transmitted.
+If that many milliseconds elapse
+and the peer has not acknowledged the data, the data will be
+skipped and no longer transmitted.
+Note that this policy does
+not even assure that the data will ever be sent.
+In times of a congestion
+with large amounts of data being queued, the
+.Fa timetolive
+may expire before the first transmission is ever made.
+.Pp
+The
+.Dv SCTP_PR_SCTP_BUF
+based policy transforms the
+.Fa timetolive
+field into a total number of bytes allowed on the outbound
+send queue.
+If that number or more bytes are in queue, then
+other buffer based sends are looked to be removed and
+skipped.
+Note that this policy may also result in the data
+never being sent if no buffer based sends are in queue and
+the maximum specified by
+.Fa timetolive
+bytes is in queue.
+.Pp
+The
+.Dv SCTP_PR_SCTP_RTX
+policy transforms the
+.Fa timetolive
+into a number of retransmissions to allow.
+This policy
+always assures that at a minimum one send attempt is
+made of the data.
+After which no more than
+.Fa timetolive
+retransmissions will be made before the data is skipped.
+.Pp
+.Fa stream_no
+is the SCTP stream that you wish to send the
+message on.
+Streams in SCTP are reliable (or partially reliable) flows of ordered
+messages.
+The
+.Fa context
+field is used only in the event the message cannot be sent.
+This is an opaque
+value that the stack retains and will give to the user when a failed send
+is given if that notification is enabled (see
+.Xr sctp 4 ) .
+Normally a user process can use this value to index some application
+specific data structure when a send cannot be fulfilled.
+.Fn sctp_sendmsgx
+is identical to
+.Fn sctp_sendmsg
+with the exception that it takes an array of sockaddr structures in the
+argument
+.Fa to
+and adds the additional argument
+.Fa addrcnt
+which specifies how many addresses are in the array.
+This allows a
+caller to implicitly set up an association passing multiple addresses
+as if
+.Fn sctp_connectx
+had been called to set up the association.
+.Sh RETURN VALUES
+The call returns the number of characters sent, or -1
+if an error occurred.
+.Sh ERRORS
+The
+.Fn sctp_sendmsg
+system call
+fails if:
+.Bl -tag -width Er
+.It Bq Er EBADF
+An invalid descriptor was specified.
+.It Bq Er ENOTSOCK
+The argument
+.Fa s
+is not a socket.
+.It Bq Er EFAULT
+An invalid user space address was specified for an argument.
+.It Bq Er EMSGSIZE
+The socket requires that message be sent atomically,
+and the size of the message to be sent made this impossible.
+.It Bq Er EAGAIN
+The socket is marked non-blocking and the requested operation
+would block.
+.It Bq Er ENOBUFS
+The system was unable to allocate an internal buffer.
+The operation may succeed when buffers become available.
+.It Bq Er ENOBUFS
+The output queue for a network interface was full.
+This generally indicates that the interface has stopped sending,
+but may be caused by transient congestion.
+.It Bq Er EHOSTUNREACH
+The remote host was unreachable.
+.It Bq Er ENOTCONN
+On a one-to-one style socket no association exists.
+.It Bq Er ECONNRESET
+An abort was received by the stack while the user was
+attempting to send data to the peer.
+.It Bq Er ENOENT
+On a one-to-many style socket no address is specified
+so that the association cannot be located or the
+.Dv SCTP_ABORT
+flag was specified on a non-existing association.
+.It Bq Er EPIPE
+The socket is unable to send anymore data
+.Dv ( SBS_CANTSENDMORE
+has been set on the socket).
+This typically means that the socket
+is not connected and is a one-to-one style socket.
+.El
+.Sh SEE ALSO
+.Xr connect 2 ,
+.Xr getsockopt 2 ,
+.Xr recv 2 ,
+.Xr select 2 ,
+.Xr socket 2 ,
+.Xr write 2 ,
+.Xr sctp_connectx 3 ,
+.Xr sendmsg 2 ,
+.Xr sctp 4
+.Rs
+.%R RFC
+.%N 6458
+.%T "Sockets API Extensions for the Stream Control Transmission Protocol (SCTP)"
+.%D December 2011
+.Re 
+.Sh HISTORY
+These functions first appeared in
+.Nx 9.0 .
+.Sh BUGS
+Because in the one-to-many style socket
+.Fn sctp_sendmsg
+or
+.Fn sctp_sendmsgx
+may have multiple associations under one endpoint, a
+select on write will only work for a one-to-one style
+socket.
Index: src/lib/libc/net/sctp_sys_calls.c
diff -u /dev/null src/lib/libc/net/sctp_sys_calls.c:1.1
--- /dev/null	Thu Aug  2 08:40:48 2018
+++ src/lib/libc/net/sctp_sys_calls.c	Thu Aug  2 08:40:48 2018
@@ -0,0 +1,963 @@
+/*	$KAME: sctp_sys_calls.c,v 1.10 2005/03/06 16:04:16 itojun Exp $ */
+/*	$NetBSD: sctp_sys_calls.c,v 1.1 2018/08/02 08:40:48 rjs Exp $ */
+
+/*
+ * Copyright (C) 2002, 2003, 2004 Cisco Systems Inc,
+ * 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 <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/errno.h>
+#include <sys/syscall.h>
+#include <sys/ioctl.h>
+#include <sys/uio.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netinet/sctp_uio.h>
+#include <netinet/sctp.h>
+
+#include <net/if_dl.h>
+
+#ifndef IN6_IS_ADDR_V4MAPPED
+#define IN6_IS_ADDR_V4MAPPED(a)		     \
+	((*(const u_int32_t *)(const void *)(&(a)->s6_addr[0]) == 0) &&	\
+	 (*(const u_int32_t *)(const void *)(&(a)->s6_addr[4]) == 0) &&	\
+	 (*(const u_int32_t *)(const void *)(&(a)->s6_addr[8]) == ntohl(0x0000ffff)))
+#endif
+
+#define SCTP_CONTROL_VEC_SIZE_RCV	16384
+
+#ifdef SCTP_DEBUG_PRINT_ADDRESS
+static void
+SCTPPrintAnAddress(struct sockaddr *a)
+{
+	char stringToPrint[256];
+	u_short prt;
+	char *srcaddr, *txt;
+
+	if (a == NULL) {
+		printf("NULL\n");
+		return;
+	}
+	if (a->sa_family == AF_INET) {
+		srcaddr = (char *)&((struct sockaddr_in *)a)->sin_addr;
+		txt = "IPv4 Address: ";
+		prt = ntohs(((struct sockaddr_in *)a)->sin_port);
+	} else if (a->sa_family == AF_INET6) {
+		srcaddr = (char *)&((struct sockaddr_in6 *)a)->sin6_addr;
+		prt = ntohs(((struct sockaddr_in6 *)a)->sin6_port);
+		txt = "IPv6 Address: ";
+	} else if (a->sa_family == AF_LINK) {
+		int i;
+		char tbuf[200];
+		u_char adbuf[200];
+		struct sockaddr_dl *dl;
+
+		dl = (struct sockaddr_dl *)a;
+		strncpy(tbuf, dl->sdl_data, dl->sdl_nlen);
+		tbuf[dl->sdl_nlen] = 0;
+		printf("Intf:%s (len:%d)Interface index:%d type:%x(%d) ll-len:%d ",
+		    tbuf, dl->sdl_nlen, dl->sdl_index, dl->sdl_type,
+		    dl->sdl_type, dl->sdl_alen);
+		memcpy(adbuf, LLADDR(dl), dl->sdl_alen);
+		for (i = 0; i < dl->sdl_alen; i++){
+			printf("%2.2x", adbuf[i]);
+			if (i < (dl->sdl_alen - 1))
+				printf(":");
+		}
+		printf("\n");
+	/*	u_short	sdl_route[16];*/	/* source routing information */
+		return;
+	} else {
+		return;
+	}
+	if (inet_ntop(a->sa_family, srcaddr, stringToPrint,
+	    sizeof(stringToPrint))) {
+		if (a->sa_family == AF_INET6) {
+			printf("%s%s:%d scope:%d\n", txt, stringToPrint, prt,
+			    ((struct sockaddr_in6 *)a)->sin6_scope_id);
+		} else {
+			printf("%s%s:%d\n", txt, stringToPrint, prt);
+		}
+
+	} else {
+		printf("%s unprintable?\n", txt);
+	}
+}
+#endif /* SCTP_DEBUG_PRINT_ADDRESS */
+
+void
+in6_sin6_2_sin(struct sockaddr_in *sin, struct sockaddr_in6 *sin6)
+{
+	memset(sin, 0, sizeof(*sin));
+	sin->sin_len = sizeof(struct sockaddr_in);
+	sin->sin_family = AF_INET;
+	sin->sin_port = sin6->sin6_port;
+	sin->sin_addr.s_addr = sin6->sin6_addr.__u6_addr.__u6_addr32[3];
+}
+
+int
+sctp_connectx(int sd, struct sockaddr *addrs, int addrcnt,
+		sctp_assoc_t *id)
+{
+	int i, ret, cnt;
+	struct sockaddr *at;
+	struct sctp_connectx_addrs sca;
+#if 0
+	char *cpto;
+#endif
+	size_t len;
+	
+	at = addrs;
+	cnt = 0;
+	len = 0;
+	/* validate all the addresses and get the size */
+	for (i = 0; i < addrcnt; i++) {
+		if (at->sa_family == AF_INET) {
+			len += at->sa_len;
+		} else if (at->sa_family == AF_INET6){
+			if (IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)at)->sin6_addr)){
+				len += sizeof(struct sockaddr_in);
+#if 0
+				in6_sin6_2_sin((struct sockaddr_in *)cpto,
+				    (struct sockaddr_in6 *)at);
+				cpto = ((caddr_t)cpto + sizeof(struct sockaddr_in));
+				len += sizeof(struct sockaddr_in);
+#endif
+			} else {
+				len += at->sa_len;
+			}
+		} else {
+			errno = EINVAL;
+			return (-1);
+		}
+		at = (struct sockaddr *)((caddr_t)at + at->sa_len);
+		cnt++;
+        }
+	/* do we have any? */
+	if (cnt == 0) {
+		errno = EINVAL;
+		return(-1);
+	}
+
+	sca.cx_num = cnt;
+	sca.cx_len = len;
+	sca.cx_addrs = addrs;
+	ret = ioctl(sd, SIOCCONNECTX, (void *)&sca);
+	if ((ret == 0) && (id != NULL)) {
+		memcpy(id, &sca.cx_num, sizeof(sctp_assoc_t));
+	}
+	return (ret);
+}
+
+int
+sctp_bindx(int sd, struct sockaddr *addrs, int addrcnt, int flags)
+{
+	struct sctp_getaddresses *gaddrs;
+	struct sockaddr *sa;
+	int i, sz, fam, argsz;
+
+	if ((flags != SCTP_BINDX_ADD_ADDR) && 
+	    (flags != SCTP_BINDX_REM_ADDR)) {
+		errno = EFAULT;
+		return(-1);
+	}
+	argsz = (sizeof(struct sockaddr_storage) +
+	    sizeof(struct sctp_getaddresses));
+	gaddrs = (struct sctp_getaddresses *)calloc(1, argsz);
+	if (gaddrs == NULL) {
+		errno = ENOMEM;
+		return(-1);
+	}
+	gaddrs->sget_assoc_id = 0;
+	sa = addrs;
+	for (i = 0; i < addrcnt; i++) {
+		sz = sa->sa_len;
+		fam = sa->sa_family;
+		((struct sockaddr_in *)&addrs[i])->sin_port = ((struct sockaddr_in *)sa)->sin_port;
+		if ((fam != AF_INET) && (fam != AF_INET6)) {
+			errno = EINVAL;
+			return(-1);
+		}
+		memcpy(gaddrs->addr, sa, sz);
+		if (setsockopt(sd, IPPROTO_SCTP, flags, gaddrs,
+		    (unsigned int)argsz) != 0) {
+			free(gaddrs);
+			return(-1);
+		}
+		memset(gaddrs, 0, argsz);
+		sa = (struct sockaddr *)((caddr_t)sa + sz);
+	}
+	free(gaddrs);
+	return(0);
+}
+
+
+int
+sctp_opt_info(int sd, sctp_assoc_t id, int opt, void *arg, socklen_t *size)
+{
+	if ((opt == SCTP_RTOINFO) || 
+ 	    (opt == SCTP_ASSOCINFO) || 
+	    (opt == SCTP_PRIMARY_ADDR) || 
+	    (opt == SCTP_SET_PEER_PRIMARY_ADDR) || 
+	    (opt == SCTP_PEER_ADDR_PARAMS) || 
+	    (opt == SCTP_STATUS) || 
+	    (opt == SCTP_GET_PEER_ADDR_INFO)) { 
+		*(sctp_assoc_t *)arg = id;
+		return(getsockopt2(sd, IPPROTO_SCTP, opt, arg, size));
+	} else {
+		errno = EOPNOTSUPP;
+		return(-1);
+	}
+}
+
+int
+sctp_getpaddrs(int sd, sctp_assoc_t id, struct sockaddr **raddrs)
+{
+	struct sctp_getaddresses *addrs;
+	struct sockaddr *sa;
+	struct sockaddr *re;
+	sctp_assoc_t asoc;
+	caddr_t lim;
+	unsigned int siz;
+	int cnt;
+
+	if (raddrs == NULL) {
+		errno = EFAULT;
+		return(-1);
+	}
+	asoc = id;
+	siz = sizeof(sctp_assoc_t);  
+	if (getsockopt2(sd, IPPROTO_SCTP, SCTP_GET_REMOTE_ADDR_SIZE,
+	    &asoc, &siz) != 0) {
+		return(-1);
+	}
+	siz = (unsigned int)asoc;
+	siz += sizeof(struct sctp_getaddresses);
+	addrs = calloc((unsigned long)1, (unsigned long)siz);
+	if (addrs == NULL) {
+		errno = ENOMEM;
+		return(-1);
+	}
+	memset(addrs, 0, (size_t)siz);
+	addrs->sget_assoc_id = id;
+	/* Now lets get the array of addresses */
+	if (getsockopt2(sd, IPPROTO_SCTP, SCTP_GET_PEER_ADDRESSES,
+	    addrs, &siz) != 0) {
+		free(addrs);
+		return(-1);
+	}
+	re = (struct sockaddr *)&addrs->addr[0];
+	*raddrs = re;
+	cnt = 0;
+	sa = (struct sockaddr *)&addrs->addr[0];
+	lim = (caddr_t)addrs + siz;
+	while ((caddr_t)sa < lim) {
+		cnt++;
+		sa = (struct sockaddr *)((caddr_t)sa + sa->sa_len);
+		if (sa->sa_len == 0)
+			break;
+	}
+	return(cnt);
+}
+
+void sctp_freepaddrs(struct sockaddr *addrs)
+{
+	/* Take away the hidden association id */
+	void *fr_addr;
+	fr_addr = (void *)((caddr_t)addrs - sizeof(sctp_assoc_t));
+	/* Now free it */
+	free(fr_addr);
+}
+
+int
+sctp_getladdrs (int sd, sctp_assoc_t id, struct sockaddr **raddrs)
+{
+	struct sctp_getaddresses *addrs;
+	struct sockaddr *re;
+	caddr_t lim;
+	struct sockaddr *sa;
+	int size_of_addresses;
+	unsigned int siz;
+	int cnt;
+
+	if (raddrs == NULL) {
+		errno = EFAULT;
+		return(-1);
+	}
+	size_of_addresses = 0;
+	siz = sizeof(int);  
+	if (getsockopt2(sd, IPPROTO_SCTP, SCTP_GET_LOCAL_ADDR_SIZE,
+	    &size_of_addresses, &siz) != 0) {
+		return(-1);
+	}
+	if (size_of_addresses == 0) {
+		errno = ENOTCONN;
+		return(-1);
+	}
+	siz = size_of_addresses + sizeof(struct sockaddr_storage);
+	siz += sizeof(struct sctp_getaddresses);
+	addrs = calloc((unsigned long)1, (unsigned long)siz);
+	if (addrs == NULL) {
+		errno = ENOMEM;
+		return(-1);
+	}
+	memset(addrs, 0, (size_t)siz);
+	addrs->sget_assoc_id = id;
+	/* Now lets get the array of addresses */
+	if (getsockopt2(sd, IPPROTO_SCTP, SCTP_GET_LOCAL_ADDRESSES, addrs,
+	    &siz) != 0) {
+		free(addrs);
+		return(-1);
+	}
+	re = (struct sockaddr *)&addrs->addr[0];
+	*raddrs = re;
+	cnt = 0;
+	sa = (struct sockaddr *)&addrs->addr[0];
+	lim = (caddr_t)addrs + siz;
+	while ((caddr_t)sa < lim) {
+		cnt++;
+		sa = (struct sockaddr *)((caddr_t)sa + sa->sa_len);
+		if (sa->sa_len == 0)
+			break;
+	}
+	return(cnt);
+}
+
+void sctp_freeladdrs(struct sockaddr *addrs)
+{
+	/* Take away the hidden association id */
+	void *fr_addr;
+	fr_addr = (void *)((caddr_t)addrs - sizeof(sctp_assoc_t));
+	/* Now free it */
+	free(fr_addr);
+}
+
+ssize_t
+sctp_sendmsg(int s, 
+	     const void *data, 
+	     size_t len,
+	     const struct sockaddr *to,
+	     socklen_t tolen __attribute__((unused)),
+	     u_int32_t ppid,
+	     u_int32_t flags,
+	     u_int16_t stream_no,
+	     u_int32_t timetolive,
+	     u_int32_t context)
+{
+	int sz;
+	struct msghdr msg;
+	struct iovec iov[2];
+	char controlVector[256];
+	struct sctp_sndrcvinfo *s_info;
+	struct cmsghdr *cmsg;
+	struct sockaddr *who=NULL;
+	union {
+		struct sockaddr_in in;
+		struct sockaddr_in6 in6;
+	} addr;
+
+#if 0
+	fprintf(io, "sctp_sendmsg(sd:%d, data:%x, len:%d, to:%x, tolen:%d, ppid:%x, flags:%x str:%d ttl:%d ctx:%x\n",
+	    s, (u_int)data, (int)len, (u_int)to, (int)tolen, ppid, flags,
+	    (int)stream_no, (int)timetolive, (u_int)context);
+	fflush(io);
+#endif
+	if (to) {
+		if (to->sa_len == 0) {
+			/*
+			 * For the lazy app, that did not
+			 * set sa_len, we attempt to set for them.
+			 */
+			switch (to->sa_family) {
+			case AF_INET:
+				memcpy(&addr, to, sizeof(struct sockaddr_in));
+				addr.in.sin_len = sizeof(struct sockaddr_in);
+				break;
+			case AF_INET6:
+				memcpy(&addr, to, sizeof(struct sockaddr_in6));
+				addr.in6.sin6_len = sizeof(struct sockaddr_in6);
+				break;
+			default:
+				errno = EAFNOSUPPORT;
+				return -1;
+			}
+		} else {
+			memcpy (&addr, to, to->sa_len);
+		}
+		who = (struct sockaddr *)&addr;
+	}
+	iov[0].iov_base = (void *)(unsigned long)data;
+	iov[0].iov_len = len;
+	iov[1].iov_base = NULL;
+	iov[1].iov_len = 0;
+
+	if (to) {
+		msg.msg_name = (caddr_t)who;
+		msg.msg_namelen = who->sa_len;
+	} else {
+		msg.msg_name = (caddr_t)NULL;
+		msg.msg_namelen = 0;
+	}
+	msg.msg_iov = iov;
+	msg.msg_iovlen = 1;
+	msg.msg_control = (caddr_t)controlVector;
+
+	cmsg = (struct cmsghdr *)controlVector;
+
+	cmsg->cmsg_level = IPPROTO_SCTP;
+	cmsg->cmsg_type = SCTP_SNDRCV;
+	cmsg->cmsg_len = CMSG_LEN (sizeof(struct sctp_sndrcvinfo) );
+	s_info = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg);
+
+	s_info->sinfo_stream = stream_no;
+	s_info->sinfo_ssn = 0;
+	s_info->sinfo_flags = flags;
+	s_info->sinfo_ppid = ppid;
+	s_info->sinfo_context = context;
+	s_info->sinfo_assoc_id = 0;
+	s_info->sinfo_timetolive = timetolive;
+	errno = 0;
+	msg.msg_controllen = cmsg->cmsg_len;
+	sz = sendmsg(s, &msg, 0);
+	return(sz);
+}
+
+sctp_assoc_t
+sctp_getassocid(int sd, struct sockaddr *sa)
+{
+	struct sctp_paddrparams sp;
+	socklen_t siz;
+
+	/* First get the assoc id */
+	siz = sizeof(struct sctp_paddrparams);
+	memset(&sp, 0, sizeof(sp));
+	memcpy((caddr_t)&sp.spp_address, sa, sa->sa_len);
+	errno = 0;
+	if (getsockopt2(sd, IPPROTO_SCTP, SCTP_PEER_ADDR_PARAMS, &sp, &siz) != 0)
+		return((sctp_assoc_t)0);
+	/* We depend on the fact that 0 can never be returned */
+	return(sp.spp_assoc_id);
+}
+
+
+
+ssize_t
+sctp_send(int sd, const void *data, size_t len,
+	  const struct sctp_sndrcvinfo *sinfo,
+	  int flags)
+{
+	int sz;
+	struct msghdr msg;
+	struct iovec iov[2];
+	struct sctp_sndrcvinfo *s_info;
+	char controlVector[256];
+	struct cmsghdr *cmsg;
+
+	iov[0].iov_base = (void *)(unsigned long)data;
+	iov[0].iov_len = len;
+	iov[1].iov_base = NULL;
+	iov[1].iov_len = 0;
+
+	msg.msg_name = 0;
+	msg.msg_namelen = 0;
+	msg.msg_iov = iov;
+	msg.msg_iovlen = 1;
+	msg.msg_control = (caddr_t)controlVector;
+  
+	cmsg = (struct cmsghdr *)controlVector;
+
+	cmsg->cmsg_level = IPPROTO_SCTP;
+	cmsg->cmsg_type = SCTP_SNDRCV;
+	cmsg->cmsg_len = CMSG_LEN (sizeof(struct sctp_sndrcvinfo) );
+	s_info = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg);
+	/* copy in the data */
+	*s_info = *sinfo;
+	errno = 0;
+	msg.msg_controllen = cmsg->cmsg_len;
+	sz = sendmsg(sd, &msg, flags);
+	return(sz);
+}
+
+
+ssize_t
+sctp_sendx(int sd, const void *msg, size_t len, 
+	   struct sockaddr *addrs, int addrcnt,
+	   struct sctp_sndrcvinfo *sinfo,
+	   int flags)
+{
+	int i, ret, cnt, saved_errno;
+	int add_len;
+	struct sockaddr *at;
+	struct sctp_connectx_addrs sca;
+
+	len = 0;
+	at = addrs;
+	cnt = 0;
+	/* validate all the addresses and get the size */
+	for (i = 0; i < addrcnt; i++) {
+		if (at->sa_family == AF_INET) {
+			add_len = sizeof(struct sockaddr_in);
+		} else if (at->sa_family == AF_INET6) {
+			add_len = sizeof(struct sockaddr_in6);
+		} else {
+			errno = EINVAL;
+			return (-1);
+		}
+		len += add_len;
+		at = (struct sockaddr *)((caddr_t)at + add_len);
+		cnt++;
+	}
+	/* do we have any? */
+	if (cnt == 0) {
+		errno = EINVAL;
+		return(-1);
+	}
+
+	sca.cx_num = cnt;
+	sca.cx_len = len;
+	sca.cx_addrs = addrs;
+	ret = ioctl(sd, SIOCCONNECTXDEL, (void *)&sca);
+	if (ret != 0) {
+		return(ret);
+	}
+	sinfo->sinfo_assoc_id = sctp_getassocid(sd, addrs);
+	if (sinfo->sinfo_assoc_id == 0) {
+		printf("Huh, can't get associd? TSNH!\n");
+		(void)setsockopt(sd, IPPROTO_SCTP, SCTP_CONNECT_X_COMPLETE, (void *)addrs,
+				 (unsigned int)addrs->sa_len);
+		errno = ENOENT;
+		return (-1);
+	}
+	ret = sctp_send(sd, msg, len, sinfo, flags);
+	saved_errno = errno;
+	(void)setsockopt(sd, IPPROTO_SCTP, SCTP_CONNECT_X_COMPLETE, (void *)addrs,
+			 (unsigned int)addrs->sa_len);
+
+	errno = saved_errno;
+	return (ret);
+}
+
+ssize_t
+sctp_sendmsgx(int sd, 
+	      const void *msg, 
+	      size_t len,
+	      struct sockaddr *addrs,
+	      int addrcnt,
+	      u_int32_t ppid,
+	      u_int32_t flags,
+	      u_int16_t stream_no,
+	      u_int32_t timetolive,
+	      u_int32_t context)
+{
+	struct sctp_sndrcvinfo sinfo;
+    
+	memset((void *) &sinfo, 0, sizeof(struct sctp_sndrcvinfo));
+	sinfo.sinfo_ppid       = ppid;
+	sinfo.sinfo_flags      = flags;
+	sinfo.sinfo_ssn        = stream_no;
+	sinfo.sinfo_timetolive = timetolive;
+	sinfo.sinfo_context    = context;
+	return sctp_sendx(sd, msg, len, addrs, addrcnt, &sinfo, 0);
+}
+
+ssize_t
+sctp_recvmsg (int s, 
+	      void *dbuf, 
+	      size_t len,
+	      struct sockaddr *from,
+	      socklen_t *fromlen,
+	      struct sctp_sndrcvinfo *sinfo,
+	      int *msg_flags)
+{
+	struct sctp_sndrcvinfo *s_info;
+	ssize_t sz;
+	struct msghdr msg;
+	struct iovec iov[2];
+	char controlVector[2048];
+	struct cmsghdr *cmsg;
+	iov[0].iov_base = dbuf;
+	iov[0].iov_len = len;
+	iov[1].iov_base = NULL;
+	iov[1].iov_len = 0;
+	msg.msg_name = (caddr_t)from;
+	msg.msg_namelen = *fromlen;
+	msg.msg_iov = iov;
+	msg.msg_iovlen = 1;
+	msg.msg_control = (caddr_t)controlVector;
+	msg.msg_controllen = sizeof(controlVector);
+	errno = 0;
+	sz = recvmsg(s, &msg, 0);
+
+	s_info = NULL;
+	len = sz;
+	*msg_flags = msg.msg_flags;
+	*fromlen = msg.msg_namelen;
+	if ((msg.msg_controllen) && sinfo) {
+		/* parse through and see if we find
+		 * the sctp_sndrcvinfo (if the user wants it).
+		 */
+		cmsg = (struct cmsghdr *)controlVector;
+		while (cmsg) {
+			if (cmsg->cmsg_level == IPPROTO_SCTP) {
+				if (cmsg->cmsg_type == SCTP_SNDRCV) {
+					/* Got it */
+					s_info = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg);
+					/* Copy it to the user */
+					*sinfo = *s_info;
+					break;
+				}
+			}
+			cmsg = CMSG_NXTHDR(&msg, cmsg);
+		}
+	}
+	return(sz);
+}
+
+ssize_t 
+sctp_recvv(int sd,
+    const struct iovec *iov,
+    int iovlen,
+    struct sockaddr *from,
+    socklen_t * fromlen,
+    void *info,
+    socklen_t * infolen,
+    unsigned int *infotype,
+    int *flags)
+{
+	char cmsgbuf[SCTP_CONTROL_VEC_SIZE_RCV];
+	struct msghdr msg;
+	struct cmsghdr *cmsg;
+	ssize_t ret;
+	struct sctp_rcvinfo *rcvinfo;
+	struct sctp_nxtinfo *nxtinfo;
+
+	if (((info != NULL) && (infolen == NULL)) ||
+	    ((info == NULL) && (infolen != NULL) && (*infolen != 0)) ||
+	    ((info != NULL) && (infotype == NULL))) {
+		errno = EINVAL;
+		return (-1);
+	}
+	if (infotype) {
+		*infotype = SCTP_RECVV_NOINFO;
+	}
+	msg.msg_name = from;
+	if (fromlen == NULL) {
+		msg.msg_namelen = 0;
+	} else {
+		msg.msg_namelen = *fromlen;
+	}
+	msg.msg_iov = __UNCONST(iov);
+	msg.msg_iovlen = iovlen;
+	msg.msg_control = cmsgbuf;
+	msg.msg_controllen = sizeof(cmsgbuf);
+	msg.msg_flags = 0;
+	ret = recvmsg(sd, &msg, *flags);
+	*flags = msg.msg_flags;
+	if ((ret > 0) &&
+	    (msg.msg_controllen > 0) &&
+	    (infotype != NULL) &&
+	    (infolen != NULL) &&
+	    (*infolen > 0)) {
+		rcvinfo = NULL;
+		nxtinfo = NULL;
+		for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
+			if (cmsg->cmsg_level != IPPROTO_SCTP) {
+				continue;
+			}
+			if (cmsg->cmsg_type == SCTP_RCVINFO) {
+				rcvinfo = (struct sctp_rcvinfo *)CMSG_DATA(cmsg);
+				if (nxtinfo != NULL) {
+					break;
+				} else {
+					continue;
+				}
+			}
+			if (cmsg->cmsg_type == SCTP_NXTINFO) {
+				nxtinfo = (struct sctp_nxtinfo *)CMSG_DATA(cmsg);
+				if (rcvinfo != NULL) {
+					break;
+				} else {
+					continue;
+				}
+			}
+		}
+		if (rcvinfo != NULL) {
+			if ((nxtinfo != NULL) && (*infolen >= sizeof(struct sctp_recvv_rn))) {
+				struct sctp_recvv_rn *rn_info;
+
+				rn_info = (struct sctp_recvv_rn *)info;
+				rn_info->recvv_rcvinfo = *rcvinfo;
+				rn_info->recvv_nxtinfo = *nxtinfo;
+				*infolen = (socklen_t) sizeof(struct sctp_recvv_rn);
+				*infotype = SCTP_RECVV_RN;
+			} else if (*infolen >= sizeof(struct sctp_rcvinfo)) {
+				memcpy(info, rcvinfo, sizeof(struct sctp_rcvinfo));
+				*infolen = (socklen_t) sizeof(struct sctp_rcvinfo);
+				*infotype = SCTP_RECVV_RCVINFO;
+			}
+		} else if (nxtinfo != NULL) {
+			if (*infolen >= sizeof(struct sctp_nxtinfo)) {
+				memcpy(info, nxtinfo, sizeof(struct sctp_nxtinfo));
+				*infolen = (socklen_t) sizeof(struct sctp_nxtinfo);
+				*infotype = SCTP_RECVV_NXTINFO;
+			}
+		}
+	}
+	return (ret);
+}
+
+ssize_t
+sctp_sendv(int sd,
+    const struct iovec *iov, int iovcnt,
+    struct sockaddr *addrs, int addrcnt,
+    void *info, socklen_t infolen, unsigned int infotype,
+    int flags)
+{
+	ssize_t ret;
+	int i;
+	socklen_t addr_len;
+	struct msghdr msg;
+	in_port_t port;
+	struct sctp_sendv_spa *spa_info;
+	struct cmsghdr *cmsg;
+	char *cmsgbuf;
+	struct sockaddr *addr;
+	struct sockaddr_in *addr_in;
+	struct sockaddr_in6 *addr_in6;
+	void *assoc_id_ptr;
+	sctp_assoc_t assoc_id;
+
+	if ((addrcnt < 0) ||
+	    (iovcnt < 0) ||
+	    ((addrs == NULL) && (addrcnt > 0)) ||
+	    ((addrs != NULL) && (addrcnt == 0)) ||
+	    ((iov == NULL) && (iovcnt > 0)) ||
+	    ((iov != NULL) && (iovcnt == 0))) {
+		errno = EINVAL;
+		return (-1);
+	}
+	cmsgbuf = malloc(CMSG_SPACE(sizeof(struct sctp_sndinfo)) +
+	    CMSG_SPACE(sizeof(struct sctp_prinfo)) +
+	    CMSG_SPACE(sizeof(struct sctp_authinfo)) +
+	    (size_t)addrcnt * CMSG_SPACE(sizeof(struct in6_addr)));
+	if (cmsgbuf == NULL) {
+		errno = ENOMEM;
+		return (-1);
+	}
+	assoc_id_ptr = NULL;
+	msg.msg_control = cmsgbuf;
+	msg.msg_controllen = 0;
+	cmsg = (struct cmsghdr *)cmsgbuf;
+	switch (infotype) {
+	case SCTP_SENDV_NOINFO:
+		if ((infolen != 0) || (info != NULL)) {
+			free(cmsgbuf);
+			errno = EINVAL;
+			return (-1);
+		}
+		break;
+	case SCTP_SENDV_SNDINFO:
+		if ((info == NULL) || (infolen < sizeof(struct sctp_sndinfo))) {
+			free(cmsgbuf);
+			errno = EINVAL;
+			return (-1);
+		}
+		cmsg->cmsg_level = IPPROTO_SCTP;
+		cmsg->cmsg_type = SCTP_SNDINFO;
+		cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndinfo));
+		memcpy(CMSG_DATA(cmsg), info, sizeof(struct sctp_sndinfo));
+		msg.msg_controllen += CMSG_SPACE(sizeof(struct sctp_sndinfo));
+		cmsg = (struct cmsghdr *)((caddr_t)cmsg + CMSG_SPACE(sizeof(struct sctp_sndinfo)));
+		assoc_id_ptr = &(((struct sctp_sndinfo *)info)->snd_assoc_id);
+		break;
+	case SCTP_SENDV_PRINFO:
+		if ((info == NULL) || (infolen < sizeof(struct sctp_prinfo))) {
+			free(cmsgbuf);
+			errno = EINVAL;
+			return (-1);
+		}
+		cmsg->cmsg_level = IPPROTO_SCTP;
+		cmsg->cmsg_type = SCTP_PRINFO;
+		cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_prinfo));
+		memcpy(CMSG_DATA(cmsg), info, sizeof(struct sctp_prinfo));
+		msg.msg_controllen += CMSG_SPACE(sizeof(struct sctp_prinfo));
+		cmsg = (struct cmsghdr *)((caddr_t)cmsg + CMSG_SPACE(sizeof(struct sctp_prinfo)));
+		break;
+	case SCTP_SENDV_AUTHINFO:
+		if ((info == NULL) || (infolen < sizeof(struct sctp_authinfo))) {
+			free(cmsgbuf);
+			errno = EINVAL;
+			return (-1);
+		}
+		cmsg->cmsg_level = IPPROTO_SCTP;
+		cmsg->cmsg_type = SCTP_AUTHINFO;
+		cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_authinfo));
+		memcpy(CMSG_DATA(cmsg), info, sizeof(struct sctp_authinfo));
+		msg.msg_controllen += CMSG_SPACE(sizeof(struct sctp_authinfo));
+		cmsg = (struct cmsghdr *)((caddr_t)cmsg + CMSG_SPACE(sizeof(struct sctp_authinfo)));
+		break;
+	case SCTP_SENDV_SPA:
+		if ((info == NULL) || (infolen < sizeof(struct sctp_sendv_spa))) {
+			free(cmsgbuf);
+			errno = EINVAL;
+			return (-1);
+		}
+		spa_info = (struct sctp_sendv_spa *)info;
+		if (spa_info->sendv_flags & SCTP_SEND_SNDINFO_VALID) {
+			cmsg->cmsg_level = IPPROTO_SCTP;
+			cmsg->cmsg_type = SCTP_SNDINFO;
+			cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndinfo));
+			memcpy(CMSG_DATA(cmsg), &spa_info->sendv_sndinfo, sizeof(struct sctp_sndinfo));
+			msg.msg_controllen += CMSG_SPACE(sizeof(struct sctp_sndinfo));
+			cmsg = (struct cmsghdr *)((caddr_t)cmsg + CMSG_SPACE(sizeof(struct sctp_sndinfo)));
+			assoc_id_ptr = &(spa_info->sendv_sndinfo.snd_assoc_id);
+		}
+		if (spa_info->sendv_flags & SCTP_SEND_PRINFO_VALID) {
+			cmsg->cmsg_level = IPPROTO_SCTP;
+			cmsg->cmsg_type = SCTP_PRINFO;
+			cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_prinfo));
+			memcpy(CMSG_DATA(cmsg), &spa_info->sendv_prinfo, sizeof(struct sctp_prinfo));
+			msg.msg_controllen += CMSG_SPACE(sizeof(struct sctp_prinfo));
+			cmsg = (struct cmsghdr *)((caddr_t)cmsg + CMSG_SPACE(sizeof(struct sctp_prinfo)));
+		}
+		if (spa_info->sendv_flags & SCTP_SEND_AUTHINFO_VALID) {
+			cmsg->cmsg_level = IPPROTO_SCTP;
+			cmsg->cmsg_type = SCTP_AUTHINFO;
+			cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_authinfo));
+			memcpy(CMSG_DATA(cmsg), &spa_info->sendv_authinfo, sizeof(struct sctp_authinfo));
+			msg.msg_controllen += CMSG_SPACE(sizeof(struct sctp_authinfo));
+			cmsg = (struct cmsghdr *)((caddr_t)cmsg + CMSG_SPACE(sizeof(struct sctp_authinfo)));
+		}
+		break;
+	default:
+		free(cmsgbuf);
+		errno = EINVAL;
+		return (-1);
+	}
+	addr = addrs;
+	msg.msg_name = NULL;
+	msg.msg_namelen = 0;
+
+	for (i = 0; i < addrcnt; i++) {
+		switch (addr->sa_family) {
+		case AF_INET:
+			addr_len = (socklen_t) sizeof(struct sockaddr_in);
+			addr_in = (struct sockaddr_in *)addr;
+			if (addr_in->sin_len != addr_len) {
+				free(cmsgbuf);
+				errno = EINVAL;
+				return (-1);
+			}
+			if (i == 0) {
+				port = addr_in->sin_port;
+			} else {
+				if (port == addr_in->sin_port) {
+					cmsg->cmsg_level = IPPROTO_SCTP;
+					cmsg->cmsg_type = SCTP_DSTADDRV4;
+					cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_addr));
+					memcpy(CMSG_DATA(cmsg), &addr_in->sin_addr, sizeof(struct in_addr));
+					msg.msg_controllen += CMSG_SPACE(sizeof(struct in_addr));
+					cmsg = (struct cmsghdr *)((caddr_t)cmsg + CMSG_SPACE(sizeof(struct in_addr)));
+				} else {
+					free(cmsgbuf);
+					errno = EINVAL;
+					return (-1);
+				}
+			}
+			break;
+		case AF_INET6:
+			addr_len = (socklen_t) sizeof(struct sockaddr_in6);
+			addr_in6 = (struct sockaddr_in6 *)addr;
+			if (addr_in6->sin6_len != addr_len) {
+				free(cmsgbuf);
+				errno = EINVAL;
+				return (-1);
+			}
+			if (i == 0) {
+				port = addr_in6->sin6_port;
+			} else {
+				if (port == addr_in6->sin6_port) {
+					cmsg->cmsg_level = IPPROTO_SCTP;
+					cmsg->cmsg_type = SCTP_DSTADDRV6;
+					cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_addr));
+					memcpy(CMSG_DATA(cmsg), &addr_in6->sin6_addr, sizeof(struct in6_addr));
+					msg.msg_controllen += CMSG_SPACE(sizeof(struct in6_addr));
+					cmsg = (struct cmsghdr *)((caddr_t)cmsg + CMSG_SPACE(sizeof(struct in6_addr)));
+				} else {
+					free(cmsgbuf);
+					errno = EINVAL;
+					return (-1);
+				}
+			}
+			break;
+		default:
+			free(cmsgbuf);
+			errno = EINVAL;
+			return (-1);
+		}
+		if (i == 0) {
+			msg.msg_name = addr;
+			msg.msg_namelen = addr_len;
+		}
+		addr = (struct sockaddr *)((caddr_t)addr + addr_len);
+	}
+	if (msg.msg_controllen == 0) {
+		msg.msg_control = NULL;
+	}
+	msg.msg_iov = __UNCONST(iov);
+	msg.msg_iovlen = iovcnt;
+	msg.msg_flags = 0;
+	ret = sendmsg(sd, &msg, flags);
+	free(cmsgbuf);
+	if ((ret >= 0) && (addrs != NULL) && (assoc_id_ptr != NULL)) {
+		assoc_id = sctp_getassocid(sd, addrs);
+		memcpy(assoc_id_ptr, &assoc_id, sizeof(assoc_id));
+	}
+	return (ret);
+}
+
+int
+sctp_peeloff(int sd, sctp_assoc_t assoc_id)
+{
+	int ret;
+	uint32_t val;
+
+	val = assoc_id;
+	ret = ioctl(sd, SIOCPEELOFF, &val);
+	if (ret == -1)
+		return ret;
+	else
+		return (int) val;
+}
+

Reply via email to