37 #include <sys/tihdr.h>
38 #include <sys/timod.h>
39 #include <sys/tpicommon.h>
40 #include <sys/socketvar.h>
41
42 #include <inet/common.h>
43 #include <inet/proto_set.h>
44 #include <inet/ip.h>
45 #include <inet/tcp.h>
46 #include <inet/tcp_impl.h>
47
48 static void tcp_activate(sock_lower_handle_t, sock_upper_handle_t,
49 sock_upcalls_t *, int, cred_t *);
50 static int tcp_accept(sock_lower_handle_t, sock_lower_handle_t,
51 sock_upper_handle_t, cred_t *);
52 static int tcp_bind(sock_lower_handle_t, struct sockaddr *,
53 socklen_t, cred_t *);
54 static int tcp_listen(sock_lower_handle_t, int, cred_t *);
55 static int tcp_connect(sock_lower_handle_t, const struct sockaddr *,
56 socklen_t, sock_connid_t *, cred_t *);
57 static int tcp_getsockopt(sock_lower_handle_t, int, int, void *,
58 socklen_t *, cred_t *);
59 static int tcp_setsockopt(sock_lower_handle_t, int, int, const void *,
60 socklen_t, cred_t *);
61 static int tcp_sendmsg(sock_lower_handle_t, mblk_t *, struct nmsghdr *,
62 cred_t *cr);
63 static int tcp_shutdown(sock_lower_handle_t, int, cred_t *);
64 static void tcp_clr_flowctrl(sock_lower_handle_t);
65 static int tcp_ioctl(sock_lower_handle_t, int, intptr_t, int, int32_t *,
66 cred_t *);
67 static int tcp_close(sock_lower_handle_t, int, cred_t *);
68
69 sock_downcalls_t sock_tcp_downcalls = {
70 tcp_activate,
71 tcp_accept,
72 tcp_bind,
73 tcp_listen,
74 tcp_connect,
75 tcp_getpeername,
76 tcp_getsockname,
77 tcp_getsockopt,
78 tcp_setsockopt,
79 tcp_sendmsg,
80 NULL,
81 NULL,
82 NULL,
310 error = EOPNOTSUPP;
311 break;
312 default:
313 error = EINVAL;
314 break;
315 }
316 } else {
317 error = proto_tlitosyserr(-error);
318 }
319 }
320
321 if (connp->conn_tcp->tcp_loopback) {
322 struct sock_proto_props sopp;
323
324 sopp.sopp_flags = SOCKOPT_LOOPBACK;
325 sopp.sopp_loopback = B_TRUE;
326
327 (*connp->conn_upcalls->su_set_proto_props)(
328 connp->conn_upper_handle, &sopp);
329 }
330 done:
331 squeue_synch_exit(connp);
332
333 return ((error == 0) ? EINPROGRESS : error);
334 }
335
336 /* ARGSUSED3 */
337 int
338 tcp_getpeername(sock_lower_handle_t proto_handle, struct sockaddr *addr,
339 socklen_t *addrlenp, cred_t *cr)
340 {
341 conn_t *connp = (conn_t *)proto_handle;
342 tcp_t *tcp = connp->conn_tcp;
343
344 /* All Solaris components should pass a cred for this operation. */
345 ASSERT(cr != NULL);
346
347 ASSERT(tcp != NULL);
348 if (tcp->tcp_state < TCPS_SYN_RCVD)
349 return (ENOTCONN);
350
735 * We can't assert the references because there might be other
736 * transient reference places because of some walkers or queued
737 * packets in squeue for the timewait state.
738 */
739 CONN_DEC_REF(connp);
740
741 /*
742 * EINPROGRESS tells sockfs to wait for a 'closed' upcall before
743 * freeing the socket.
744 */
745 return (EINPROGRESS);
746 }
747
748 /* ARGSUSED */
749 sock_lower_handle_t
750 tcp_create(int family, int type, int proto, sock_downcalls_t **sock_downcalls,
751 uint_t *smodep, int *errorp, int flags, cred_t *credp)
752 {
753 conn_t *connp;
754 boolean_t isv6 = family == AF_INET6;
755 if (type != SOCK_STREAM || (family != AF_INET && family != AF_INET6) ||
756 (proto != 0 && proto != IPPROTO_TCP)) {
757 *errorp = EPROTONOSUPPORT;
758 return (NULL);
759 }
760
761 connp = tcp_create_common(credp, isv6, B_TRUE, errorp);
762 if (connp == NULL) {
763 return (NULL);
764 }
765
766 /*
767 * Put the ref for TCP. Ref for IP was already put
768 * by ipcl_conn_create. Also Make the conn_t globally
769 * visible to walkers
770 */
771 mutex_enter(&connp->conn_lock);
772 CONN_INC_REF_LOCKED(connp);
773 ASSERT(connp->conn_ref == 2);
774 connp->conn_state_flags &= ~CONN_INCIPIENT;
775
776 connp->conn_flags |= IPCL_NONSTR;
777 mutex_exit(&connp->conn_lock);
778
779 ASSERT(errorp != NULL);
780 *errorp = 0;
781 *sock_downcalls = &sock_tcp_downcalls;
782 *smodep = SM_CONNREQUIRED | SM_EXDATA | SM_ACCEPTSUPP |
783 SM_SENDFILESUPP;
784
785 return ((sock_lower_handle_t)connp);
786 }
787
788 /*
789 * tcp_fallback
|
37 #include <sys/tihdr.h>
38 #include <sys/timod.h>
39 #include <sys/tpicommon.h>
40 #include <sys/socketvar.h>
41
42 #include <inet/common.h>
43 #include <inet/proto_set.h>
44 #include <inet/ip.h>
45 #include <inet/tcp.h>
46 #include <inet/tcp_impl.h>
47
48 static void tcp_activate(sock_lower_handle_t, sock_upper_handle_t,
49 sock_upcalls_t *, int, cred_t *);
50 static int tcp_accept(sock_lower_handle_t, sock_lower_handle_t,
51 sock_upper_handle_t, cred_t *);
52 static int tcp_bind(sock_lower_handle_t, struct sockaddr *,
53 socklen_t, cred_t *);
54 static int tcp_listen(sock_lower_handle_t, int, cred_t *);
55 static int tcp_connect(sock_lower_handle_t, const struct sockaddr *,
56 socklen_t, sock_connid_t *, cred_t *);
57 static int tcp_getpeername(sock_lower_handle_t, struct sockaddr *,
58 socklen_t *, cred_t *);
59 static int tcp_getsockname(sock_lower_handle_t, struct sockaddr *,
60 socklen_t *, cred_t *);
61 static int tcp_getsockopt(sock_lower_handle_t, int, int, void *,
62 socklen_t *, cred_t *);
63 static int tcp_setsockopt(sock_lower_handle_t, int, int, const void *,
64 socklen_t, cred_t *);
65 static int tcp_sendmsg(sock_lower_handle_t, mblk_t *, struct nmsghdr *,
66 cred_t *);
67 static int tcp_shutdown(sock_lower_handle_t, int, cred_t *);
68 static void tcp_clr_flowctrl(sock_lower_handle_t);
69 static int tcp_ioctl(sock_lower_handle_t, int, intptr_t, int, int32_t *,
70 cred_t *);
71 static int tcp_close(sock_lower_handle_t, int, cred_t *);
72
73 sock_downcalls_t sock_tcp_downcalls = {
74 tcp_activate,
75 tcp_accept,
76 tcp_bind,
77 tcp_listen,
78 tcp_connect,
79 tcp_getpeername,
80 tcp_getsockname,
81 tcp_getsockopt,
82 tcp_setsockopt,
83 tcp_sendmsg,
84 NULL,
85 NULL,
86 NULL,
314 error = EOPNOTSUPP;
315 break;
316 default:
317 error = EINVAL;
318 break;
319 }
320 } else {
321 error = proto_tlitosyserr(-error);
322 }
323 }
324
325 if (connp->conn_tcp->tcp_loopback) {
326 struct sock_proto_props sopp;
327
328 sopp.sopp_flags = SOCKOPT_LOOPBACK;
329 sopp.sopp_loopback = B_TRUE;
330
331 (*connp->conn_upcalls->su_set_proto_props)(
332 connp->conn_upper_handle, &sopp);
333 }
334 squeue_synch_exit(connp);
335
336 return ((error == 0) ? EINPROGRESS : error);
337 }
338
339 /* ARGSUSED3 */
340 int
341 tcp_getpeername(sock_lower_handle_t proto_handle, struct sockaddr *addr,
342 socklen_t *addrlenp, cred_t *cr)
343 {
344 conn_t *connp = (conn_t *)proto_handle;
345 tcp_t *tcp = connp->conn_tcp;
346
347 /* All Solaris components should pass a cred for this operation. */
348 ASSERT(cr != NULL);
349
350 ASSERT(tcp != NULL);
351 if (tcp->tcp_state < TCPS_SYN_RCVD)
352 return (ENOTCONN);
353
738 * We can't assert the references because there might be other
739 * transient reference places because of some walkers or queued
740 * packets in squeue for the timewait state.
741 */
742 CONN_DEC_REF(connp);
743
744 /*
745 * EINPROGRESS tells sockfs to wait for a 'closed' upcall before
746 * freeing the socket.
747 */
748 return (EINPROGRESS);
749 }
750
751 /* ARGSUSED */
752 sock_lower_handle_t
753 tcp_create(int family, int type, int proto, sock_downcalls_t **sock_downcalls,
754 uint_t *smodep, int *errorp, int flags, cred_t *credp)
755 {
756 conn_t *connp;
757 boolean_t isv6 = family == AF_INET6;
758
759 if (type != SOCK_STREAM || (family != AF_INET && family != AF_INET6) ||
760 (proto != 0 && proto != IPPROTO_TCP)) {
761 *errorp = EPROTONOSUPPORT;
762 return (NULL);
763 }
764
765 connp = tcp_create_common(credp, isv6, B_TRUE, errorp);
766 if (connp == NULL) {
767 return (NULL);
768 }
769
770 /*
771 * Put the ref for TCP. Ref for IP was already put
772 * by ipcl_conn_create. Also make the conn_t globally
773 * visible to walkers.
774 */
775 mutex_enter(&connp->conn_lock);
776 CONN_INC_REF_LOCKED(connp);
777 ASSERT(connp->conn_ref == 2);
778 connp->conn_state_flags &= ~CONN_INCIPIENT;
779
780 connp->conn_flags |= IPCL_NONSTR;
781 mutex_exit(&connp->conn_lock);
782
783 ASSERT(errorp != NULL);
784 *errorp = 0;
785 *sock_downcalls = &sock_tcp_downcalls;
786 *smodep = SM_CONNREQUIRED | SM_EXDATA | SM_ACCEPTSUPP |
787 SM_SENDFILESUPP;
788
789 return ((sock_lower_handle_t)connp);
790 }
791
792 /*
793 * tcp_fallback
|