da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * CDDL HEADER START
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * The contents of this file are subject to the terms of the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Common Development and Distribution License (the "License").
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * You may not use this file except in compliance with the License.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * or http://www.opensolaris.org/os/licensing.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * See the License for the specific language governing permissions
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * and limitations under the License.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * When distributing Covered Code, include this CDDL HEADER in each
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * If applicable, add the following below this CDDL HEADER, with the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * fields enclosed by brackets "[]" replaced with your own identifying
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * information: Portions Copyright [yyyy] [name of copyright owner]
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * CDDL HEADER END
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
5cdbe942b031cac50f4252efc4371b15d624fcd1jb * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Use is subject to license terms.
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross *
88c10719b37fbb198caa2923d45715f6d98f7e87Gordon Ross * Copyright 2016 Nexenta Systems, Inc. All rights reserved.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <sys/types.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <sys/param.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <sys/ddi.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <sys/sunddi.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <sys/time.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <sys/varargs.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <sys/modctl.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <sys/pathname.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <sys/vnode.h>
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross#include <sys/socket.h>
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning#include <sys/ksocket.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#undef mem_free /* XXX Remove this after we convert everything to kmem_alloc */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <smbsrv/smb_vops.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <smbsrv/smb.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <smbsrv/smb_kproto.h>
21b7895d5162890490668032d92f9fbe941f02bbjb#include <smbsrv/smb_kstat.h>
21b7895d5162890490668032d92f9fbe941f02bbjb
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * SMB Network Socket API
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * smb_socreate: Creates an socket based on domain/type.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * smb_soshutdown: Disconnect a socket created with smb_socreate
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * smb_sodestroy: Release resources associated with a socket
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * smb_sosend: Send the contents of a buffer on a socket
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * smb_sorecv: Receive data into a buffer from a socket
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * smb_iov_sosend: Send the contents of an iovec on a socket
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * smb_iov_sorecv: Receive data into an iovec from a socket
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningksocket_t
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwsmb_socreate(int domain, int type, int protocol)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning ksocket_t sock;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning int err = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning err = ksocket_socket(&sock, domain, type, protocol, KSOCKET_SLEEP,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning CRED());
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (err != 0)
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning return (NULL);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning else
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning return (sock);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * smb_soshutdown will disconnect the socket and prevent subsequent PDU
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * reception and transmission. The sonode still exists but its state
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * gets modified to indicate it is no longer connected. Calls to
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * smb_sorecv/smb_iov_sorecv will return so smb_soshutdown can be used
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * regain control of a thread stuck in smb_sorecv.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwvoid
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningsmb_soshutdown(ksocket_t so)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning (void) ksocket_shutdown(so, SHUT_RDWR, CRED());
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * smb_sodestroy releases all resources associated with a socket previously
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * created with smb_socreate. The socket must be shutdown using smb_soshutdown
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * before the socket is destroyed with smb_sodestroy, otherwise undefined
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * behavior will result.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwvoid
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningsmb_sodestroy(ksocket_t so)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning (void) ksocket_close(so, CRED());
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwint
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningsmb_sorecv(ksocket_t so, void *msg, size_t len)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning size_t recvd;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int err;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw ASSERT(so != NULL);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw ASSERT(len != 0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if ((err = ksocket_recv(so, msg, len, MSG_WAITALL, &recvd,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning CRED())) != 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (err);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* Successful receive */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning return ((recvd == len) ? 0 : -1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
5cdbe942b031cac50f4252efc4371b15d624fcd1jb * smb_net_txl_constructor
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
5cdbe942b031cac50f4252efc4371b15d624fcd1jb * Transmit list constructor
5cdbe942b031cac50f4252efc4371b15d624fcd1jb */
5cdbe942b031cac50f4252efc4371b15d624fcd1jbvoid
5cdbe942b031cac50f4252efc4371b15d624fcd1jbsmb_net_txl_constructor(smb_txlst_t *txl)
5cdbe942b031cac50f4252efc4371b15d624fcd1jb{
5cdbe942b031cac50f4252efc4371b15d624fcd1jb ASSERT(txl->tl_magic != SMB_TXLST_MAGIC);
5cdbe942b031cac50f4252efc4371b15d624fcd1jb
5cdbe942b031cac50f4252efc4371b15d624fcd1jb mutex_init(&txl->tl_mutex, NULL, MUTEX_DEFAULT, NULL);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross cv_init(&txl->tl_wait_cv, NULL, CV_DEFAULT, NULL);
5cdbe942b031cac50f4252efc4371b15d624fcd1jb txl->tl_active = B_FALSE;
5cdbe942b031cac50f4252efc4371b15d624fcd1jb txl->tl_magic = SMB_TXLST_MAGIC;
5cdbe942b031cac50f4252efc4371b15d624fcd1jb}
5cdbe942b031cac50f4252efc4371b15d624fcd1jb
5cdbe942b031cac50f4252efc4371b15d624fcd1jb/*
5cdbe942b031cac50f4252efc4371b15d624fcd1jb * smb_net_txl_destructor
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
5cdbe942b031cac50f4252efc4371b15d624fcd1jb * Transmit list destructor
5cdbe942b031cac50f4252efc4371b15d624fcd1jb */
5cdbe942b031cac50f4252efc4371b15d624fcd1jbvoid
5cdbe942b031cac50f4252efc4371b15d624fcd1jbsmb_net_txl_destructor(smb_txlst_t *txl)
5cdbe942b031cac50f4252efc4371b15d624fcd1jb{
5cdbe942b031cac50f4252efc4371b15d624fcd1jb ASSERT(txl->tl_magic == SMB_TXLST_MAGIC);
5cdbe942b031cac50f4252efc4371b15d624fcd1jb
5cdbe942b031cac50f4252efc4371b15d624fcd1jb txl->tl_magic = 0;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross cv_destroy(&txl->tl_wait_cv);
5cdbe942b031cac50f4252efc4371b15d624fcd1jb mutex_destroy(&txl->tl_mutex);
5cdbe942b031cac50f4252efc4371b15d624fcd1jb}
5cdbe942b031cac50f4252efc4371b15d624fcd1jb
5cdbe942b031cac50f4252efc4371b15d624fcd1jb/*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * smb_net_send_uio
5cdbe942b031cac50f4252efc4371b15d624fcd1jb *
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * This routine puts the transmit buffer passed in on the wire.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * If another thread is already sending, block on the CV.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwint
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Rosssmb_net_send_uio(smb_session_t *s, struct uio *uio)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross struct msghdr msg;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross size_t sent;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross smb_txlst_t *txl = &s->s_txlst;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross int rc = 0;
5cdbe942b031cac50f4252efc4371b15d624fcd1jb
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross DTRACE_PROBE1(send__wait__start, struct smb_session_t *, s);
5cdbe942b031cac50f4252efc4371b15d624fcd1jb
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross /*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Wait for our turn to send.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
5cdbe942b031cac50f4252efc4371b15d624fcd1jb mutex_enter(&txl->tl_mutex);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross while (txl->tl_active)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross cv_wait(&txl->tl_wait_cv, &txl->tl_mutex);
88c10719b37fbb198caa2923d45715f6d98f7e87Gordon Ross txl->tl_active = B_TRUE;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross mutex_exit(&txl->tl_mutex);
5cdbe942b031cac50f4252efc4371b15d624fcd1jb
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross DTRACE_PROBE1(send__wait__done, struct smb_session_t *, s);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross /*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * OK, try to send.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross *
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * This should block until we've sent it all,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * or given up due to errors (socket closed).
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross bzero(&msg, sizeof (msg));
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross msg.msg_iov = uio->uio_iov;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross msg.msg_iovlen = uio->uio_iovcnt;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross while (uio->uio_resid > 0) {
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross rc = ksocket_sendmsg(s->sock, &msg, 0, &sent, CRED());
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (rc != 0)
5cdbe942b031cac50f4252efc4371b15d624fcd1jb break;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross uio->uio_resid -= sent;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross mutex_enter(&txl->tl_mutex);
5cdbe942b031cac50f4252efc4371b15d624fcd1jb txl->tl_active = B_FALSE;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross cv_signal(&txl->tl_wait_cv);
5cdbe942b031cac50f4252efc4371b15d624fcd1jb mutex_exit(&txl->tl_mutex);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
5cdbe942b031cac50f4252efc4371b15d624fcd1jb return (rc);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}