51 #include <sys/vnode.h> |
51 #include <sys/vnode.h> |
52 #include <sys/poll.h> |
52 #include <sys/poll.h> |
53 #include <sys/stropts.h> |
53 #include <sys/stropts.h> |
54 #include <sys/stream.h> |
54 #include <sys/stream.h> |
55 #include <sys/strsubr.h> |
55 #include <sys/strsubr.h> |
|
56 #include <sys/strsun.h> |
56 #include <sys/suntpi.h> |
57 #include <sys/suntpi.h> |
57 #include <sys/ioctl.h> |
58 #include <sys/ioctl.h> |
58 #include <sys/sockio.h> |
59 #include <sys/sockio.h> |
59 #include <sys/filio.h> |
60 #include <sys/filio.h> |
60 #include <sys/stat.h> |
61 #include <sys/stat.h> |
84 |
85 |
85 #include <sys/esunddi.h> |
86 #include <sys/esunddi.h> |
86 #include <sys/autoconf.h> |
87 #include <sys/autoconf.h> |
87 |
88 |
88 #include <fs/sockfs/nl7c.h> |
89 #include <fs/sockfs/nl7c.h> |
|
90 |
|
91 #include <inet/udp_impl.h> |
|
92 #include <inet/tcp_impl.h> |
89 |
93 |
90 static int socktpi_close(struct vnode *, int, int, offset_t, struct cred *); |
94 static int socktpi_close(struct vnode *, int, int, offset_t, struct cred *); |
91 static int socktpi_read(struct vnode *, struct uio *, int, struct cred *, |
95 static int socktpi_read(struct vnode *, struct uio *, int, struct cred *, |
92 struct caller_context *); |
96 struct caller_context *); |
93 static int socktpi_write(struct vnode *, struct uio *, int, struct cred *, |
97 static int socktpi_write(struct vnode *, struct uio *, int, struct cred *, |
138 VOPNAME_DISPOSE, fs_error, |
142 VOPNAME_DISPOSE, fs_error, |
139 NULL, NULL |
143 NULL, NULL |
140 }; |
144 }; |
141 |
145 |
142 /* |
146 /* |
|
147 * Do direct function call to the transport layer below; this would |
|
148 * also allow the transport to utilize read-side synchronous stream |
|
149 * interface if necessary. This is a /etc/system tunable that must |
|
150 * not be modified on a running system. By default this is enabled |
|
151 * for performance reasons and may be disabled for debugging purposes. |
|
152 */ |
|
153 boolean_t socktpi_direct = B_TRUE; |
|
154 |
|
155 /* |
143 * Open routine used by socket() call. Note that vn_open checks for |
156 * Open routine used by socket() call. Note that vn_open checks for |
144 * VSOCK and fails the open (and VOP_OPEN is fs_nosys). The VSOCK check is |
157 * VSOCK and fails the open (and VOP_OPEN is fs_nosys). The VSOCK check is |
145 * needed since VSOCK type vnodes exist in various underlying filesystems as |
158 * needed since VSOCK type vnodes exist in various underlying filesystems as |
146 * a result of an AF_UNIX bind to a pathname. |
159 * a result of an AF_UNIX bind to a pathname. |
147 * |
160 * |
203 return (ENOTTY); /* XXX */ |
216 return (ENOTTY); /* XXX */ |
204 } |
217 } |
205 |
218 |
206 ASSERT(stp->sd_wrq != NULL); |
219 ASSERT(stp->sd_wrq != NULL); |
207 so->so_provinfo = tpi_findprov(stp->sd_wrq); |
220 so->so_provinfo = tpi_findprov(stp->sd_wrq); |
|
221 |
|
222 /* |
|
223 * If caller is interested in doing direct function call |
|
224 * interface to/from transport module, probe the module |
|
225 * directly beneath the streamhead to see if it qualifies. |
|
226 * |
|
227 * We turn off direct interface when qualifications fail; |
|
228 * note that we do these checks for everything other than |
|
229 * the tcp acceptor case, because the acceptor inherits |
|
230 * the capabilities of the listener and we've already done |
|
231 * the checks against the listening socket. |
|
232 */ |
|
233 if (!(flag & SO_ACCEPTOR) && (so->so_state & SS_DIRECT)) { |
|
234 queue_t *tq = stp->sd_wrq->q_next; |
|
235 |
|
236 /* |
|
237 * SS_DIRECT is currently supported and tested |
|
238 * only for tcp/udp; this is the main reason to |
|
239 * have the following assertions. |
|
240 */ |
|
241 ASSERT(so->so_family == AF_INET || |
|
242 so->so_family == AF_INET6); |
|
243 ASSERT(so->so_protocol == IPPROTO_UDP || |
|
244 so->so_protocol == IPPROTO_TCP || |
|
245 so->so_protocol == IPPROTO_IP); |
|
246 ASSERT(so->so_type == SOCK_DGRAM || |
|
247 so->so_type == SOCK_STREAM); |
|
248 |
|
249 /* |
|
250 * Abort direct call interface if the module directly |
|
251 * underneath the stream head is not defined with the |
|
252 * _D_DIRECT flag. This could happen in the tcp or |
|
253 * udp case, when some other module is autopushed |
|
254 * above it, or for some reasons the expected module |
|
255 * isn't purely D_MP (which is the main requirement). |
|
256 */ |
|
257 if (!socktpi_direct || !(tq->q_flag & _QDIRECT) || |
|
258 !(_OTHERQ(tq)->q_flag & _QDIRECT)) { |
|
259 int rval; |
|
260 |
|
261 /* Continue on without direct calls */ |
|
262 so->so_state &= ~SS_DIRECT; |
|
263 if ((error = strioctl(vp, _SIOCSOCKFALLBACK, |
|
264 0, 0, K_TO_K, CRED(), &rval)) != 0) { |
|
265 (void) socktpi_close(vp, flag, 1, |
|
266 (offset_t)0, cr); |
|
267 return (error); |
|
268 } |
|
269 } |
|
270 } |
208 } else { |
271 } else { |
209 /* |
272 /* |
210 * While the same socket can not be reopened (unlike specfs) |
273 * While the same socket can not be reopened (unlike specfs) |
211 * the stream head sets STREOPENFAIL when the autopush fails. |
274 * the stream head sets STREOPENFAIL when the autopush fails. |
212 */ |
275 */ |
433 if (so_mode & SM_BYTESTREAM) { |
496 if (so_mode & SM_BYTESTREAM) { |
434 /* Send M_DATA messages */ |
497 /* Send M_DATA messages */ |
435 if (so->so_nl7c_flags & NL7C_ENABLED) { |
498 if (so->so_nl7c_flags & NL7C_ENABLED) { |
436 /* Give NL7C some data */ |
499 /* Give NL7C some data */ |
437 nl7c_data(so, uiop); |
500 nl7c_data(so, uiop); |
|
501 } |
|
502 |
|
503 if ((so_state & SS_DIRECT) && |
|
504 canputnext(vp->v_stream->sd_wrq)) { |
|
505 return (sostream_direct(so, uiop, NULL, cr)); |
438 } |
506 } |
439 return (strwrite(vp, uiop, cr)); |
507 return (strwrite(vp, uiop, cr)); |
440 } else { |
508 } else { |
441 /* Send T_DATA_REQ messages without MORE_flag set */ |
509 /* Send T_DATA_REQ messages without MORE_flag set */ |
442 return (sosend_svc(so, uiop, T_DATA_REQ, 0, 0)); |
510 return (sosend_svc(so, uiop, T_DATA_REQ, 0, 0)); |
629 |
697 |
630 case I_FDINSERT: |
698 case I_FDINSERT: |
631 case I_SENDFD: |
699 case I_SENDFD: |
632 case I_RECVFD: |
700 case I_RECVFD: |
633 case I_ATMARK: |
701 case I_ATMARK: |
634 case SIOCPOPSOCKFS: |
702 case _SIOCSOCKFALLBACK: |
635 /* |
703 /* |
636 * These ioctls do not apply to sockets. I_FDINSERT can be |
704 * These ioctls do not apply to sockets. I_FDINSERT can be |
637 * used to send M_PROTO messages without modifying the socket |
705 * used to send M_PROTO messages without modifying the socket |
638 * state. I_SENDFD/RECVFD should not be used for socket file |
706 * state. I_SENDFD/RECVFD should not be used for socket file |
639 * descriptor passing since they assume a twisted stream. |
707 * descriptor passing since they assume a twisted stream. |
640 * SIOCATMARK must be used instead of I_ATMARK. |
708 * SIOCATMARK must be used instead of I_ATMARK. |
641 * |
709 * |
642 * SIOCPOPSOCKFS from an application should never be |
710 * _SIOCSOCKFALLBACK from an application should never be |
643 * processed. It is always generated in response to I_POP. |
711 * processed. It is only generated by socktpi_open() or |
|
712 * in response to I_POP or I_PUSH. |
644 */ |
713 */ |
645 #ifdef DEBUG |
714 #ifdef DEBUG |
646 cmn_err(CE_WARN, "Unsupported STREAMS ioctl 0x%x on socket. " |
715 cmn_err(CE_WARN, "Unsupported STREAMS ioctl 0x%x on socket. " |
647 "Pid = %d\n", cmd, curproc->p_pid); |
716 "Pid = %d\n", cmd, curproc->p_pid); |
648 #endif /* DEBUG */ |
717 #endif /* DEBUG */ |
722 return (strioctl(vp, cmd, arg, mode, U_TO_K, cr, rvalp)); |
791 return (strioctl(vp, cmd, arg, mode, U_TO_K, cr, rvalp)); |
723 } |
792 } |
724 |
793 |
725 switch (cmd) { |
794 switch (cmd) { |
726 case I_PUSH: |
795 case I_PUSH: |
|
796 if (so->so_state & SS_DIRECT) { |
|
797 mutex_enter(&so->so_lock); |
|
798 so_lock_single(so); |
|
799 mutex_exit(&so->so_lock); |
|
800 |
|
801 error = strioctl(vp, _SIOCSOCKFALLBACK, 0, 0, K_TO_K, |
|
802 CRED(), rvalp); |
|
803 |
|
804 mutex_enter(&so->so_lock); |
|
805 if (error == 0) |
|
806 so->so_state &= ~SS_DIRECT; |
|
807 so_unlock_single(so, SOLOCKED); |
|
808 mutex_exit(&so->so_lock); |
|
809 |
|
810 if (error != 0) |
|
811 return (error); |
|
812 } |
|
813 |
727 error = strioctl(vp, cmd, arg, mode, U_TO_K, cr, rvalp); |
814 error = strioctl(vp, cmd, arg, mode, U_TO_K, cr, rvalp); |
728 if (error == 0) |
815 if (error == 0) |
729 so->so_pushcnt++; |
816 so->so_pushcnt++; |
730 return (error); |
817 return (error); |
731 |
818 |