diff -r f6c702a75a83 lib/libsctp/sctp_sys_calls.c
--- a/lib/libsctp/sctp_sys_calls.c	Fri Jun 30 19:59:12 2006 +0200
+++ b/lib/libsctp/sctp_sys_calls.c	Wed Jul 05 21:49:11 2006 +0200
@@ -650,6 +650,21 @@ sctp_recvmsg (int s,
 	return(sz);
 }
 
+int
+sctp_peeloff(int sd, sctp_assoc_t assoc_id)
+{
+	int error;
+	int val = (int)assoc_id;
+	size_t len = sizeof(val);
+
+	error = getsockopt(sd, IPPROTO_SCTP, SCTP_PEELOFF, &val, &len);
+	if (error)
+		errno = error;
+
+	return(error == 0 ? val : -1);
+}
+
+#if 0
 #ifdef SYS_sctp_peeloff
 int
 sctp_peeloff(sd, assoc_id)
@@ -659,3 +674,4 @@ sctp_peeloff(sd, assoc_id)
 	return (syscall(SYS_sctp_peeloff, sd, assoc_id));
 }
 #endif
+#endif
diff -r f6c702a75a83 sys/kern/init_sysent.c
--- a/sys/kern/init_sysent.c	Fri Jun 30 19:59:12 2006 +0200
+++ b/sys/kern/init_sysent.c	Wed Jul 05 21:49:11 2006 +0200
@@ -2,8 +2,8 @@
  * System call switch table.
  *
  * DO NOT EDIT-- this file is automatically generated.
- * $DragonFly: src/sys/kern/init_sysent.c,v 1.42 2006/06/13 21:04:16 dillon Exp $
- * created from DragonFly: src/sys/kern/syscalls.master,v 1.39 2006/06/13 08:12:03 dillon Exp 
+ * $DragonFly$
+ * created from DragonFly: src/sys/kern/syscalls.master,v 1.40 2006/06/13 21:04:16 dillon Exp 
  */
 
 #include "opt_compat.h"
@@ -398,7 +398,7 @@ struct sysent sysent[] = {
 	{ AS(getresgid_args), (sy_call_t *)sys_getresgid },	/* 361 = getresgid */
 	{ 0, (sy_call_t *)sys_kqueue },			/* 362 = kqueue */
 	{ AS(kevent_args), (sy_call_t *)sys_kevent },	/* 363 = kevent */
-	{ AS(sctp_peeloff_args), (sy_call_t *)sys_sctp_peeloff },	/* 364 = sctp_peeloff */
+	{ 0, (sy_call_t *)sys_nosys },			/* 364 = nosys */
 	{ 0, (sy_call_t *)sys_nosys },			/* 365 = nosys */
 	{ 0, (sy_call_t *)sys_nosys },			/* 366 = nosys */
 	{ 0, (sy_call_t *)sys_nosys },			/* 367 = nosys */
diff -r f6c702a75a83 sys/kern/syscalls.c
--- a/sys/kern/syscalls.c	Fri Jun 30 19:59:12 2006 +0200
+++ b/sys/kern/syscalls.c	Wed Jul 05 21:49:11 2006 +0200
@@ -2,8 +2,8 @@
  * System call names.
  *
  * DO NOT EDIT-- this file is automatically generated.
- * $DragonFly: src/sys/kern/syscalls.c,v 1.41 2006/06/13 21:04:16 dillon Exp $
- * created from DragonFly: src/sys/kern/syscalls.master,v 1.39 2006/06/13 08:12:03 dillon Exp 
+ * $DragonFly$
+ * created from DragonFly: src/sys/kern/syscalls.master,v 1.40 2006/06/13 21:04:16 dillon Exp 
  */
 
 char *syscallnames[] = {
@@ -373,7 +373,7 @@ char *syscallnames[] = {
 	"getresgid",			/* 361 = getresgid */
 	"kqueue",			/* 362 = kqueue */
 	"kevent",			/* 363 = kevent */
-	"sctp_peeloff",			/* 364 = sctp_peeloff */
+	"#364",			/* 364 = nosys */
 	"#365",			/* 365 = nosys */
 	"#366",			/* 366 = nosys */
 	"#367",			/* 367 = nosys */
diff -r f6c702a75a83 sys/kern/syscalls.master
--- a/sys/kern/syscalls.master	Fri Jun 30 19:59:12 2006 +0200
+++ b/sys/kern/syscalls.master	Wed Jul 05 21:49:11 2006 +0200
@@ -531,7 +531,7 @@ 363	STD	BSD	{ int kevent(int fd, \
 			    const struct kevent *changelist, int nchanges, \
 			    struct kevent *eventlist, int nevents, \
 			    const struct timespec *timeout); }
-364	STD	BSD	{ int sctp_peeloff(int sd, caddr_t name ); }
+364	UNIMPL	NOHIDE	nosys
 ; 365-392 used by FreeBSD-current
 365	UNIMPL	NOHIDE	nosys
 366	UNIMPL	NOHIDE	nosys
diff -r f6c702a75a83 sys/kern/uipc_syscalls.c
--- a/sys/kern/uipc_syscalls.c	Fri Jun 30 19:59:12 2006 +0200
+++ b/sys/kern/uipc_syscalls.c	Wed Jul 05 21:49:11 2006 +0200
@@ -1758,91 +1758,3 @@ done0:
 		m_freem(mheader);
 	return (error);
 }
-
-int
-sys_sctp_peeloff(struct sctp_peeloff_args *uap)
-{
-#ifdef SCTP
-	struct thread *td = curthread;
-	struct proc *p = td->td_proc;
-	struct file *lfp = NULL;
-	struct file *nfp = NULL;
-	int error;
-	struct socket *head, *so;
-	caddr_t assoc_id;
-	int fd;
-	short fflag;		/* type must match fp->f_flag */
-
-	assoc_id = uap->name;
-	error = holdsock(p->p_fd, uap->sd, &lfp);
-	if (error) {
-		return (error);
-	}
-	crit_enter();
-	head = (struct socket *)lfp->f_data;
-	error = sctp_can_peel_off(head, assoc_id);
-	if (error) {
-		crit_exit();
-		goto done;
-	}
-	/*
-	 * At this point we know we do have a assoc to pull
-	 * we proceed to get the fd setup. This may block
-	 * but that is ok.
-	 */
-
-	fflag = lfp->f_flag;
-	error = falloc(p, &nfp, &fd);
-	if (error) {
-		/*
-		 * Probably ran out of file descriptors. Put the
-		 * unaccepted connection back onto the queue and
-		 * do another wakeup so some other process might
-		 * have a chance at it.
-		 */
-		crit_exit();
-		goto done;
-	}
-	uap->sysmsg_result = fd;
-
-	so = sctp_get_peeloff(head, assoc_id, &error);
-	if (so == NULL) {
-		/*
-		 * Either someone else peeled it off OR
-		 * we can't get a socket.
-		 */
-		goto noconnection;
-	}
-	so->so_state &= ~SS_COMP;
-	so->so_state &= ~SS_NOFDREF;
-	so->so_head = NULL;
-	if (head->so_sigio != NULL)
-		fsetown(fgetown(head->so_sigio), &so->so_sigio);
-
-	nfp->f_type = DTYPE_SOCKET;
-	nfp->f_flag = fflag;
-	nfp->f_ops = &socketops;
-	nfp->f_data = so;
-
-noconnection:
-	/*
-	 * Assign the file pointer to the reserved descriptor, or clear
-	 * the reserved descriptor if an error occured.
-	 */
-	if (error)
-		fsetfd(p, NULL, fd);
-	else
-		fsetfd(p, nfp, fd);
-	crit_exit();
-	/*
-	 * Release explicitly held references before returning.
-	 */
-done:
-	if (nfp != NULL)
-		fdrop(nfp);
-	fdrop(lfp);
-	return (error);
-#else /* SCTP */
-	return(EOPNOTSUPP);
-#endif /* SCTP */
-}
diff -r f6c702a75a83 sys/netinet/sctp.h
--- a/sys/netinet/sctp.h	Fri Jun 30 19:59:12 2006 +0200
+++ b/sys/netinet/sctp.h	Wed Jul 05 21:49:11 2006 +0200
@@ -149,6 +149,9 @@ struct sctp_paramhdr {
 #define SCTP_GET_NONCE_VALUES           0x00000023
 #define SCTP_DELAYED_ACK_TIME           0x00000024
 
+/* sctp_peeloff */
+#define SCTP_PEELOFF			0x000000ff
+
 /* Things for the AUTH draft possibly */
 #define SCTP_PEER_PUBLIC_KEY            0x00000100 /* get the peers public key */
 #define SCTP_MY_PUBLIC_KEY              0x00000101 /* get/set my endpoints public key */
diff -r f6c702a75a83 sys/netinet/sctp_usrreq.c
--- a/sys/netinet/sctp_usrreq.c	Fri Jun 30 19:59:12 2006 +0200
+++ b/sys/netinet/sctp_usrreq.c	Wed Jul 05 21:49:11 2006 +0200
@@ -61,7 +61,9 @@
 #include <sys/socketvar.h>
 #include <sys/sysctl.h>
 #include <sys/syslog.h>
+#include <sys/spinlock2.h>
 #include <sys/thread2.h>
+#include <sys/file.h>
 #include <net/if.h>
 #include <net/if_types.h>
 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__DragonFly__)
@@ -89,6 +91,7 @@
 #include <netinet/sctputil.h>
 #include <netinet/sctp_indata.h>
 #include <netinet/sctp_asconf.h>
+#include <netinet/sctp_peeloff.h>
 #ifdef IPSEC
 #ifndef __OpenBSD__
 #include <netinet6/ipsec.h>
@@ -148,6 +151,8 @@ unsigned int sctp_assoc_rtx_max_default 
 unsigned int sctp_assoc_rtx_max_default = SCTP_DEF_MAX_SEND;
 unsigned int sctp_path_rtx_max_default = SCTP_DEF_MAX_SEND/2;
 unsigned int sctp_nr_outgoing_streams_default = SCTP_OSTREAM_INITIAL;
+
+extern struct fileops socketops;
 
 void
 sctp_init(void)
@@ -2659,6 +2664,84 @@ sctp_optsget(struct socket *so,
 		       ((struct sockaddr *)&stcb->asoc.primary_destination->ro._l_addr)->sa_len);
 		SCTP_TCB_UNLOCK(stcb);
 		m->m_len = sizeof(*ssp);
+	}
+	break;
+	case SCTP_PEELOFF:
+	{
+		caddr_t assoc_id;
+		int *fd, fflag;
+		struct socket *newso;
+		struct file *nfp = NULL;
+
+		if ((size_t)m->m_len < sizeof(int)) {
+			error = EINVAL;
+			break;
+		}
+		assoc_id = *mtod(m, caddr_t *);
+
+		error = sctp_can_peel_off(so, assoc_id);
+		if (error)
+			goto done;
+
+		/* XXX: The file containing this socket should be held already? */
+		fflag = -1;
+		{
+			int i;
+			struct filedesc *fdp = p->td_proc->p_fd;
+
+			spin_lock_rd(&fdp->fd_spin);
+			for (i = 0; i <= fdp->fd_lastfile; ++i) {
+					if (fdp->fd_files[i].fp &&
+					    (struct socket *)fdp->fd_files[i].fp->f_data == so) {
+						fflag = fdp->fd_files[i].fp->f_flag;
+						break;
+					}
+			}
+			spin_unlock_rd(&fdp->fd_spin);
+			if (fflag == -1) {
+				error = EINVAL;
+				goto done;
+			}
+		}
+
+		fd = mtod(m, int *);
+		error = falloc(p->td_proc, &nfp, fd);
+		if (error) {
+			/* Probably ran out of file descriptors. Put the
+			 * unaccepted connection back onto the queue and do
+			 * another wakeup so some other process might have a
+			 * change at it.
+			 */
+			goto done;
+		}
+
+		newso = sctp_get_peeloff(so, assoc_id, &error);
+		if (newso == NULL) {
+			/*
+			 * Either someone else peeled it off, or we can't get a
+			 * socket
+			 */
+			goto noconnection;
+		}
+		newso->so_state &= ~SS_COMP;
+		newso->so_state &= ~SS_NOFDREF;
+		newso->so_head = NULL;
+		if (so->so_sigio != NULL)
+			fsetown(fgetown(so->so_sigio), &newso->so_sigio);
+
+		nfp->f_type = DTYPE_SOCKET;
+		nfp->f_flag = fflag;
+		nfp->f_ops = &socketops;
+		nfp->f_data = newso;
+ noconnection:
+		if (error)
+			fsetfd(p->td_proc, NULL, *fd);
+		else
+			fsetfd(p->td_proc, nfp, *fd);
+
+ done:
+		if (nfp != NULL)
+			fdrop(nfp);
 	}
 	break;
 	default:
