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