xref: /titanic_51/usr/src/uts/common/fs/smbsrv/smb_net.c (revision a90cf9f29973990687fa61de9f1f6ea22e924e40)
1da6c28aaSamw /*
2da6c28aaSamw  * CDDL HEADER START
3da6c28aaSamw  *
4da6c28aaSamw  * The contents of this file are subject to the terms of the
5da6c28aaSamw  * Common Development and Distribution License (the "License").
6da6c28aaSamw  * You may not use this file except in compliance with the License.
7da6c28aaSamw  *
8da6c28aaSamw  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9da6c28aaSamw  * or http://www.opensolaris.org/os/licensing.
10da6c28aaSamw  * See the License for the specific language governing permissions
11da6c28aaSamw  * and limitations under the License.
12da6c28aaSamw  *
13da6c28aaSamw  * When distributing Covered Code, include this CDDL HEADER in each
14da6c28aaSamw  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15da6c28aaSamw  * If applicable, add the following below this CDDL HEADER, with the
16da6c28aaSamw  * fields enclosed by brackets "[]" replaced with your own identifying
17da6c28aaSamw  * information: Portions Copyright [yyyy] [name of copyright owner]
18da6c28aaSamw  *
19da6c28aaSamw  * CDDL HEADER END
20da6c28aaSamw  */
21da6c28aaSamw /*
225cdbe942Sjb150015  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23da6c28aaSamw  * Use is subject to license terms.
24b819cea2SGordon Ross  *
25*a90cf9f2SGordon Ross  * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
26da6c28aaSamw  */
27da6c28aaSamw 
28da6c28aaSamw #include <sys/types.h>
29da6c28aaSamw #include <sys/param.h>
30da6c28aaSamw #include <sys/ddi.h>
31da6c28aaSamw #include <sys/sunddi.h>
32da6c28aaSamw #include <sys/time.h>
33da6c28aaSamw #include <sys/varargs.h>
34da6c28aaSamw #include <sys/modctl.h>
35da6c28aaSamw #include <sys/pathname.h>
36da6c28aaSamw #include <sys/vnode.h>
37b819cea2SGordon Ross #include <sys/socket.h>
380f1702c5SYu Xiangning #include <sys/ksocket.h>
39da6c28aaSamw #undef mem_free /* XXX Remove this after we convert everything to kmem_alloc */
40da6c28aaSamw 
41da6c28aaSamw #include <smbsrv/smb_vops.h>
42da6c28aaSamw #include <smbsrv/smb.h>
43da6c28aaSamw #include <smbsrv/smb_kproto.h>
4421b7895dSjb150015 #include <smbsrv/smb_kstat.h>
4521b7895dSjb150015 
46da6c28aaSamw /*
47da6c28aaSamw  * SMB Network Socket API
48da6c28aaSamw  *
49da6c28aaSamw  * smb_socreate:	Creates an socket based on domain/type.
50da6c28aaSamw  * smb_soshutdown:	Disconnect a socket created with smb_socreate
51da6c28aaSamw  * smb_sodestroy:	Release resources associated with a socket
52da6c28aaSamw  * smb_sosend:		Send the contents of a buffer on a socket
53da6c28aaSamw  * smb_sorecv:		Receive data into a buffer from a socket
54da6c28aaSamw  * smb_iov_sosend:	Send the contents of an iovec on a socket
55da6c28aaSamw  * smb_iov_sorecv:	Receive data into an iovec from a socket
56da6c28aaSamw  */
57da6c28aaSamw 
580f1702c5SYu Xiangning ksocket_t
59da6c28aaSamw smb_socreate(int domain, int type, int protocol)
60da6c28aaSamw {
610f1702c5SYu Xiangning 	ksocket_t	sock;
62da6c28aaSamw 	int		err = 0;
63da6c28aaSamw 
640f1702c5SYu Xiangning 	err = ksocket_socket(&sock, domain, type, protocol, KSOCKET_SLEEP,
650f1702c5SYu Xiangning 	    CRED());
66da6c28aaSamw 
670f1702c5SYu Xiangning 	if (err != 0)
68da6c28aaSamw 		return (NULL);
690f1702c5SYu Xiangning 	else
700f1702c5SYu Xiangning 		return (sock);
71da6c28aaSamw }
72da6c28aaSamw 
73da6c28aaSamw /*
74da6c28aaSamw  * smb_soshutdown will disconnect the socket and prevent subsequent PDU
75da6c28aaSamw  * reception and transmission.  The sonode still exists but its state
76da6c28aaSamw  * gets modified to indicate it is no longer connected.  Calls to
77da6c28aaSamw  * smb_sorecv/smb_iov_sorecv will return so smb_soshutdown can be used
78da6c28aaSamw  * regain control of a thread stuck in smb_sorecv.
79da6c28aaSamw  */
80da6c28aaSamw void
810f1702c5SYu Xiangning smb_soshutdown(ksocket_t so)
82da6c28aaSamw {
830f1702c5SYu Xiangning 	(void) ksocket_shutdown(so, SHUT_RDWR, CRED());
84da6c28aaSamw }
85da6c28aaSamw 
86da6c28aaSamw /*
87da6c28aaSamw  * smb_sodestroy releases all resources associated with a socket previously
88da6c28aaSamw  * created with smb_socreate.  The socket must be shutdown using smb_soshutdown
89da6c28aaSamw  * before the socket is destroyed with smb_sodestroy, otherwise undefined
90da6c28aaSamw  * behavior will result.
91da6c28aaSamw  */
92da6c28aaSamw void
930f1702c5SYu Xiangning smb_sodestroy(ksocket_t so)
94da6c28aaSamw {
950f1702c5SYu Xiangning 	(void) ksocket_close(so, CRED());
96da6c28aaSamw }
97da6c28aaSamw 
98da6c28aaSamw int
990f1702c5SYu Xiangning smb_sorecv(ksocket_t so, void *msg, size_t len)
100da6c28aaSamw {
1010f1702c5SYu Xiangning 	size_t recvd;
102da6c28aaSamw 	int err;
103da6c28aaSamw 
104da6c28aaSamw 	ASSERT(so != NULL);
105da6c28aaSamw 	ASSERT(len != 0);
106da6c28aaSamw 
1070f1702c5SYu Xiangning 	if ((err = ksocket_recv(so, msg, len, MSG_WAITALL, &recvd,
1080f1702c5SYu Xiangning 	    CRED())) != 0) {
109da6c28aaSamw 		return (err);
110da6c28aaSamw 	}
111da6c28aaSamw 
112da6c28aaSamw 	/* Successful receive */
1130f1702c5SYu Xiangning 	return ((recvd == len) ? 0 : -1);
114da6c28aaSamw }
1155cdbe942Sjb150015 
1165cdbe942Sjb150015 /*
1175cdbe942Sjb150015  * smb_net_txl_constructor
1185cdbe942Sjb150015  *
1195cdbe942Sjb150015  *	Transmit list constructor
1205cdbe942Sjb150015  */
1215cdbe942Sjb150015 void
1225cdbe942Sjb150015 smb_net_txl_constructor(smb_txlst_t *txl)
1235cdbe942Sjb150015 {
1245cdbe942Sjb150015 	ASSERT(txl->tl_magic != SMB_TXLST_MAGIC);
1255cdbe942Sjb150015 
1265cdbe942Sjb150015 	mutex_init(&txl->tl_mutex, NULL, MUTEX_DEFAULT, NULL);
127*a90cf9f2SGordon Ross 	cv_init(&txl->tl_wait_cv, NULL, CV_DEFAULT, NULL);
1285cdbe942Sjb150015 	txl->tl_active = B_FALSE;
1295cdbe942Sjb150015 	txl->tl_magic = SMB_TXLST_MAGIC;
1305cdbe942Sjb150015 }
1315cdbe942Sjb150015 
1325cdbe942Sjb150015 /*
1335cdbe942Sjb150015  * smb_net_txl_destructor
1345cdbe942Sjb150015  *
1355cdbe942Sjb150015  *	Transmit list destructor
1365cdbe942Sjb150015  */
1375cdbe942Sjb150015 void
1385cdbe942Sjb150015 smb_net_txl_destructor(smb_txlst_t *txl)
1395cdbe942Sjb150015 {
1405cdbe942Sjb150015 	ASSERT(txl->tl_magic == SMB_TXLST_MAGIC);
1415cdbe942Sjb150015 
1425cdbe942Sjb150015 	txl->tl_magic = 0;
143*a90cf9f2SGordon Ross 	cv_destroy(&txl->tl_wait_cv);
1445cdbe942Sjb150015 	mutex_destroy(&txl->tl_mutex);
1455cdbe942Sjb150015 }
1465cdbe942Sjb150015 
1475cdbe942Sjb150015 /*
148*a90cf9f2SGordon Ross  * smb_net_send_uio
1495cdbe942Sjb150015  *
150*a90cf9f2SGordon Ross  * This routine puts the transmit buffer passed in on the wire.
151*a90cf9f2SGordon Ross  * If another thread is already sending, block on the CV.
1525cdbe942Sjb150015  */
1535cdbe942Sjb150015 int
154*a90cf9f2SGordon Ross smb_net_send_uio(smb_session_t *s, struct uio *uio)
1555cdbe942Sjb150015 {
156*a90cf9f2SGordon Ross 	struct msghdr msg;
157*a90cf9f2SGordon Ross 	size_t sent;
158*a90cf9f2SGordon Ross 	smb_txlst_t *txl = &s->s_txlst;
1595cdbe942Sjb150015 	int rc = 0;
1605cdbe942Sjb150015 
161*a90cf9f2SGordon Ross 	DTRACE_PROBE1(send__wait__start, struct smb_session_t *, s);
1625cdbe942Sjb150015 
163*a90cf9f2SGordon Ross 	/*
164*a90cf9f2SGordon Ross 	 * Wait for our turn to send.
165*a90cf9f2SGordon Ross 	 */
1665cdbe942Sjb150015 	mutex_enter(&txl->tl_mutex);
167*a90cf9f2SGordon Ross 	while (txl->tl_active)
168*a90cf9f2SGordon Ross 		cv_wait(&txl->tl_wait_cv, &txl->tl_mutex);
169*a90cf9f2SGordon Ross 
170*a90cf9f2SGordon Ross 	/*
171*a90cf9f2SGordon Ross 	 * Did the connection close while we waited?
172*a90cf9f2SGordon Ross 	 */
173*a90cf9f2SGordon Ross 	switch (s->s_state) {
174*a90cf9f2SGordon Ross 	case SMB_SESSION_STATE_DISCONNECTED:
175*a90cf9f2SGordon Ross 	case SMB_SESSION_STATE_TERMINATED:
176*a90cf9f2SGordon Ross 		rc = ENOTCONN;
177*a90cf9f2SGordon Ross 		break;
178*a90cf9f2SGordon Ross 	default:
1795cdbe942Sjb150015 		txl->tl_active = B_TRUE;
1805cdbe942Sjb150015 		break;
1815cdbe942Sjb150015 	}
182*a90cf9f2SGordon Ross 	mutex_exit(&txl->tl_mutex);
183*a90cf9f2SGordon Ross 
184*a90cf9f2SGordon Ross 	DTRACE_PROBE1(send__wait__done, struct smb_session_t *, s);
185*a90cf9f2SGordon Ross 	if (rc != 0)
186*a90cf9f2SGordon Ross 		return (rc);
187*a90cf9f2SGordon Ross 
188*a90cf9f2SGordon Ross 	/*
189*a90cf9f2SGordon Ross 	 * OK, try to send.
190*a90cf9f2SGordon Ross 	 *
191*a90cf9f2SGordon Ross 	 * This should block until we've sent it all,
192*a90cf9f2SGordon Ross 	 * or given up due to errors (socket closed).
193*a90cf9f2SGordon Ross 	 */
194*a90cf9f2SGordon Ross 	bzero(&msg, sizeof (msg));
195*a90cf9f2SGordon Ross 	msg.msg_iov = uio->uio_iov;
196*a90cf9f2SGordon Ross 	msg.msg_iovlen = uio->uio_iovcnt;
197*a90cf9f2SGordon Ross 	while (uio->uio_resid > 0) {
198*a90cf9f2SGordon Ross 		rc = ksocket_sendmsg(s->sock, &msg, 0, &sent, CRED());
199*a90cf9f2SGordon Ross 		if (rc != 0)
200*a90cf9f2SGordon Ross 			break;
201*a90cf9f2SGordon Ross 		uio->uio_resid -= sent;
202*a90cf9f2SGordon Ross 	}
203*a90cf9f2SGordon Ross 
2045cdbe942Sjb150015 	mutex_enter(&txl->tl_mutex);
2055cdbe942Sjb150015 	txl->tl_active = B_FALSE;
206*a90cf9f2SGordon Ross 	cv_signal(&txl->tl_wait_cv);
2075cdbe942Sjb150015 	mutex_exit(&txl->tl_mutex);
208*a90cf9f2SGordon Ross 
2095cdbe942Sjb150015 	return (rc);
2105cdbe942Sjb150015 }
211