+ return (error);
+}
+
+int
+peeloff(struct proc *p, struct peeloff_args *uap, int *retval)
+{
+ /*
+ * Due to similiarity with a POSIX interface, define as
+ * an unofficial cancellation point.
+ */
+ __pthread_testcancel(1);
+ return (peeloff_nocancel(p, uap, retval));
+}
+
+static int
+peeloff_nocancel(struct proc *p, struct peeloff_args *uap, int *retval)
+{
+ struct fileproc *fp;
+ struct socket *mp_so, *so = NULL;
+ int newfd, fd = uap->s;
+ short fflag; /* type must match fp->f_flag */
+ int error;
+
+ *retval = -1;
+
+ error = fp_getfsock(p, fd, &fp, &mp_so);
+ if (error != 0) {
+ if (error == EOPNOTSUPP)
+ error = ENOTSOCK;
+ goto out_nofile;
+ }
+ if (mp_so == NULL) {
+ error = EBADF;
+ goto out;
+ }
+
+ socket_lock(mp_so, 1);
+ error = sopeelofflocked(mp_so, uap->aid, &so);
+ if (error != 0) {
+ socket_unlock(mp_so, 1);
+ goto out;
+ }
+ VERIFY(so != NULL);
+ socket_unlock(mp_so, 0); /* keep ref on mp_so for us */
+
+ fflag = fp->f_flag;
+ error = falloc(p, &fp, &newfd, vfs_context_current());
+ if (error != 0) {
+ /* drop this socket (probably ran out of file descriptors) */
+ soclose(so);
+ sodereference(mp_so); /* our mp_so ref */
+ goto out;
+ }
+
+ fp->f_flag = fflag;
+ fp->f_ops = &socketops;
+ fp->f_data = (caddr_t)so;
+
+ /*
+ * If the socket has been marked as inactive by sosetdefunct(),
+ * disallow further operations on it.
+ */
+ if (so->so_flags & SOF_DEFUNCT) {
+ sodefunct(current_proc(), so,
+ SHUTDOWN_SOCKET_LEVEL_DISCONNECT_INTERNAL);
+ }
+
+ proc_fdlock(p);
+ procfdtbl_releasefd(p, newfd, NULL);
+ fp_drop(p, newfd, fp, 1);
+ proc_fdunlock(p);
+
+ sodereference(mp_so); /* our mp_so ref */
+ *retval = newfd;
+
+out:
+ file_drop(fd);
+
+out_nofile:
+ return (error);
+}
+
+int
+disconnectx(struct proc *p, struct disconnectx_args *uap, int *retval)
+{
+ /*
+ * Due to similiarity with a POSIX interface, define as
+ * an unofficial cancellation point.
+ */
+ __pthread_testcancel(1);
+ return (disconnectx_nocancel(p, uap, retval));
+}
+
+static int
+disconnectx_nocancel(struct proc *p, struct disconnectx_args *uap, int *retval)
+{
+#pragma unused(p, retval)
+ struct socket *so;
+ int fd = uap->s;
+ int error;
+
+ error = file_socket(fd, &so);
+ if (error != 0)
+ return (error);
+ if (so == NULL) {
+ error = EBADF;
+ goto out;
+ }
+
+ error = sodisconnectx(so, uap->aid, uap->cid);