4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
27 * NetBIOS session service functions
39 #include <sys/types.h>
40 #include <sys/socket.h>
43 #include <netsmb/netbios.h>
44 #include <netsmb/smb_lib.h>
45 #include <netsmb/nb_lib.h>
46 #include <netsmb/mchain.h>
51 static int nb_ssn_send(struct smb_ctx
*, struct mbdata
*, int, int);
52 static int nb_ssn_recv(struct smb_ctx
*, struct mbdata
*, int *, int *);
53 static int nb_ssn_pollin(struct smb_ctx
*, int);
56 * Send a data message.
59 smb_ssn_send(struct smb_ctx
*ctx
, struct mbdata
*mbp
)
61 return (nb_ssn_send(ctx
, mbp
, 0, mbp
->mb_count
));
65 * Send a NetBIOS message, after
66 * prepending the 4-byte header.
69 nb_ssn_send(struct smb_ctx
*ctx
, struct mbdata
*mbp
,
81 * Prepend the NetBIOS header.
82 * Our mbufs leave space for this.
84 hdr
= (mtype
<< 24) | mlen
;
88 bcopy(&hdrbuf
, m
->m_data
, 4);
91 * Get contiguous data (so TCP won't fragment)
92 * Note: replaces mb_top.
94 err
= m_lineup(mbp
->mb_top
, &mbp
->mb_top
);
102 if (t_snd(ctx
->ct_tran_fd
, m
->m_data
, m
->m_len
, 0) < 0) {
103 if (t_errno
== TSYSERR
)
107 DPRINT("t_snd: t_errno %d, err %d", t_errno
, err
);
115 * Receive a data message. Discard anything else.
116 * Caller must deal with EAGAIN, EINTR.
119 smb_ssn_recv(struct smb_ctx
*ctx
, struct mbdata
*mbp
)
121 int err
, mtype
, mlen
;
122 err
= nb_ssn_recv(ctx
, mbp
, &mtype
, &mlen
);
125 if (mtype
!= NB_SSN_MESSAGE
) {
126 DPRINT("discard type 0x%x", mtype
);
131 DPRINT("zero length");
140 * Receive a NetBIOS message, any type.
141 * Give caller type and length.
144 nb_ssn_recv(struct smb_ctx
*ctx
, struct mbdata
*mb
,
145 int *mtype
, int *mlen
)
148 uint32_t hdr
, hdrbuf
;
149 int cnt
, len
, err
, moreflag
;
150 int fd
= ctx
->ct_tran_fd
;
151 int tmo
= smb_recv_timeout
* 1000;
154 * Start by getting the header
157 if ((err
= nb_ssn_pollin(ctx
, tmo
)) != 0) {
158 DPRINT("pollin err %d", err
);
162 cnt
= t_rcv(fd
, &hdrbuf
, sizeof (hdrbuf
), &moreflag
);
164 err
= get_xti_err(fd
);
165 DPRINT("t_errno %d err %d", t_errno
, err
);
169 if (cnt
!= sizeof (hdrbuf
)) {
170 DPRINT("hdr cnt %d", cnt
);
175 * Decode the header, get the length.
178 *mtype
= (hdr
>> 24) & 0xff;
179 *mlen
= hdr
& 0xffffff;
185 * Get a message buffer, read the payload
187 if ((err
= mb_init_sz(mb
, *mlen
)) != 0)
189 buf
= mb
->mb_top
->m_data
;
193 if ((err
= nb_ssn_pollin(ctx
, tmo
)) != 0) {
194 DPRINT("pollin err %d", err
);
200 cnt
= t_rcv(fd
, buf
, len
, &moreflag
);
202 err
= get_xti_err(fd
);
203 DPRINT("t_errno %d err %d", t_errno
, err
);
209 mb
->mb_top
->m_len
= *mlen
;
210 mb
->mb_count
= *mlen
;
219 if (t_errno
== TSYSERR
)
222 if (t_errno
== TLOOK
) {
226 (void) t_rcvdis(fd
, NULL
);
227 (void) t_snddis(fd
, NULL
);
230 /* Received orderly release indication */
232 /* Send orderly release indicator */
241 * Wait for data we can receive.
242 * Timeout is mSec., as for poll(2)
245 nb_ssn_pollin(struct smb_ctx
*ctx
, int tmo
)
247 struct pollfd pfd
[1];
250 pfd
[0].fd
= ctx
->ct_tran_fd
;
251 pfd
[0].events
= POLLIN
| POLLPRI
;
253 cnt
= poll(pfd
, 1, tmo
);
269 * Send a NetBIOS session request and
270 * wait for the response.
273 nb_ssn_request(struct smb_ctx
*ctx
, char *srvname
)
275 struct mbdata req
, res
;
276 struct nb_name lcl
, srv
;
277 int err
, mtype
, mlen
;
280 bzero(&req
, sizeof (req
));
281 bzero(&res
, sizeof (res
));
283 if ((err
= mb_init(&req
)) != 0)
286 ucwks
= utf8_str_toupper(ctx
->ct_locname
);
293 snprintf(lcl
.nn_name
, NB_NAMELEN
, "%-15.15s", ucwks
);
294 lcl
.nn_type
= NBT_WKSTA
;
295 lcl
.nn_scope
= ctx
->ct_nb
->nb_scope
;
298 snprintf(srv
.nn_name
, NB_NAMELEN
, "%-15.15s", srvname
);
299 srv
.nn_type
= NBT_SERVER
;
300 srv
.nn_scope
= ctx
->ct_nb
->nb_scope
;
303 * Build the request. Header is prepended later.
305 if ((err
= nb_name_encode(&req
, &srv
)) != 0)
307 if ((err
= nb_name_encode(&req
, &lcl
)) != 0)
311 * Send it, wait for the reply.
313 err
= nb_ssn_send(ctx
, &req
, NB_SSN_REQUEST
, req
.mb_count
);
315 DPRINT("send, err %d", err
);
318 err
= nb_ssn_recv(ctx
, &res
, &mtype
, &mlen
);
320 DPRINT("recv, err %d", err
);
324 if (mtype
!= NB_SSN_POSRESP
) {
325 DPRINT("recv, mtype 0x%x", mtype
);