17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
32 * $Id: smb_trantcp.c,v 1.39 2005/03/02 01:27:44 lindak Exp $
33 */
34 /*
35 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
36 * Use is subject to license terms.
37 * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
38 */
39
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/autoconf.h>
43 #include <sys/sysmacros.h>
44 #include <sys/sunddi.h>
45 #include <sys/kmem.h>
46 #include <sys/proc.h>
47 #include <sys/protosw.h>
48 #include <sys/socket.h>
49 #include <sys/poll.h>
50 #include <sys/stream.h>
51 #include <sys/strsubr.h>
52 #include <sys/strsun.h>
53 #include <sys/stropts.h>
54 #include <sys/cmn_err.h>
55 #include <sys/tihdr.h>
56 #include <sys/tiuser.h>
57 #include <sys/t_kuser.h>
58 #include <sys/priv.h>
59
60 #include <net/if.h>
61 #include <net/route.h>
62
63 #include <netinet/in.h>
64 #include <netinet/tcp.h>
65
66 #include <netsmb/smb_osdep.h>
67 #include <netsmb/mchain.h>
68 #include <netsmb/netbios.h>
69
70 #include <netsmb/smb.h>
71 #include <netsmb/smb_conn.h>
72 #include <netsmb/smb_subr.h>
73 #include <netsmb/smb_tran.h>
74 #include <netsmb/smb_trantcp.h>
75
76 /*
77 * SMB messages are up to 64K.
78 * Let's leave room for two.
79 */
80 static int smb_tcpsndbuf = 0x20000;
81 static int smb_tcprcvbuf = 0x20000;
82
83 static int nb_disconnect(struct nbpcb *nbp);
84
85
86 /*
87 * Get mblks into *mpp until the data length is at least mlen.
88 * Note that *mpp may already contain a fragment.
89 *
90 * If we ever have to wait more than 15 sec. to read a message,
91 * return ETIME. (Caller will declare the VD dead.)
92 */
93 static int
94 nb_getmsg_mlen(struct nbpcb *nbp, mblk_t **mpp, size_t mlen)
95 {
96 mblk_t *im, *tm;
97 union T_primitives *pptr;
98 size_t dlen;
99 int events, fmode, timo, waitflg;
100 int error = 0;
101
102 /* We should be the only reader. */
146 * but have to check for other types.
147 */
148 switch (tm->b_datap->db_type) {
149 case M_DATA:
150 break;
151 case M_PROTO:
152 case M_PCPROTO:
153 /*LINTED*/
154 pptr = (union T_primitives *)tm->b_rptr;
155 switch (pptr->type) {
156 case T_DATA_IND:
157 /* remove 1st mblk, keep the rest. */
158 im = tm->b_cont;
159 tm->b_cont = NULL;
160 freeb(tm);
161 tm = im;
162 break;
163 case T_DISCON_IND:
164 /* Peer disconnected. */
165 NBDEBUG("T_DISCON_IND: reason=%d",
166 pptr->discon_ind.DISCON_reason);
167 goto discon;
168 case T_ORDREL_IND:
169 /* Peer disconnecting. */
170 NBDEBUG("T_ORDREL_IND");
171 goto discon;
172 case T_OK_ACK:
173 switch (pptr->ok_ack.CORRECT_prim) {
174 case T_DISCON_REQ:
175 NBDEBUG("T_OK_ACK/T_DISCON_REQ");
176 goto discon;
177 default:
178 NBDEBUG("T_OK_ACK/prim=%d",
179 pptr->ok_ack.CORRECT_prim);
180 goto discon;
181 }
182 default:
183 NBDEBUG("M_PROTO/type=%d", pptr->type);
184 goto discon;
185 }
186 break; /* M_PROTO, M_PCPROTO */
187
188 default:
189 NBDEBUG("unexpected msg type=%d",
190 tm->b_datap->db_type);
191 /*FALLTHROUGH*/
192 discon:
193 /*
194 * The connection is no longer usable.
195 * Drop this message and disconnect.
196 *
197 * Note: nb_disconnect only does t_snddis
198 * on the first call, but does important
199 * cleanup and state change on any call.
200 */
201 freemsg(tm);
202 (void) nb_disconnect(nbp);
203 return (ENOTCONN);
468 if (error) {
469 if (m0)
470 m_freem(m0);
471 return (error);
472 }
473 if (mpp)
474 *mpp = m0;
475 else
476 m_freem(m0);
477 *lenp = (int)len;
478 *rpcodep = rpcode;
479 return (0);
480 }
481
482 /*
483 * SMB transport interface
484 *
485 * This is called only by the thread creating this endpoint,
486 * so we're single-threaded here.
487 */
488 /*ARGSUSED*/
489 static int
490 smb_nbst_create(struct smb_vc *vcp, cred_t *cr)
491 {
492 struct nbpcb *nbp;
493
494 nbp = kmem_zalloc(sizeof (struct nbpcb), KM_SLEEP);
495
496 nbp->nbp_timo.tv_sec = SMB_NBTIMO;
497 nbp->nbp_state = NBST_CLOSED; /* really IDLE */
498 nbp->nbp_vc = vcp;
499 nbp->nbp_sndbuf = smb_tcpsndbuf;
500 nbp->nbp_rcvbuf = smb_tcprcvbuf;
501 nbp->nbp_cred = cr;
502 crhold(cr);
503 mutex_init(&nbp->nbp_lock, NULL, MUTEX_DRIVER, NULL);
504 vcp->vc_tdata = nbp;
505
506 return (0);
507 }
508
509 /*
510 * destroy a transport endpoint
511 *
512 * This is called only by the thread with the last reference
513 * to this endpoint, so we're single-threaded here.
514 */
515 static int
516 smb_nbst_done(struct smb_vc *vcp)
517 {
518 struct nbpcb *nbp = vcp->vc_tdata;
519
520 if (nbp == NULL)
521 return (ENOTCONN);
522 vcp->vc_tdata = NULL;
523
524 /*
525 * Don't really need to disconnect here,
526 * because the close following will do it.
527 * But it's harmless.
528 */
529 if (nbp->nbp_flags & NBF_CONNECTED)
530 (void) nb_disconnect(nbp);
531 if (nbp->nbp_tiptr)
532 (void) t_kclose(nbp->nbp_tiptr, 0);
533 if (nbp->nbp_laddr)
534 smb_free_sockaddr((struct sockaddr *)nbp->nbp_laddr);
535 if (nbp->nbp_paddr)
536 smb_free_sockaddr((struct sockaddr *)nbp->nbp_paddr);
537 if (nbp->nbp_cred)
538 crfree(nbp->nbp_cred);
539 mutex_destroy(&nbp->nbp_lock);
540 kmem_free(nbp, sizeof (*nbp));
541 return (0);
542 }
543
544 /*
545 * Loan a transport file pointer (from user space) to this
546 * IOD endpoint. There should be no other thread using this
547 * endpoint when we do this, but lock for consistency.
548 */
549 static int
550 nb_loan_fp(struct nbpcb *nbp, struct file *fp, cred_t *cr)
551 {
552 TIUSER *tiptr;
553 int err;
554
555 err = t_kopen(fp, 0, 0, &tiptr, cr);
556 if (err != 0)
557 return (err);
558
559 mutex_enter(&nbp->nbp_lock);
560
561 nbp->nbp_tiptr = tiptr;
562 nbp->nbp_fmode = tiptr->fp->f_flag;
563 nbp->nbp_flags |= NBF_CONNECTED;
564 nbp->nbp_state = NBST_SESSION;
565
566 mutex_exit(&nbp->nbp_lock);
567
568 return (0);
569 }
570
571 /*
572 * Take back the transport file pointer we previously loaned.
573 * It's possible there may be another thread in here, so let
574 * others get out of the way before we pull the rug out.
575 *
576 * Some notes about the locking here: The higher-level IOD code
577 * serializes activity such that at most one reader and writer
578 * thread can be active in this code (and possibly both).
579 * Keeping nbp_lock held during the activities of these two
580 * threads would lead to the possibility of nbp_lock being
581 * held by a blocked thread, so this instead sets one of the
582 * flags (NBF_SENDLOCK | NBF_RECVLOCK) when a sender or a
583 * receiver is active (respectively). Lastly, tear-down is
584 * the only tricky bit (here) where we must wait for any of
585 * these activities to get out of current calls so they will
586 * notice that we've turned off the NBF_CONNECTED flag.
587 */
588 static void
589 nb_unloan_fp(struct nbpcb *nbp)
590 {
591
592 mutex_enter(&nbp->nbp_lock);
593
594 nbp->nbp_flags &= ~NBF_CONNECTED;
595 while (nbp->nbp_flags & (NBF_SENDLOCK | NBF_RECVLOCK)) {
596 nbp->nbp_flags |= NBF_LOCKWAIT;
597 cv_wait(&nbp->nbp_cv, &nbp->nbp_lock);
598 }
599 if (nbp->nbp_frag != NULL) {
600 freemsg(nbp->nbp_frag);
601 nbp->nbp_frag = NULL;
602 }
603 if (nbp->nbp_tiptr != NULL) {
604 (void) t_kclose(nbp->nbp_tiptr, 0);
605 nbp->nbp_tiptr = NULL;
606 }
607 nbp->nbp_state = NBST_CLOSED;
608
609 mutex_exit(&nbp->nbp_lock);
610 }
611
612 static int
613 smb_nbst_loan_fp(struct smb_vc *vcp, struct file *fp, cred_t *cr)
614 {
615 struct nbpcb *nbp = vcp->vc_tdata;
616 int error = 0;
617
618 /*
619 * Un-loan the existing one, if any.
620 */
621 (void) nb_disconnect(nbp);
622 nb_unloan_fp(nbp);
623
624 /*
625 * Loan the new one passed in.
626 */
627 if (fp != NULL) {
628 error = nb_loan_fp(nbp, fp, cr);
629 }
630
631 return (error);
632 }
633
634 /*ARGSUSED*/
635 static int
636 smb_nbst_bind(struct smb_vc *vcp, struct sockaddr *sap)
637 {
638 return (ENOTSUP);
639 }
640
641 /*ARGSUSED*/
642 static int
643 smb_nbst_connect(struct smb_vc *vcp, struct sockaddr *sap)
644 {
645 return (ENOTSUP);
646 }
647
648 /*ARGSUSED*/
649 static int
650 smb_nbst_disconnect(struct smb_vc *vcp)
651 {
652 struct nbpcb *nbp = vcp->vc_tdata;
653
654 if (nbp == NULL)
655 return (ENOTCONN);
656
657 return (nb_disconnect(nbp));
658 }
659
660 static int
661 nb_disconnect(struct nbpcb *nbp)
662 {
663 int err = 0;
664
665 mutex_enter(&nbp->nbp_lock);
666
667 if ((nbp->nbp_flags & NBF_CONNECTED) != 0) {
668 nbp->nbp_flags &= ~NBF_CONNECTED;
815 nbp->nbp_flags &= ~NBF_LOCKWAIT;
816 cv_broadcast(&nbp->nbp_cv);
817 }
818 out:
819 mutex_exit(&nbp->nbp_lock);
820 return (err);
821 }
822
823 /*
824 * Wait for up to "ticks" clock ticks for input on vcp.
825 * Returns zero if input is available, otherwise ETIME
826 * indicating time expired, or other error codes.
827 */
828 /*ARGSUSED*/
829 static int
830 smb_nbst_poll(struct smb_vc *vcp, int ticks)
831 {
832 return (ENOTSUP);
833 }
834
835 static int
836 smb_nbst_getparam(struct smb_vc *vcp, int param, void *data)
837 {
838 struct nbpcb *nbp = vcp->vc_tdata;
839
840 switch (param) {
841 case SMBTP_SNDSZ:
842 *(int *)data = nbp->nbp_sndbuf;
843 break;
844 case SMBTP_RCVSZ:
845 *(int *)data = nbp->nbp_rcvbuf;
846 break;
847 case SMBTP_TIMEOUT:
848 *(struct timespec *)data = nbp->nbp_timo;
849 break;
850 #ifdef SMBTP_SELECTID
851 case SMBTP_SELECTID:
852 *(void **)data = nbp->nbp_selectid;
853 break;
854 #endif
855 #ifdef SMBTP_UPCALL
856 case SMBTP_UPCALL:
857 *(void **)data = nbp->nbp_upcall;
858 break;
859 #endif
860 default:
861 return (EINVAL);
862 }
863 return (0);
864 }
865
866 /*ARGSUSED*/
867 static int
868 smb_nbst_setparam(struct smb_vc *vcp, int param, void *data)
869 {
870 return (EINVAL);
871 }
872
873 /*
874 * Check for fatal errors
875 */
876 /*ARGSUSED*/
877 static int
878 smb_nbst_fatal(struct smb_vc *vcp, int error)
879 {
880 switch (error) {
881 case ENOTCONN:
882 case ENETRESET:
883 case ECONNABORTED:
884 case EPIPE:
885 return (1);
886 }
887 return (0);
888 }
889
890
891 struct smb_tran_desc smb_tran_nbtcp_desc = {
892 SMBT_NBTCP,
893 smb_nbst_create,
894 smb_nbst_done,
895 smb_nbst_bind,
896 smb_nbst_connect,
897 smb_nbst_disconnect,
898 smb_nbst_send,
899 smb_nbst_recv,
900 smb_nbst_poll,
901 smb_nbst_loan_fp,
902 smb_nbst_getparam,
903 smb_nbst_setparam,
904 smb_nbst_fatal,
905 {NULL, NULL}
906 };
|
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
32 * $Id: smb_trantcp.c,v 1.39 2005/03/02 01:27:44 lindak Exp $
33 */
34 /*
35 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
36 * Use is subject to license terms.
37 *
38 * Copyright 2018 Nexenta Systems, Inc. All rights reserved.
39 */
40
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/autoconf.h>
44 #include <sys/sysmacros.h>
45 #include <sys/sunddi.h>
46 #include <sys/kmem.h>
47 #include <sys/proc.h>
48 #include <sys/protosw.h>
49 #include <sys/socket.h>
50 #include <sys/poll.h>
51 #include <sys/stream.h>
52 #include <sys/strsubr.h>
53 #include <sys/strsun.h>
54 #include <sys/stropts.h>
55 #include <sys/cmn_err.h>
56 #include <sys/tihdr.h>
57 #include <sys/tiuser.h>
58 #include <sys/t_kuser.h>
59 #include <sys/priv.h>
60
61 #include <net/if.h>
62 #include <net/route.h>
63
64 #include <netinet/in.h>
65 #include <netinet/tcp.h>
66
67 #include <netsmb/smb_osdep.h>
68 #include <netsmb/mchain.h>
69 #include <netsmb/netbios.h>
70
71 #include <netsmb/smb.h>
72 #include <netsmb/smb_conn.h>
73 #include <netsmb/smb_subr.h>
74 #include <netsmb/smb_tran.h>
75 #include <netsmb/smb_trantcp.h>
76
77 static int nb_disconnect(struct nbpcb *nbp);
78
79
80 /*
81 * Get mblks into *mpp until the data length is at least mlen.
82 * Note that *mpp may already contain a fragment.
83 *
84 * If we ever have to wait more than 15 sec. to read a message,
85 * return ETIME. (Caller will declare the VD dead.)
86 */
87 static int
88 nb_getmsg_mlen(struct nbpcb *nbp, mblk_t **mpp, size_t mlen)
89 {
90 mblk_t *im, *tm;
91 union T_primitives *pptr;
92 size_t dlen;
93 int events, fmode, timo, waitflg;
94 int error = 0;
95
96 /* We should be the only reader. */
140 * but have to check for other types.
141 */
142 switch (tm->b_datap->db_type) {
143 case M_DATA:
144 break;
145 case M_PROTO:
146 case M_PCPROTO:
147 /*LINTED*/
148 pptr = (union T_primitives *)tm->b_rptr;
149 switch (pptr->type) {
150 case T_DATA_IND:
151 /* remove 1st mblk, keep the rest. */
152 im = tm->b_cont;
153 tm->b_cont = NULL;
154 freeb(tm);
155 tm = im;
156 break;
157 case T_DISCON_IND:
158 /* Peer disconnected. */
159 NBDEBUG("T_DISCON_IND: reason=%d",
160 (int)pptr->discon_ind.DISCON_reason);
161 goto discon;
162 case T_ORDREL_IND:
163 /* Peer disconnecting. */
164 NBDEBUG("T_ORDREL_IND");
165 goto discon;
166 case T_OK_ACK:
167 switch (pptr->ok_ack.CORRECT_prim) {
168 case T_DISCON_REQ:
169 NBDEBUG("T_OK_ACK/T_DISCON_REQ");
170 goto discon;
171 default:
172 NBDEBUG("T_OK_ACK/prim=%d",
173 (int)pptr->ok_ack.CORRECT_prim);
174 goto discon;
175 }
176 default:
177 NBDEBUG("M_PROTO/type=%d", (int)pptr->type);
178 goto discon;
179 }
180 break; /* M_PROTO, M_PCPROTO */
181
182 default:
183 NBDEBUG("unexpected msg type=%d",
184 tm->b_datap->db_type);
185 /*FALLTHROUGH*/
186 discon:
187 /*
188 * The connection is no longer usable.
189 * Drop this message and disconnect.
190 *
191 * Note: nb_disconnect only does t_snddis
192 * on the first call, but does important
193 * cleanup and state change on any call.
194 */
195 freemsg(tm);
196 (void) nb_disconnect(nbp);
197 return (ENOTCONN);
462 if (error) {
463 if (m0)
464 m_freem(m0);
465 return (error);
466 }
467 if (mpp)
468 *mpp = m0;
469 else
470 m_freem(m0);
471 *lenp = (int)len;
472 *rpcodep = rpcode;
473 return (0);
474 }
475
476 /*
477 * SMB transport interface
478 *
479 * This is called only by the thread creating this endpoint,
480 * so we're single-threaded here.
481 */
482 static int
483 smb_nbst_create(struct smb_vc *vcp, cred_t *cr)
484 {
485 TIUSER *tiptr = NULL;
486 struct nbpcb *nbp = NULL;
487 dev_t dev;
488 int rc;
489 ushort_t fmode;
490
491 switch (vcp->vc_srvaddr.sa.sa_family) {
492 case AF_INET:
493 dev = nsmb_dev_tcp;
494 break;
495 case AF_INET6:
496 dev = nsmb_dev_tcp6;
497 break;
498 default:
499 return (EAFNOSUPPORT);
500 }
501
502 fmode = FREAD|FWRITE;
503 rc = t_kopen(NULL, dev, fmode, &tiptr, cr);
504 if (rc != 0) {
505 cmn_err(CE_NOTE, "t_kopen failed, rc=%d", rc);
506 return (rc);
507 }
508 ASSERT(tiptr != NULL);
509
510 nbp = kmem_zalloc(sizeof (struct nbpcb), KM_SLEEP);
511
512 nbp->nbp_timo.tv_sec = SMB_NBTIMO;
513 nbp->nbp_state = NBST_IDLE;
514 nbp->nbp_vc = vcp;
515 nbp->nbp_tiptr = tiptr;
516 nbp->nbp_fmode = fmode;
517 nbp->nbp_cred = cr;
518 crhold(cr);
519 mutex_init(&nbp->nbp_lock, NULL, MUTEX_DRIVER, NULL);
520
521 vcp->vc_tdata = nbp;
522
523 return (0);
524 }
525
526 /*
527 * destroy a transport endpoint
528 *
529 * This is called only by the thread with the last reference
530 * to this endpoint, so we're single-threaded here.
531 */
532 static int
533 smb_nbst_done(struct smb_vc *vcp)
534 {
535 struct nbpcb *nbp = vcp->vc_tdata;
536
537 if (nbp == NULL)
538 return (ENOTCONN);
539 vcp->vc_tdata = NULL;
540
541 /*
542 * Don't really need to disconnect here,
543 * because the close following will do it.
544 * But it's harmless.
545 */
546 if (nbp->nbp_flags & NBF_CONNECTED)
547 (void) nb_disconnect(nbp);
548 if (nbp->nbp_tiptr)
549 (void) t_kclose(nbp->nbp_tiptr, 0);
550 if (nbp->nbp_laddr)
551 smb_free_sockaddr((struct sockaddr *)nbp->nbp_laddr);
552 if (nbp->nbp_paddr)
553 smb_free_sockaddr((struct sockaddr *)nbp->nbp_paddr);
554 if (nbp->nbp_cred)
555 crfree(nbp->nbp_cred);
556 mutex_destroy(&nbp->nbp_lock);
557 kmem_free(nbp, sizeof (*nbp));
558 return (0);
559 }
560
561 static int
562 smb_nbst_bind(struct smb_vc *vcp, struct sockaddr *sap)
563 {
564 struct nbpcb *nbp = vcp->vc_tdata;
565 TIUSER *tiptr = nbp->nbp_tiptr;
566 int err;
567
568 /* Only default bind supported. */
569 if (sap != NULL)
570 return (ENOTSUP);
571
572 err = t_kbind(tiptr, NULL, NULL);
573
574 return (err);
575 }
576
577 static int
578 smb_nbst_unbind(struct smb_vc *vcp)
579 {
580 struct nbpcb *nbp = vcp->vc_tdata;
581 TIUSER *tiptr = nbp->nbp_tiptr;
582 int err;
583
584 err = t_kunbind(tiptr);
585
586 return (err);
587 }
588
589 static int
590 smb_nbst_connect(struct smb_vc *vcp, struct sockaddr *sap)
591 {
592 struct t_call call;
593 struct nbpcb *nbp = vcp->vc_tdata;
594 TIUSER *tiptr = nbp->nbp_tiptr;
595 int alen, err;
596
597 /* Need the address length */
598 switch (sap->sa_family) {
599 case AF_INET:
600 alen = sizeof (struct sockaddr_in);
601 break;
602 case AF_INET6:
603 alen = sizeof (struct sockaddr_in6);
604 break;
605 default:
606 return (EAFNOSUPPORT);
607 }
608
609 /* sockaddr goes in the "addr" netbuf */
610 bzero(&call, sizeof (call));
611 call.addr.buf = (char *)sap;
612 call.addr.len = alen;
613 call.addr.maxlen = alen;
614
615 err = t_kconnect(tiptr, &call, NULL);
616 if (err != 0)
617 return (err);
618
619 mutex_enter(&nbp->nbp_lock);
620
621 nbp->nbp_flags |= NBF_CONNECTED;
622 nbp->nbp_state = NBST_SESSION;
623
624 mutex_exit(&nbp->nbp_lock);
625
626 return (0);
627 }
628
629 static int
630 smb_nbst_disconnect(struct smb_vc *vcp)
631 {
632 struct nbpcb *nbp = vcp->vc_tdata;
633
634 if (nbp == NULL)
635 return (ENOTCONN);
636
637 return (nb_disconnect(nbp));
638 }
639
640 static int
641 nb_disconnect(struct nbpcb *nbp)
642 {
643 int err = 0;
644
645 mutex_enter(&nbp->nbp_lock);
646
647 if ((nbp->nbp_flags & NBF_CONNECTED) != 0) {
648 nbp->nbp_flags &= ~NBF_CONNECTED;
795 nbp->nbp_flags &= ~NBF_LOCKWAIT;
796 cv_broadcast(&nbp->nbp_cv);
797 }
798 out:
799 mutex_exit(&nbp->nbp_lock);
800 return (err);
801 }
802
803 /*
804 * Wait for up to "ticks" clock ticks for input on vcp.
805 * Returns zero if input is available, otherwise ETIME
806 * indicating time expired, or other error codes.
807 */
808 /*ARGSUSED*/
809 static int
810 smb_nbst_poll(struct smb_vc *vcp, int ticks)
811 {
812 return (ENOTSUP);
813 }
814
815 /*ARGSUSED*/
816 static int
817 smb_nbst_getparam(struct smb_vc *vcp, int param, void *data)
818 {
819 return (EINVAL);
820 }
821
822 static int
823 smb_nbst_setparam(struct smb_vc *vcp, int param, void *data)
824 {
825 struct t_optmgmt oreq, ores;
826 struct {
827 struct T_opthdr oh;
828 int ival;
829 } opts;
830 struct nbpcb *nbp = vcp->vc_tdata;
831 int level, name, err;
832
833 switch (param) {
834 case SMBTP_TCP_NODELAY:
835 level = IPPROTO_TCP;
836 name = TCP_NODELAY;
837 break;
838
839 case SMBTP_TCP_CON_TMO: /* int mSec */
840 level = IPPROTO_TCP;
841 name = TCP_CONN_ABORT_THRESHOLD;
842 break;
843
844 case SMBTP_KEEPALIVE: // SO_KEEPALIVE
845 case SMBTP_SNDBUF: // SO_SNDBUF
846 case SMBTP_RCVBUF: // SO_RCVBUF
847 case SMBTP_RCVTIMEO: // SO_RCVTIMEO
848 level = SOL_SOCKET;
849 name = param;
850 break;
851
852 default:
853 return (EINVAL);
854 }
855
856 /* opt header */
857 opts.oh.len = sizeof (opts);
858 opts.oh.level = level;
859 opts.oh.name = name;
860 opts.oh.status = 0;
861 opts.ival = *(int *)data;
862
863 oreq.flags = T_NEGOTIATE;
864 oreq.opt.buf = (void *)&opts;
865 oreq.opt.len = sizeof (opts);
866 oreq.opt.maxlen = oreq.opt.len;
867
868 ores.flags = 0;
869 ores.opt.buf = NULL;
870 ores.opt.len = 0;
871 ores.opt.maxlen = 0;
872
873 err = t_koptmgmt(nbp->nbp_tiptr, &oreq, &ores);
874 if (err != 0) {
875 cmn_err(CE_NOTE, "t_opgmgnt, err = %d", err);
876 return (EPROTO);
877 }
878
879 if ((ores.flags & T_SUCCESS) == 0) {
880 cmn_err(CE_NOTE, "smb_nbst_setparam: "
881 "flags 0x%x, status 0x%x",
882 (int)ores.flags, (int)opts.oh.status);
883 return (EPROTO);
884 }
885
886 return (0);
887 }
888
889 /*
890 * Check for fatal errors
891 */
892 /*ARGSUSED*/
893 static int
894 smb_nbst_fatal(struct smb_vc *vcp, int error)
895 {
896 switch (error) {
897 case ENOTCONN:
898 case ENETRESET:
899 case ECONNABORTED:
900 case EPIPE:
901 return (1);
902 }
903 return (0);
904 }
905
906
907 struct smb_tran_desc smb_tran_nbtcp_desc = {
908 SMBT_NBTCP,
909 smb_nbst_create,
910 smb_nbst_done,
911 smb_nbst_bind,
912 smb_nbst_unbind,
913 smb_nbst_connect,
914 smb_nbst_disconnect,
915 smb_nbst_send,
916 smb_nbst_recv,
917 smb_nbst_poll,
918 smb_nbst_getparam,
919 smb_nbst_setparam,
920 smb_nbst_fatal,
921 {NULL, NULL}
922 };
|