4bff34e37def8a90f9194d81bc345c52ba20086athurlow/*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Copyright (c) 2000-2001 Boris Popov
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * All rights reserved.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Redistribution and use in source and binary forms, with or without
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * modification, are permitted provided that the following conditions
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * are met:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * 1. Redistributions of source code must retain the above copyright
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * notice, this list of conditions and the following disclaimer.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * 2. Redistributions in binary form must reproduce the above copyright
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * notice, this list of conditions and the following disclaimer in the
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * documentation and/or other materials provided with the distribution.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * 3. All advertising materials mentioning features or use of this software
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * must display the following acknowledgement:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * This product includes software developed by Boris Popov.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * 4. Neither the name of the author nor the names of any co-contributors
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * may be used to endorse or promote products derived from this software
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * without specific prior written permission.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * SUCH DAMAGE.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * $Id: smb_trantcp.c,v 1.39 2005/03/02 01:27:44 lindak Exp $
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
22eb7cb54d8a6bcf6fe2674cb4b1f0cf2d85cfb6gd/*
de8c4a14ec9a49bad5e62b2cfa6c1ba21de1c708Erik Nordmark * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
22eb7cb54d8a6bcf6fe2674cb4b1f0cf2d85cfb6gd * Use is subject to license terms.
3ce9ce383e93f64f4baed13c5a0a28d7a5f1b71eBayard Bell * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
22eb7cb54d8a6bcf6fe2674cb4b1f0cf2d85cfb6gd */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/param.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/systm.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/autoconf.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/sysmacros.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/sunddi.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/kmem.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/proc.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/protosw.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/socket.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/poll.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/stream.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/strsubr.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/strsun.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/stropts.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/cmn_err.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/tihdr.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/tiuser.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/t_kuser.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <sys/priv.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <net/if.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <net/route.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <netinet/in.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <netinet/tcp.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <netsmb/smb_osdep.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <netsmb/mchain.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <netsmb/netbios.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <netsmb/smb.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <netsmb/smb_conn.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <netsmb/smb_subr.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <netsmb/smb_tran.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include <netsmb/smb_trantcp.h>
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow/*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * SMB messages are up to 64K.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Let's leave room for two.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlowstatic int smb_tcpsndbuf = 0x20000;
4bff34e37def8a90f9194d81bc345c52ba20086athurlowstatic int smb_tcprcvbuf = 0x20000;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlowstatic int nb_disconnect(struct nbpcb *nbp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow/*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Get mblks into *mpp until the data length is at least mlen.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Note that *mpp may already contain a fragment.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * If we ever have to wait more than 15 sec. to read a message,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * return ETIME. (Caller will declare the VD dead.)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlowstatic int
4bff34e37def8a90f9194d81bc345c52ba20086athurlownb_getmsg_mlen(struct nbpcb *nbp, mblk_t **mpp, size_t mlen)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mblk_t *im, *tm;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow union T_primitives *pptr;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow size_t dlen;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow int events, fmode, timo, waitflg;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow int error = 0;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross /* We should be the only reader. */
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross ASSERT(nbp->nbp_flags & NBF_RECVLOCK);
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross /* nbp->nbp_tiptr checked by caller */
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Get the first message (fragment) if
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * we don't already have a left-over.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow dlen = msgdsize(*mpp); /* *mpp==null is OK */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow while (dlen < mlen) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * I think we still want this to return ETIME
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * if nothing arrives for SMB_NBTIMO (15) sec.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * so we can report "server not responding".
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * We _could_ just block here now that our
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * IOD is just a reader.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#if 1
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /* Wait with timeout... */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow events = 0;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow waitflg = READWAIT;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow timo = SEC_TO_TICK(SMB_NBTIMO);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = t_kspoll(nbp->nbp_tiptr, timo, waitflg, &events);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (!error && !events)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = ETIME;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /* file mode for recv is: */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow fmode = FNDELAY; /* non-blocking */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#else
4bff34e37def8a90f9194d81bc345c52ba20086athurlow fmode = 0; /* normal (blocking) */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#endif
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /* Get some more... */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow tm = NULL;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = tli_recv(nbp->nbp_tiptr, &tm, fmode);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error == EAGAIN)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow continue;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Normally get M_DATA messages here,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * but have to check for other types.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow switch (tm->b_datap->db_type) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow case M_DATA:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow case M_PROTO:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow case M_PCPROTO:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*LINTED*/
4bff34e37def8a90f9194d81bc345c52ba20086athurlow pptr = (union T_primitives *)tm->b_rptr;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow switch (pptr->type) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow case T_DATA_IND:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /* remove 1st mblk, keep the rest. */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow im = tm->b_cont;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow tm->b_cont = NULL;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow freeb(tm);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow tm = im;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow case T_DISCON_IND:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /* Peer disconnected. */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow NBDEBUG("T_DISCON_IND: reason=%d",
4bff34e37def8a90f9194d81bc345c52ba20086athurlow pptr->discon_ind.DISCON_reason);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow goto discon;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow case T_ORDREL_IND:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /* Peer disconnecting. */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow NBDEBUG("T_ORDREL_IND");
4bff34e37def8a90f9194d81bc345c52ba20086athurlow goto discon;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow case T_OK_ACK:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow switch (pptr->ok_ack.CORRECT_prim) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow case T_DISCON_REQ:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow NBDEBUG("T_OK_ACK/T_DISCON_REQ");
4bff34e37def8a90f9194d81bc345c52ba20086athurlow goto discon;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow default:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow NBDEBUG("T_OK_ACK/prim=%d",
4bff34e37def8a90f9194d81bc345c52ba20086athurlow pptr->ok_ack.CORRECT_prim);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow goto discon;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow default:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow NBDEBUG("M_PROTO/type=%d", pptr->type);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow goto discon;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break; /* M_PROTO, M_PCPROTO */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow default:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow NBDEBUG("unexpected msg type=%d",
4bff34e37def8a90f9194d81bc345c52ba20086athurlow tm->b_datap->db_type);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*FALLTHROUGH*/
4bff34e37def8a90f9194d81bc345c52ba20086athurlowdiscon:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * The connection is no longer usable.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Drop this message and disconnect.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Note: nb_disconnect only does t_snddis
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * on the first call, but does important
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * cleanup and state change on any call.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow freemsg(tm);
02d09e03eb27f3a2dc299de704e45dae5173f43fGordon Ross (void) nb_disconnect(nbp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (ENOTCONN);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * If we have a data message, append it to
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * the previous chunk(s) and update dlen
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (!tm)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow continue;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (*mpp == NULL) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *mpp = tm;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow } else {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /* Append */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow for (im = *mpp; im->b_cont; im = im->b_cont)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow ;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow im->b_cont = tm;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow dlen += msgdsize(tm);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow/*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Send a T_DISCON_REQ (disconnect)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlowstatic int
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Rossnb_snddis(struct nbpcb *nbp)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross TIUSER *tiptr = nbp->nbp_tiptr;
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross cred_t *cr = nbp->nbp_cred;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mblk_t *mp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct T_discon_req *dreq;
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross int error, mlen;
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross ASSERT(MUTEX_HELD(&nbp->nbp_lock));
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross if (tiptr == NULL)
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross return (EBADF);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mlen = sizeof (struct T_discon_req);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (!(mp = allocb_cred_wait(mlen, STR_NOSIG, &error, cr, NOPID)))
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mp->b_datap->db_type = M_PROTO;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*LINTED*/
4bff34e37def8a90f9194d81bc345c52ba20086athurlow dreq = (struct T_discon_req *)mp->b_wptr;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow dreq->PRIM_type = T_DISCON_REQ;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow dreq->SEQ_number = -1;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mp->b_wptr += sizeof (struct T_discon_req);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross error = tli_send(tiptr, mp, tiptr->fp->f_flag);
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross /*
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross * There is an OK/ACK response expected, which is
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross * either handled by our receiver thread, or just
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross * discarded if we're closing this endpoint.
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross */
6723e17f4e092e7f275f0791f9fce3ea061339d7Gordon Ross
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow/*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Stuff the NetBIOS header into space already prepended.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
02d09e03eb27f3a2dc299de704e45dae5173f43fGordon Rossstatic void
4bff34e37def8a90f9194d81bc345c52ba20086athurlownb_sethdr(mblk_t *m, uint8_t type, uint32_t len)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow uint32_t *p;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow len &= 0x1FFFF;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow len |= (type << 24);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*LINTED*/
4bff34e37def8a90f9194d81bc345c52ba20086athurlow p = (uint32_t *)m->b_rptr;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *p = htonl(len);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow/*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Wait for up to 15 sec. for the next packet.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Often return ETIME and do nothing else.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * When a packet header is available, check
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * the header and get the length, but don't
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * consume it. No side effects here except
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * for the pullupmsg call.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlowstatic int
4bff34e37def8a90f9194d81bc345c52ba20086athurlownbssn_peekhdr(struct nbpcb *nbp, size_t *lenp, uint8_t *rpcodep)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow uint32_t len, *hdr;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow int error;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Get the first message (fragment) if
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * we don't already have a left-over.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = nb_getmsg_mlen(nbp, &nbp->nbp_frag, sizeof (len));
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (!pullupmsg(nbp->nbp_frag, sizeof (len)))
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (ENOSR);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Check the NetBIOS header.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * (NOT consumed here)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*LINTED*/
4bff34e37def8a90f9194d81bc345c52ba20086athurlow hdr = (uint32_t *)nbp->nbp_frag->b_rptr;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow len = ntohl(*hdr);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if ((len >> 16) & 0xFE) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow NBDEBUG("bad nb header received 0x%x (MBZ flag set)\n", len);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (EPIPE);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *rpcodep = (len >> 24) & 0xFF;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow switch (*rpcodep) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow case NB_SSN_MESSAGE:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow case NB_SSN_REQUEST:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow case NB_SSN_POSRESP:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow case NB_SSN_NEGRESP:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow case NB_SSN_RTGRESP:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow case NB_SSN_KEEPALIVE:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow default:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow NBDEBUG("bad nb header received 0x%x (bogus type)\n", len);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (EPIPE);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow len &= 0x1ffff;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (len > NB_MAXPKTLEN) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow NBDEBUG("packet too long (%d)\n", len);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (EFBIG);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *lenp = len;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (0);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow/*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Receive a NetBIOS message. This may block to wait for the entire
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * message to arrive. The caller knows there is (or should be) a
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * message to be read. When we receive and drop a keepalive or
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * zero-length message, return EAGAIN so the caller knows that
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * something was received. This avoids false triggering of the
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * "server not responding" state machine.
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross *
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross * Calls to this are serialized at a higher level.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlowstatic int
4bff34e37def8a90f9194d81bc345c52ba20086athurlownbssn_recv(struct nbpcb *nbp, mblk_t **mpp, int *lenp,
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross uint8_t *rpcodep)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mblk_t *m0;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow uint8_t rpcode;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow int error;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow size_t rlen, len;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /* We should be the only reader. */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow ASSERT(nbp->nbp_flags & NBF_RECVLOCK);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross if (nbp->nbp_tiptr == NULL)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (EBADF);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (mpp) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (*mpp) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow NBDEBUG("*mpp not 0 - leak?");
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *mpp = NULL;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow m0 = NULL;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Get the NetBIOS header (not consumed yet)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = nbssn_peekhdr(nbp, &len, &rpcode);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error != ETIME)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow NBDEBUG("peekhdr, error=%d\n", error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow NBDEBUG("Have pkt, type=0x%x len=0x%x\n",
4bff34e37def8a90f9194d81bc345c52ba20086athurlow (int)rpcode, (int)len);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Block here waiting for the whole packet to arrive.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * If we get a timeout, return without side effects.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * The data length we wait for here includes both the
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * NetBIOS header and the payload.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = nb_getmsg_mlen(nbp, &nbp->nbp_frag, len + 4);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow NBDEBUG("getmsg(body), error=%d\n", error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * We now have an entire NetBIOS message.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Trim off the NetBIOS header and consume it.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Note: _peekhdr has done pullupmsg for us,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * so we know it's safe to advance b_rptr.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow m0 = nbp->nbp_frag;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow m0->b_rptr += 4;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * There may be more data after the message
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * we're about to return, in which case we
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * split it and leave the remainder.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow rlen = msgdsize(m0);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow ASSERT(rlen >= len);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow nbp->nbp_frag = NULL;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (rlen > len)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow nbp->nbp_frag = m_split(m0, len, 1);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (nbp->nbp_state != NBST_SESSION) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * No session is established.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Return whatever packet we got.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow goto out;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * A session is established; the only packets
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * we should see are session message and
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * keep-alive packets. Drop anything else.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow switch (rpcode) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow case NB_SSN_KEEPALIVE:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * It's a keepalive. Discard any data in it
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * (there's not supposed to be any, but that
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * doesn't mean some server won't send some)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (len)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow NBDEBUG("Keepalive with data %d\n", (int)len);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = EAGAIN;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow case NB_SSN_MESSAGE:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Session message. Does it have any data?
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (len == 0) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * No data - treat as keepalive (drop).
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = EAGAIN;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Yes, has data. Return it.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = 0;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow default:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Drop anything else.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow NBDEBUG("non-session packet %x\n", rpcode);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = EAGAIN;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlowout:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (error) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (m0)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow m_freem(m0);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (mpp)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *mpp = m0;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow else
4bff34e37def8a90f9194d81bc345c52ba20086athurlow m_freem(m0);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *lenp = (int)len;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *rpcodep = rpcode;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (0);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow/*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * SMB transport interface
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross *
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross * This is called only by the thread creating this endpoint,
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross * so we're single-threaded here.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross/*ARGSUSED*/
4bff34e37def8a90f9194d81bc345c52ba20086athurlowstatic int
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rosssmb_nbst_create(struct smb_vc *vcp, cred_t *cr)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct nbpcb *nbp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow nbp = kmem_zalloc(sizeof (struct nbpcb), KM_SLEEP);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow nbp->nbp_timo.tv_sec = SMB_NBTIMO;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow nbp->nbp_state = NBST_CLOSED; /* really IDLE */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow nbp->nbp_vc = vcp;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow nbp->nbp_sndbuf = smb_tcpsndbuf;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow nbp->nbp_rcvbuf = smb_tcprcvbuf;
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross nbp->nbp_cred = cr;
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross crhold(cr);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mutex_init(&nbp->nbp_lock, NULL, MUTEX_DRIVER, NULL);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_tdata = nbp;
6723e17f4e092e7f275f0791f9fce3ea061339d7Gordon Ross
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (0);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross/*
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross * destroy a transport endpoint
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross *
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross * This is called only by the thread with the last reference
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross * to this endpoint, so we're single-threaded here.
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross */
4bff34e37def8a90f9194d81bc345c52ba20086athurlowstatic int
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rosssmb_nbst_done(struct smb_vc *vcp)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct nbpcb *nbp = vcp->vc_tdata;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (nbp == NULL)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (ENOTCONN);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow vcp->vc_tdata = NULL;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Don't really need to disconnect here,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * because the close following will do it.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * But it's harmless.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (nbp->nbp_flags & NBF_CONNECTED)
02d09e03eb27f3a2dc299de704e45dae5173f43fGordon Ross (void) nb_disconnect(nbp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (nbp->nbp_tiptr)
02d09e03eb27f3a2dc299de704e45dae5173f43fGordon Ross (void) t_kclose(nbp->nbp_tiptr, 0);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (nbp->nbp_laddr)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_free_sockaddr((struct sockaddr *)nbp->nbp_laddr);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (nbp->nbp_paddr)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_free_sockaddr((struct sockaddr *)nbp->nbp_paddr);
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross if (nbp->nbp_cred)
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross crfree(nbp->nbp_cred);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mutex_destroy(&nbp->nbp_lock);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow kmem_free(nbp, sizeof (*nbp));
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (0);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross/*
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross * Loan a transport file pointer (from user space) to this
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross * IOD endpoint. There should be no other thread using this
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross * endpoint when we do this, but lock for consistency.
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross */
4bff34e37def8a90f9194d81bc345c52ba20086athurlowstatic int
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Rossnb_loan_fp(struct nbpcb *nbp, struct file *fp, cred_t *cr)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross TIUSER *tiptr;
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross int err;
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross err = t_kopen(fp, 0, 0, &tiptr, cr);
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross if (err != 0)
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross return (err);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross mutex_enter(&nbp->nbp_lock);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross nbp->nbp_tiptr = tiptr;
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross nbp->nbp_fmode = tiptr->fp->f_flag;
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross nbp->nbp_flags |= NBF_CONNECTED;
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross nbp->nbp_state = NBST_SESSION;
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross mutex_exit(&nbp->nbp_lock);
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross return (0);
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross}
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross/*
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross * Take back the transport file pointer we previously loaned.
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross * It's possible there may be another thread in here, so let
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross * others get out of the way before we pull the rug out.
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross *
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross * Some notes about the locking here: The higher-level IOD code
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross * serializes activity such that at most one reader and writer
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross * thread can be active in this code (and possibly both).
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross * Keeping nbp_lock held during the activities of these two
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross * threads would lead to the possibility of nbp_lock being
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross * held by a blocked thread, so this instead sets one of the
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross * flags (NBF_SENDLOCK | NBF_RECVLOCK) when a sender or a
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross * receiver is active (respectively). Lastly, tear-down is
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross * the only tricky bit (here) where we must wait for any of
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross * these activities to get out of current calls so they will
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross * notice that we've turned off the NBF_CONNECTED flag.
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross */
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Rossstatic void
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Rossnb_unloan_fp(struct nbpcb *nbp)
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross{
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross mutex_enter(&nbp->nbp_lock);
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross nbp->nbp_flags &= ~NBF_CONNECTED;
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross while (nbp->nbp_flags & (NBF_SENDLOCK | NBF_RECVLOCK)) {
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross nbp->nbp_flags |= NBF_LOCKWAIT;
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross cv_wait(&nbp->nbp_cv, &nbp->nbp_lock);
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross }
3ce9ce383e93f64f4baed13c5a0a28d7a5f1b71eBayard Bell if (nbp->nbp_frag != NULL) {
3ce9ce383e93f64f4baed13c5a0a28d7a5f1b71eBayard Bell freemsg(nbp->nbp_frag);
3ce9ce383e93f64f4baed13c5a0a28d7a5f1b71eBayard Bell nbp->nbp_frag = NULL;
3ce9ce383e93f64f4baed13c5a0a28d7a5f1b71eBayard Bell }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (nbp->nbp_tiptr != NULL) {
02d09e03eb27f3a2dc299de704e45dae5173f43fGordon Ross (void) t_kclose(nbp->nbp_tiptr, 0);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross nbp->nbp_tiptr = NULL;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross nbp->nbp_state = NBST_CLOSED;
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross mutex_exit(&nbp->nbp_lock);
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross}
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Rossstatic int
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Rosssmb_nbst_loan_fp(struct smb_vc *vcp, struct file *fp, cred_t *cr)
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross{
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross struct nbpcb *nbp = vcp->vc_tdata;
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross int error = 0;
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross /*
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross * Un-loan the existing one, if any.
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross */
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross (void) nb_disconnect(nbp);
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross nb_unloan_fp(nbp);
7962806f7d687e6068b5eaf4397dfb03a8d7383bGordon Ross
7962806f7d687e6068b5eaf4397dfb03a8d7383bGordon Ross /*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * Loan the new one passed in.
7962806f7d687e6068b5eaf4397dfb03a8d7383bGordon Ross */
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross if (fp != NULL) {
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross error = nb_loan_fp(nbp, fp, cr);
7962806f7d687e6068b5eaf4397dfb03a8d7383bGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross/*ARGSUSED*/
4bff34e37def8a90f9194d81bc345c52ba20086athurlowstatic int
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rosssmb_nbst_bind(struct smb_vc *vcp, struct sockaddr *sap)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return (ENOTSUP);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross/*ARGSUSED*/
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossstatic int
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rosssmb_nbst_connect(struct smb_vc *vcp, struct sockaddr *sap)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross{
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return (ENOTSUP);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow/*ARGSUSED*/
4bff34e37def8a90f9194d81bc345c52ba20086athurlowstatic int
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rosssmb_nbst_disconnect(struct smb_vc *vcp)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct nbpcb *nbp = vcp->vc_tdata;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (nbp == NULL)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (ENOTCONN);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (nb_disconnect(nbp));
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlowstatic int
4bff34e37def8a90f9194d81bc345c52ba20086athurlownb_disconnect(struct nbpcb *nbp)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
02d09e03eb27f3a2dc299de704e45dae5173f43fGordon Ross int err = 0;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mutex_enter(&nbp->nbp_lock);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross if ((nbp->nbp_flags & NBF_CONNECTED) != 0) {
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross nbp->nbp_flags &= ~NBF_CONNECTED;
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross err = nb_snddis(nbp);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
02d09e03eb27f3a2dc299de704e45dae5173f43fGordon Ross
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross mutex_exit(&nbp->nbp_lock);
02d09e03eb27f3a2dc299de704e45dae5173f43fGordon Ross return (err);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow/*
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross * Add the NetBIOS session header and send.
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross *
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross * Calls to this are serialized at a higher level.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlowstatic int
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Rossnbssn_send(struct nbpcb *nbp, mblk_t *m)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow ptrdiff_t diff;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow uint32_t mlen;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow int error;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross /* We should be the only sender. */
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross ASSERT(nbp->nbp_flags & NBF_SENDLOCK);
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross if (nbp->nbp_tiptr == NULL) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = EBADF;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow goto errout;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Get the message length, which
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * does NOT include the NetBIOS header
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mlen = msgdsize(m);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Normally, mb_init() will have left space
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * for us to prepend the NetBIOS header in
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * the data block of the first mblk.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * However, we have to check in case other
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * code did not leave this space, or if the
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * message is from dupmsg (db_ref > 1)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * If don't find room in the first data block,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * we have to allocb a new message and link it
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * on the front of the chain. We try not to
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * do this becuase it's less efficient. Also,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * some network drivers will apparently send
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * each mblk in the chain as separate frames.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * (That's arguably a driver bug.)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross *
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * Not bothering with allocb_cred_wait below
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * because the message we're prepending to
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * should already have a db_credp.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow diff = MBLKHEAD(m);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (diff == 4 && DB_REF(m) == 1) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /* We can use the first dblk. */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow m->b_rptr -= 4;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow } else {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /* Link a new mblk on the head. */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mblk_t *m0;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /* M_PREPEND */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow m0 = allocb_wait(4, BPRI_LO, STR_NOSIG, &error);
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross if (m0 == NULL)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow goto errout;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow m0->b_wptr += 4;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow m0->b_cont = m;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow m = m0;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow nb_sethdr(m, NB_SSN_MESSAGE, mlen);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow error = tli_send(nbp->nbp_tiptr, m, 0);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlowerrout:
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross if (m != NULL)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow m_freem(m);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (error);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross/*
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross * Always consume the message.
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross * (On error too!)
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross */
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Rossstatic int
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Rosssmb_nbst_send(struct smb_vc *vcp, mblk_t *m)
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross{
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross struct nbpcb *nbp = vcp->vc_tdata;
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross int err;
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross mutex_enter(&nbp->nbp_lock);
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross if ((nbp->nbp_flags & NBF_CONNECTED) == 0) {
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross err = ENOTCONN;
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross goto out;
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross }
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross if (nbp->nbp_flags & NBF_SENDLOCK) {
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross NBDEBUG("multiple smb_nbst_send!\n");
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross err = EWOULDBLOCK;
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross goto out;
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross }
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross nbp->nbp_flags |= NBF_SENDLOCK;
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross mutex_exit(&nbp->nbp_lock);
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross err = nbssn_send(nbp, m);
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross m = NULL; /* nbssn_send always consumes this */
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross mutex_enter(&nbp->nbp_lock);
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross nbp->nbp_flags &= ~NBF_SENDLOCK;
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross if (nbp->nbp_flags & NBF_LOCKWAIT) {
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross nbp->nbp_flags &= ~NBF_LOCKWAIT;
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross cv_broadcast(&nbp->nbp_cv);
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross }
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Rossout:
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross mutex_exit(&nbp->nbp_lock);
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross if (m != NULL)
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross m_freem(m);
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross return (err);
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross}
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross
4bff34e37def8a90f9194d81bc345c52ba20086athurlowstatic int
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rosssmb_nbst_recv(struct smb_vc *vcp, mblk_t **mpp)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct nbpcb *nbp = vcp->vc_tdata;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow uint8_t rpcode;
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross int err, rplen;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mutex_enter(&nbp->nbp_lock);
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross if ((nbp->nbp_flags & NBF_CONNECTED) == 0) {
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross err = ENOTCONN;
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross goto out;
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (nbp->nbp_flags & NBF_RECVLOCK) {
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross NBDEBUG("multiple smb_nbst_recv!\n");
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross err = EWOULDBLOCK;
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross goto out;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow nbp->nbp_flags |= NBF_RECVLOCK;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mutex_exit(&nbp->nbp_lock);
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross err = nbssn_recv(nbp, mpp, &rplen, &rpcode);
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mutex_enter(&nbp->nbp_lock);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow nbp->nbp_flags &= ~NBF_RECVLOCK;
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross if (nbp->nbp_flags & NBF_LOCKWAIT) {
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross nbp->nbp_flags &= ~NBF_LOCKWAIT;
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross cv_broadcast(&nbp->nbp_cv);
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross }
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Rossout:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow mutex_exit(&nbp->nbp_lock);
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross return (err);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow/*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Wait for up to "ticks" clock ticks for input on vcp.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Returns zero if input is available, otherwise ETIME
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * indicating time expired, or other error codes.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow/*ARGSUSED*/
4bff34e37def8a90f9194d81bc345c52ba20086athurlowstatic int
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rosssmb_nbst_poll(struct smb_vc *vcp, int ticks)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
3d804dabd641ca3bac12a320ebf63c36c6f3eba0Gordon Ross return (ENOTSUP);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlowstatic int
4bff34e37def8a90f9194d81bc345c52ba20086athurlowsmb_nbst_getparam(struct smb_vc *vcp, int param, void *data)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow struct nbpcb *nbp = vcp->vc_tdata;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow switch (param) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow case SMBTP_SNDSZ:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *(int *)data = nbp->nbp_sndbuf;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow case SMBTP_RCVSZ:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *(int *)data = nbp->nbp_rcvbuf;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow case SMBTP_TIMEOUT:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *(struct timespec *)data = nbp->nbp_timo;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#ifdef SMBTP_SELECTID
4bff34e37def8a90f9194d81bc345c52ba20086athurlow case SMBTP_SELECTID:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *(void **)data = nbp->nbp_selectid;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#endif
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#ifdef SMBTP_UPCALL
4bff34e37def8a90f9194d81bc345c52ba20086athurlow case SMBTP_UPCALL:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *(void **)data = nbp->nbp_upcall;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow break;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#endif
4bff34e37def8a90f9194d81bc345c52ba20086athurlow default:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (EINVAL);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (0);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow/*ARGSUSED*/
4bff34e37def8a90f9194d81bc345c52ba20086athurlowstatic int
4bff34e37def8a90f9194d81bc345c52ba20086athurlowsmb_nbst_setparam(struct smb_vc *vcp, int param, void *data)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (EINVAL);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow/*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Check for fatal errors
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow/*ARGSUSED*/
4bff34e37def8a90f9194d81bc345c52ba20086athurlowstatic int
4bff34e37def8a90f9194d81bc345c52ba20086athurlowsmb_nbst_fatal(struct smb_vc *vcp, int error)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow switch (error) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow case ENOTCONN:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow case ENETRESET:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow case ECONNABORTED:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow case EPIPE:
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (1);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return (0);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlowstruct smb_tran_desc smb_tran_nbtcp_desc = {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow SMBT_NBTCP,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_nbst_create,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_nbst_done,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_nbst_bind,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_nbst_connect,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_nbst_disconnect,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_nbst_send,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_nbst_recv,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_nbst_poll,
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross smb_nbst_loan_fp,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_nbst_getparam,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_nbst_setparam,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow smb_nbst_fatal,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow {NULL, NULL}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow};