- /*
- * Set socket level options here and then call protocol
- * specific routine.
- */
- struct socket *cloned_so = NULL;
- int cloned_fd = *(int *)data;
-
- /* let's make sure it's either -1 or a valid file descriptor */
- if (cloned_fd != -1) {
- struct file *cloned_fp;
- error = getsock(p->p_fd, cloned_fd, &cloned_fp);
- if (error) {
- thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
- return (error);
- }
-
- cloned_so = (struct socket *)cloned_fp->f_data;
- }
-
- /* Always set socket non-blocking for OT */
- fp->f_flag |= FNONBLOCK;
- so->so_state |= SS_NBIO;
- so->so_options |= SO_DONTTRUNC | SO_WANTMORE;
- so->so_flags |= SOF_NOSIGPIPE;
-
- if (cloned_so && so != cloned_so) {
- /* Flags options */
- so->so_options |= cloned_so->so_options & ~SO_ACCEPTCONN;
-
- /* SO_LINGER */
- if (so->so_options & SO_LINGER)
- so->so_linger = cloned_so->so_linger;
-
- /* SO_SNDBUF, SO_RCVBUF */
- if (cloned_so->so_snd.sb_hiwat > 0) {
- if (sbreserve(&so->so_snd, cloned_so->so_snd.sb_hiwat) == 0) {
- error = ENOBUFS;
- thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
- return (error);
- }
- }
- if (cloned_so->so_rcv.sb_hiwat > 0) {
- if (sbreserve(&so->so_rcv, cloned_so->so_rcv.sb_hiwat) == 0) {
- error = ENOBUFS;
- thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
- return (error);
- }
- }
-
- /* SO_SNDLOWAT, SO_RCVLOWAT */
- so->so_snd.sb_lowat =
- (cloned_so->so_snd.sb_lowat > so->so_snd.sb_hiwat) ?
- so->so_snd.sb_hiwat : cloned_so->so_snd.sb_lowat;
- so->so_rcv.sb_lowat =
- (cloned_so->so_rcv.sb_lowat > so->so_rcv.sb_hiwat) ?
- so->so_rcv.sb_hiwat : cloned_so->so_rcv.sb_lowat;
-
- /* SO_SNDTIMEO, SO_RCVTIMEO */
- so->so_snd.sb_timeo = cloned_so->so_snd.sb_timeo;
- so->so_rcv.sb_timeo = cloned_so->so_rcv.sb_timeo;
- }
-
- error = (*so->so_proto->pr_usrreqs->pru_control)(so, cmd, data, 0, p);
- /* Just ignore protocols that do not understand it */
- if (error == EOPNOTSUPP)
- error = 0;
-
- thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
- return (error);
- }
+ /*
+ * Set socket level options here and then call protocol
+ * specific routine.
+ */
+ struct socket *cloned_so = NULL;
+ int cloned_fd = *(int *)data;
+
+ /* let's make sure it's either -1 or a valid file descriptor */
+ if (cloned_fd != -1) {
+ error = file_socket(cloned_fd, &cloned_so);
+ if (error) {
+ goto out;
+ }
+ dropsockref = cloned_fd;
+ }
+
+ /* Always set socket non-blocking for OT */
+ so->so_state |= SS_NBIO;
+ so->so_options |= SO_DONTTRUNC | SO_WANTMORE;
+ so->so_flags |= SOF_NOSIGPIPE;
+
+ if (cloned_so && so != cloned_so) {
+ /* Flags options */
+ so->so_options |=
+ cloned_so->so_options & ~SO_ACCEPTCONN;
+
+ /* SO_LINGER */
+ if (so->so_options & SO_LINGER)
+ so->so_linger = cloned_so->so_linger;
+
+ /* SO_SNDBUF, SO_RCVBUF */
+ if (cloned_so->so_snd.sb_hiwat > 0) {
+ if (sbreserve(&so->so_snd,
+ cloned_so->so_snd.sb_hiwat) == 0) {
+ error = ENOBUFS;
+ goto out;
+ }
+ }
+ if (cloned_so->so_rcv.sb_hiwat > 0) {
+ if (sbreserve(&so->so_rcv,
+ cloned_so->so_rcv.sb_hiwat) == 0) {
+ error = ENOBUFS;
+ goto out;
+ }
+ }
+
+ /* SO_SNDLOWAT, SO_RCVLOWAT */
+ so->so_snd.sb_lowat =
+ (cloned_so->so_snd.sb_lowat > so->so_snd.sb_hiwat) ?
+ so->so_snd.sb_hiwat : cloned_so->so_snd.sb_lowat;
+ so->so_rcv.sb_lowat =
+ (cloned_so->so_rcv.sb_lowat > so->so_rcv.sb_hiwat) ?
+ so->so_rcv.sb_hiwat : cloned_so->so_rcv.sb_lowat;
+
+ /* SO_SNDTIMEO, SO_RCVTIMEO */
+ so->so_snd.sb_timeo = cloned_so->so_snd.sb_timeo;
+ so->so_rcv.sb_timeo = cloned_so->so_rcv.sb_timeo;
+ }
+
+ error = (*so->so_proto->pr_usrreqs->pru_control)(so, cmd,
+ data, 0, p);
+ /* Just ignore protocols that do not understand it */
+ if (error == EOPNOTSUPP)
+ error = 0;
+
+ goto out;
+ }