Index: sys/modules/Makefile =================================================================== --- sys/modules/Makefile +++ sys/modules/Makefile @@ -319,6 +319,7 @@ ${_safe} \ ${_sbni} \ scc \ + ${_sctp} \ sdhci \ ${_sdhci_acpi} \ sdhci_pci \ @@ -430,6 +431,9 @@ .if ${KERN_OPTS:MIPSEC_SUPPORT} && !${KERN_OPTS:MIPSEC} _ipsec= ipsec .endif +.if ${KERN_OPTS:MSCTP_SUPPORT} || ${KERN_OPTS:MSCTP} +_sctp= sctp +.endif .endif .if (${MK_INET_SUPPORT} != "no" && ${MK_INET6_SUPPORT} != "no") || \ Index: sys/modules/sctp/Makefile =================================================================== --- /dev/null +++ sys/modules/sctp/Makefile @@ -0,0 +1,30 @@ +# $FreeBSD$ + +.PATH: ${SRCTOP}/sys/netinet +.PATH: ${SRCTOP}/sys/netinet6 + +KMOD= sctp +SRCS= sctp_asconf.c \ + sctp_auth.c \ + sctp_bsd_addr.c \ + sctp_cc_functions.c \ + sctp_crc32.c \ + sctp_indata.c \ + sctp_input.c \ + sctp_kdtrace.c \ + sctp_module.c \ + sctp_output.c \ + sctp_pcb.c \ + sctp_peeloff.c \ + sctp_ss_functions.c \ + sctp_syscalls.c \ + sctp_sysctl.c \ + sctp_timer.c \ + sctp_usrreq.c \ + sctp6_usrreq.c \ + sctputil.c + +SRCS+= device_if.h bus_if.h vnode_if.h +SRCS+= opt_capsicum.h opt_ktrace.h opt_inet.h opt_inet6.h opt_sctp.h + +.include Index: sys/netinet/sctp_module.c =================================================================== --- /dev/null +++ sys/netinet/sctp_module.c @@ -0,0 +1,197 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2019-2020 The FreeBSD Foundation + * + * This software was developed by Mark Johnston under sponsorship from + * the FreeBSD Foundation. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 +__FBSDID("$FreeBSD$"); + +#include "opt_inet.h" +#include "opt_inet6.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#ifdef INET +extern struct domain inetdomain; + +struct protosw sctp_stream_protosw = { + .pr_type = SOCK_STREAM, + .pr_domain = &inetdomain, + .pr_protocol = IPPROTO_SCTP, + .pr_flags = PR_CONNREQUIRED|PR_WANTRCVD|PR_LASTHDR, + .pr_input = sctp_input, + .pr_ctlinput = sctp_ctlinput, + .pr_ctloutput = sctp_ctloutput, + .pr_drain = sctp_drain, + .pr_usrreqs = &sctp_usrreqs, +}; + +struct protosw sctp_seqpacket_protosw = { + .pr_type = SOCK_SEQPACKET, + .pr_domain = &inetdomain, + .pr_protocol = IPPROTO_SCTP, + .pr_flags = PR_WANTRCVD|PR_LASTHDR, + .pr_input = sctp_input, + .pr_ctlinput = sctp_ctlinput, + .pr_ctloutput = sctp_ctloutput, + .pr_drain = sctp_drain, + .pr_usrreqs = &sctp_usrreqs, +}; +#endif + +#ifdef INET6 +extern struct domain inet6domain; + +struct protosw sctp6_stream_protosw = { + .pr_type = SOCK_STREAM, + .pr_domain = &inet6domain, + .pr_protocol = IPPROTO_SCTP, + .pr_flags = PR_CONNREQUIRED|PR_WANTRCVD|PR_LASTHDR, + .pr_input = sctp6_input, + .pr_ctlinput = sctp6_ctlinput, + .pr_ctloutput = sctp_ctloutput, + .pr_init = sctp_init, + .pr_drain = sctp_drain, + .pr_usrreqs = &sctp6_usrreqs, +}; + +struct protosw sctp6_seqpacket_protosw = { + .pr_type = SOCK_SEQPACKET, + .pr_domain = &inet6domain, + .pr_protocol = IPPROTO_SCTP, + .pr_flags = PR_WANTRCVD|PR_LASTHDR, + .pr_input = sctp6_input, + .pr_ctlinput = sctp6_ctlinput, + .pr_ctloutput = sctp_ctloutput, +#ifndef INET /* Do not call initialization and drain routines twice. */ + .pr_init = sctp_init, + .pr_drain = sctp_drain, +#endif + .pr_usrreqs = &sctp6_usrreqs, +}; +#endif + +static int +sctp_module_load(void) +{ + int error; + +#ifdef INET + error = pf_proto_register(PF_INET, &sctp_stream_protosw); + if (error != 0) + return (error); + error = pf_proto_register(PF_INET, &sctp_seqpacket_protosw); + if (error != 0) + return (error); + error = ipproto_register(IPPROTO_SCTP); + if (error != 0) + return (error); +#endif +#ifdef INET6 + error = pf_proto_register(PF_INET6, &sctp6_stream_protosw); + if (error != 0) + return (error); + error = pf_proto_register(PF_INET6, &sctp6_seqpacket_protosw); + if (error != 0) + return (error); + error = ip6proto_register(IPPROTO_SCTP); + if (error != 0) + return (error); +#endif + error = sctp_syscalls_init(); + if (error != 0) + return (error); + return (0); +} + +static int __unused +sctp_module_unload(void) +{ + + (void)sctp_syscalls_uninit(); + +#ifdef INET + (void)ipproto_unregister(IPPROTO_SCTP); + (void)pf_proto_unregister(PF_INET, IPPROTO_SCTP, SOCK_STREAM); + (void)pf_proto_unregister(PF_INET, IPPROTO_SCTP, SOCK_SEQPACKET); +#endif +#ifdef INET6 + (void)ip6proto_unregister(IPPROTO_SCTP); + (void)pf_proto_unregister(PF_INET6, IPPROTO_SCTP, SOCK_STREAM); + (void)pf_proto_unregister(PF_INET6, IPPROTO_SCTP, SOCK_SEQPACKET); +#endif + return (0); +} + +static int +sctp_modload(struct module *module, int cmd, void *arg) +{ + int error; + + switch (cmd) { + case MOD_LOAD: + error = sctp_module_load(); + break; + case MOD_UNLOAD: + /* + * Unloading SCTP is currently unsupported. Currently, SCTP + * iterator threads are not stopped during unload. + */ + error = EOPNOTSUPP; + break; + default: + error = 0; + break; + } + return (error); +} + +static moduledata_t sctp_mod = { + "sctp", + &sctp_modload, + NULL, +}; + +DECLARE_MODULE(sctp, sctp_mod, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY); +MODULE_VERSION(sctp, 1); Index: sys/netinet/sctp_os_bsd.h =================================================================== --- sys/netinet/sctp_os_bsd.h +++ sys/netinet/sctp_os_bsd.h @@ -45,9 +45,12 @@ #include "opt_sctp.h" #include +#include +#include #include #include #include +#include #include #include #include @@ -85,7 +88,6 @@ #include #ifdef INET6 -#include #include #include #include @@ -477,4 +479,7 @@ #define SCTP_IS_LISTENING(inp) ((inp->sctp_flags & SCTP_PCB_FLAGS_ACCEPTING) != 0) +int sctp_syscalls_init(void); +int sctp_syscalls_uninit(void); + #endif Index: sys/netinet/sctp_syscalls.c =================================================================== --- sys/netinet/sctp_syscalls.c +++ sys/netinet/sctp_syscalls.c @@ -69,6 +69,8 @@ #include #endif #ifdef COMPAT_FREEBSD32 +#include +#include #include #endif @@ -78,6 +80,7 @@ #include #include +#include #include static struct syscall_helper_data sctp_syscalls[] = { @@ -88,28 +91,52 @@ SYSCALL_INIT_LAST }; -static void -sctp_syscalls_init(void *unused __unused) +#ifdef COMPAT_FREEBSD32 +static struct syscall_helper_data sctp32_syscalls[] = { + SYSCALL32_INIT_HELPER_COMPAT(sctp_peeloff), + SYSCALL32_INIT_HELPER_COMPAT(sctp_generic_sendmsg), + SYSCALL32_INIT_HELPER_COMPAT(sctp_generic_sendmsg_iov), + SYSCALL32_INIT_HELPER_COMPAT(sctp_generic_recvmsg), + SYSCALL_INIT_LAST +}; +#endif + +int +sctp_syscalls_init(void) { - int error __unused; + int error; - error = syscall_helper_register(sctp_syscalls, SY_THR_STATIC); - KASSERT((error == 0), - ("%s: syscall_helper_register failed for sctp syscalls", __func__)); + error = syscall_helper_register(sctp_syscalls, SY_THR_STATIC_KLD); + if (error != 0) + return (error); #ifdef COMPAT_FREEBSD32 - error = syscall32_helper_register(sctp_syscalls, SY_THR_STATIC); - KASSERT((error == 0), - ("%s: syscall32_helper_register failed for sctp syscalls", - __func__)); + error = syscall32_helper_register(sctp32_syscalls, SY_THR_STATIC_KLD); + if (error != 0) + return (error); #endif + return (0); +} + +int +sctp_syscalls_uninit(void) +{ + int error; + +#ifdef COMPAT_FREEBSD32 + error = syscall32_helper_unregister(sctp32_syscalls); + if (error != 0) + return (error); +#endif + error = syscall_helper_unregister(sctp_syscalls); + if (error != 0) + return (error); + return (0); } -SYSINIT(sctp_syscalls, SI_SUB_SYSCALLS, SI_ORDER_ANY, sctp_syscalls_init, NULL); /* * SCTP syscalls. * Functionality only compiled in if SCTP is defined in the kernel Makefile, * otherwise all return EOPNOTSUPP. - * XXX: We should make this loadable one day. */ int sys_sctp_peeloff(td, uap) @@ -119,7 +146,7 @@ caddr_t name; } */ *uap; { -#if (defined(INET) || defined(INET6)) && defined(SCTP) +#if defined(INET) || defined(INET6) struct file *headfp, *nfp = NULL; struct socket *head, *so; cap_rights_t rights; @@ -181,9 +208,7 @@ fdrop(headfp, td); done2: return (error); -#else /* SCTP */ - return (EOPNOTSUPP); -#endif /* SCTP */ +#endif } int @@ -199,7 +224,7 @@ int flags } */ *uap; { -#if (defined(INET) || defined(INET6)) && defined(SCTP) +#if defined(INET) || defined(INET6) struct sctp_sndrcvinfo sinfo, *u_sinfo = NULL; struct socket *so; struct file *fp = NULL; @@ -294,9 +319,7 @@ sctp_bad2: free(to, M_SONAME); return (error); -#else /* SCTP */ - return (EOPNOTSUPP); -#endif /* SCTP */ +#endif } int @@ -312,7 +335,7 @@ int flags } */ *uap; { -#if (defined(INET) || defined(INET6)) && defined(SCTP) +#if defined(INET) || defined(INET6) struct sctp_sndrcvinfo sinfo, *u_sinfo = NULL; struct socket *so; struct file *fp = NULL; @@ -424,9 +447,7 @@ sctp_bad2: free(to, M_SONAME); return (error); -#else /* SCTP */ - return (EOPNOTSUPP); -#endif /* SCTP */ +#endif } int @@ -442,7 +463,7 @@ int *msg_flags } */ *uap; { -#if (defined(INET) || defined(INET6)) && defined(SCTP) +#if defined(INET) || defined(INET6) uint8_t sockbufstore[256]; struct uio auio; struct iovec *iov, *tiov; @@ -572,7 +593,5 @@ fdrop(fp, td); return (error); -#else /* SCTP */ - return (EOPNOTSUPP); -#endif /* SCTP */ +#endif } Index: sys/netinet/sctp_usrreq.c =================================================================== --- sys/netinet/sctp_usrreq.c +++ sys/netinet/sctp_usrreq.c @@ -97,9 +97,9 @@ static void sctp_finish(void *unused __unused) { + EVENTHANDLER_DEREGISTER(rt_addrmsg, SCTP_BASE_VAR(eh_tag)); sctp_pcb_finish(); } - VNET_SYSUNINIT(sctp, SI_SUB_PROTO_DOMAIN, SI_ORDER_FOURTH, sctp_finish, NULL); #endif