Print this page
5133 Upstream SMB client fixes: Nexenta SUP-538 and SUP-548
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/uts/common/fs/smbclnt/netsmb/smb_trantcp.c
+++ new/usr/src/uts/common/fs/smbclnt/netsmb/smb_trantcp.c
1 1 /*
2 2 * Copyright (c) 2000-2001 Boris Popov
3 3 * All rights reserved.
4 4 *
5 5 * Redistribution and use in source and binary forms, with or without
6 6 * modification, are permitted provided that the following conditions
7 7 * are met:
8 8 * 1. Redistributions of source code must retain the above copyright
9 9 * notice, this list of conditions and the following disclaimer.
10 10 * 2. Redistributions in binary form must reproduce the above copyright
11 11 * notice, this list of conditions and the following disclaimer in the
12 12 * documentation and/or other materials provided with the distribution.
13 13 * 3. All advertising materials mentioning features or use of this software
14 14 * must display the following acknowledgement:
15 15 * This product includes software developed by Boris Popov.
16 16 * 4. Neither the name of the author nor the names of any co-contributors
17 17 * may be used to endorse or promote products derived from this software
18 18 * without specific prior written permission.
19 19 *
20 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
↓ open down ↓ |
24 lines elided |
↑ open up ↑ |
25 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 30 * SUCH DAMAGE.
31 31 *
32 32 * $Id: smb_trantcp.c,v 1.39 2005/03/02 01:27:44 lindak Exp $
33 33 */
34 34 /*
35 - * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
36 35 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
37 36 * Use is subject to license terms.
37 + * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
38 38 */
39 39
40 40 #include <sys/param.h>
41 41 #include <sys/systm.h>
42 42 #include <sys/autoconf.h>
43 43 #include <sys/sysmacros.h>
44 44 #include <sys/sunddi.h>
45 45 #include <sys/kmem.h>
46 46 #include <sys/proc.h>
47 47 #include <sys/protosw.h>
48 48 #include <sys/socket.h>
49 49 #include <sys/poll.h>
50 50 #include <sys/stream.h>
51 51 #include <sys/strsubr.h>
52 52 #include <sys/strsun.h>
53 53 #include <sys/stropts.h>
54 54 #include <sys/cmn_err.h>
55 55 #include <sys/tihdr.h>
56 56 #include <sys/tiuser.h>
57 57 #include <sys/t_kuser.h>
58 58 #include <sys/priv.h>
59 59
60 60 #include <net/if.h>
61 61 #include <net/route.h>
62 62
63 63 #include <netinet/in.h>
64 64 #include <netinet/tcp.h>
65 65
66 66 #include <netsmb/smb_osdep.h>
67 67 #include <netsmb/mchain.h>
68 68 #include <netsmb/netbios.h>
69 69
70 70 #include <netsmb/smb.h>
71 71 #include <netsmb/smb_conn.h>
72 72 #include <netsmb/smb_subr.h>
73 73 #include <netsmb/smb_tran.h>
74 74 #include <netsmb/smb_trantcp.h>
75 75
76 76 /*
77 77 * SMB messages are up to 64K.
78 78 * Let's leave room for two.
79 79 */
80 80 static int smb_tcpsndbuf = 0x20000;
81 81 static int smb_tcprcvbuf = 0x20000;
82 82
83 83 static int nb_disconnect(struct nbpcb *nbp);
84 84
85 85
86 86 /*
87 87 * Get mblks into *mpp until the data length is at least mlen.
88 88 * Note that *mpp may already contain a fragment.
89 89 *
90 90 * If we ever have to wait more than 15 sec. to read a message,
91 91 * return ETIME. (Caller will declare the VD dead.)
92 92 */
93 93 static int
94 94 nb_getmsg_mlen(struct nbpcb *nbp, mblk_t **mpp, size_t mlen)
95 95 {
96 96 mblk_t *im, *tm;
97 97 union T_primitives *pptr;
98 98 size_t dlen;
99 99 int events, fmode, timo, waitflg;
100 100 int error = 0;
101 101
102 102 /* We should be the only reader. */
103 103 ASSERT(nbp->nbp_flags & NBF_RECVLOCK);
104 104 /* nbp->nbp_tiptr checked by caller */
105 105
106 106 /*
107 107 * Get the first message (fragment) if
108 108 * we don't already have a left-over.
109 109 */
110 110 dlen = msgdsize(*mpp); /* *mpp==null is OK */
111 111 while (dlen < mlen) {
112 112
113 113 /*
114 114 * I think we still want this to return ETIME
115 115 * if nothing arrives for SMB_NBTIMO (15) sec.
116 116 * so we can report "server not responding".
117 117 * We _could_ just block here now that our
118 118 * IOD is just a reader.
119 119 */
120 120 #if 1
121 121 /* Wait with timeout... */
122 122 events = 0;
123 123 waitflg = READWAIT;
124 124 timo = SEC_TO_TICK(SMB_NBTIMO);
125 125 error = t_kspoll(nbp->nbp_tiptr, timo, waitflg, &events);
126 126 if (!error && !events)
127 127 error = ETIME;
128 128 if (error)
129 129 break;
130 130 /* file mode for recv is: */
131 131 fmode = FNDELAY; /* non-blocking */
132 132 #else
133 133 fmode = 0; /* normal (blocking) */
134 134 #endif
135 135
136 136 /* Get some more... */
137 137 tm = NULL;
138 138 error = tli_recv(nbp->nbp_tiptr, &tm, fmode);
139 139 if (error == EAGAIN)
140 140 continue;
141 141 if (error)
142 142 break;
143 143
144 144 /*
145 145 * Normally get M_DATA messages here,
146 146 * but have to check for other types.
147 147 */
148 148 switch (tm->b_datap->db_type) {
149 149 case M_DATA:
150 150 break;
151 151 case M_PROTO:
152 152 case M_PCPROTO:
153 153 /*LINTED*/
154 154 pptr = (union T_primitives *)tm->b_rptr;
155 155 switch (pptr->type) {
156 156 case T_DATA_IND:
157 157 /* remove 1st mblk, keep the rest. */
158 158 im = tm->b_cont;
159 159 tm->b_cont = NULL;
160 160 freeb(tm);
161 161 tm = im;
162 162 break;
163 163 case T_DISCON_IND:
164 164 /* Peer disconnected. */
165 165 NBDEBUG("T_DISCON_IND: reason=%d",
166 166 pptr->discon_ind.DISCON_reason);
167 167 goto discon;
168 168 case T_ORDREL_IND:
169 169 /* Peer disconnecting. */
170 170 NBDEBUG("T_ORDREL_IND");
171 171 goto discon;
172 172 case T_OK_ACK:
173 173 switch (pptr->ok_ack.CORRECT_prim) {
174 174 case T_DISCON_REQ:
175 175 NBDEBUG("T_OK_ACK/T_DISCON_REQ");
176 176 goto discon;
177 177 default:
178 178 NBDEBUG("T_OK_ACK/prim=%d",
179 179 pptr->ok_ack.CORRECT_prim);
180 180 goto discon;
181 181 }
182 182 default:
183 183 NBDEBUG("M_PROTO/type=%d", pptr->type);
184 184 goto discon;
185 185 }
186 186 break; /* M_PROTO, M_PCPROTO */
187 187
188 188 default:
189 189 NBDEBUG("unexpected msg type=%d",
190 190 tm->b_datap->db_type);
191 191 /*FALLTHROUGH*/
192 192 discon:
193 193 /*
194 194 * The connection is no longer usable.
195 195 * Drop this message and disconnect.
196 196 *
197 197 * Note: nb_disconnect only does t_snddis
198 198 * on the first call, but does important
199 199 * cleanup and state change on any call.
200 200 */
201 201 freemsg(tm);
202 202 (void) nb_disconnect(nbp);
203 203 return (ENOTCONN);
204 204 }
205 205
206 206 /*
207 207 * If we have a data message, append it to
208 208 * the previous chunk(s) and update dlen
209 209 */
210 210 if (!tm)
211 211 continue;
212 212 if (*mpp == NULL) {
213 213 *mpp = tm;
214 214 } else {
215 215 /* Append */
216 216 for (im = *mpp; im->b_cont; im = im->b_cont)
217 217 ;
218 218 im->b_cont = tm;
219 219 }
220 220 dlen += msgdsize(tm);
221 221 }
222 222
223 223 return (error);
224 224 }
225 225
226 226 /*
227 227 * Send a T_DISCON_REQ (disconnect)
228 228 */
229 229 static int
230 230 nb_snddis(struct nbpcb *nbp)
231 231 {
232 232 TIUSER *tiptr = nbp->nbp_tiptr;
233 233 cred_t *cr = nbp->nbp_cred;
234 234 mblk_t *mp;
235 235 struct T_discon_req *dreq;
236 236 int error, mlen;
237 237
238 238 ASSERT(MUTEX_HELD(&nbp->nbp_lock));
239 239
240 240 if (tiptr == NULL)
241 241 return (EBADF);
242 242
243 243 mlen = sizeof (struct T_discon_req);
244 244 if (!(mp = allocb_cred_wait(mlen, STR_NOSIG, &error, cr, NOPID)))
245 245 return (error);
246 246
247 247 mp->b_datap->db_type = M_PROTO;
248 248 /*LINTED*/
249 249 dreq = (struct T_discon_req *)mp->b_wptr;
250 250 dreq->PRIM_type = T_DISCON_REQ;
251 251 dreq->SEQ_number = -1;
252 252 mp->b_wptr += sizeof (struct T_discon_req);
253 253
254 254 error = tli_send(tiptr, mp, tiptr->fp->f_flag);
255 255 /*
256 256 * There is an OK/ACK response expected, which is
257 257 * either handled by our receiver thread, or just
258 258 * discarded if we're closing this endpoint.
259 259 */
260 260
261 261 return (error);
262 262 }
263 263
264 264 /*
265 265 * Stuff the NetBIOS header into space already prepended.
266 266 */
267 267 static void
268 268 nb_sethdr(mblk_t *m, uint8_t type, uint32_t len)
269 269 {
270 270 uint32_t *p;
271 271
272 272 len &= 0x1FFFF;
273 273 len |= (type << 24);
274 274
275 275 /*LINTED*/
276 276 p = (uint32_t *)m->b_rptr;
277 277 *p = htonl(len);
278 278 }
279 279
280 280 /*
281 281 * Wait for up to 15 sec. for the next packet.
282 282 * Often return ETIME and do nothing else.
283 283 * When a packet header is available, check
284 284 * the header and get the length, but don't
285 285 * consume it. No side effects here except
286 286 * for the pullupmsg call.
287 287 */
288 288 static int
289 289 nbssn_peekhdr(struct nbpcb *nbp, size_t *lenp, uint8_t *rpcodep)
290 290 {
291 291 uint32_t len, *hdr;
292 292 int error;
293 293
294 294 /*
295 295 * Get the first message (fragment) if
296 296 * we don't already have a left-over.
297 297 */
298 298 error = nb_getmsg_mlen(nbp, &nbp->nbp_frag, sizeof (len));
299 299 if (error)
300 300 return (error);
301 301
302 302 if (!pullupmsg(nbp->nbp_frag, sizeof (len)))
303 303 return (ENOSR);
304 304
305 305 /*
306 306 * Check the NetBIOS header.
307 307 * (NOT consumed here)
308 308 */
309 309 /*LINTED*/
310 310 hdr = (uint32_t *)nbp->nbp_frag->b_rptr;
311 311
312 312 len = ntohl(*hdr);
313 313 if ((len >> 16) & 0xFE) {
314 314 NBDEBUG("bad nb header received 0x%x (MBZ flag set)\n", len);
315 315 return (EPIPE);
316 316 }
317 317 *rpcodep = (len >> 24) & 0xFF;
318 318 switch (*rpcodep) {
319 319 case NB_SSN_MESSAGE:
320 320 case NB_SSN_REQUEST:
321 321 case NB_SSN_POSRESP:
322 322 case NB_SSN_NEGRESP:
323 323 case NB_SSN_RTGRESP:
324 324 case NB_SSN_KEEPALIVE:
325 325 break;
326 326 default:
327 327 NBDEBUG("bad nb header received 0x%x (bogus type)\n", len);
328 328 return (EPIPE);
329 329 }
330 330 len &= 0x1ffff;
331 331 if (len > NB_MAXPKTLEN) {
332 332 NBDEBUG("packet too long (%d)\n", len);
333 333 return (EFBIG);
334 334 }
335 335 *lenp = len;
336 336 return (0);
337 337 }
338 338
339 339 /*
340 340 * Receive a NetBIOS message. This may block to wait for the entire
341 341 * message to arrive. The caller knows there is (or should be) a
342 342 * message to be read. When we receive and drop a keepalive or
343 343 * zero-length message, return EAGAIN so the caller knows that
344 344 * something was received. This avoids false triggering of the
345 345 * "server not responding" state machine.
346 346 *
347 347 * Calls to this are serialized at a higher level.
348 348 */
349 349 static int
350 350 nbssn_recv(struct nbpcb *nbp, mblk_t **mpp, int *lenp,
351 351 uint8_t *rpcodep)
352 352 {
353 353 mblk_t *m0;
354 354 uint8_t rpcode;
355 355 int error;
356 356 size_t rlen, len;
357 357
358 358 /* We should be the only reader. */
359 359 ASSERT(nbp->nbp_flags & NBF_RECVLOCK);
360 360
361 361 if (nbp->nbp_tiptr == NULL)
362 362 return (EBADF);
363 363 if (mpp) {
364 364 if (*mpp) {
365 365 NBDEBUG("*mpp not 0 - leak?");
366 366 }
367 367 *mpp = NULL;
368 368 }
369 369 m0 = NULL;
370 370
371 371 /*
372 372 * Get the NetBIOS header (not consumed yet)
373 373 */
374 374 error = nbssn_peekhdr(nbp, &len, &rpcode);
375 375 if (error) {
376 376 if (error != ETIME)
377 377 NBDEBUG("peekhdr, error=%d\n", error);
378 378 return (error);
379 379 }
380 380 NBDEBUG("Have pkt, type=0x%x len=0x%x\n",
381 381 (int)rpcode, (int)len);
382 382
383 383 /*
384 384 * Block here waiting for the whole packet to arrive.
385 385 * If we get a timeout, return without side effects.
386 386 * The data length we wait for here includes both the
387 387 * NetBIOS header and the payload.
388 388 */
389 389 error = nb_getmsg_mlen(nbp, &nbp->nbp_frag, len + 4);
390 390 if (error) {
391 391 NBDEBUG("getmsg(body), error=%d\n", error);
392 392 return (error);
393 393 }
394 394
395 395 /*
396 396 * We now have an entire NetBIOS message.
397 397 * Trim off the NetBIOS header and consume it.
398 398 * Note: _peekhdr has done pullupmsg for us,
399 399 * so we know it's safe to advance b_rptr.
400 400 */
401 401 m0 = nbp->nbp_frag;
402 402 m0->b_rptr += 4;
403 403
404 404 /*
405 405 * There may be more data after the message
406 406 * we're about to return, in which case we
407 407 * split it and leave the remainder.
408 408 */
409 409 rlen = msgdsize(m0);
410 410 ASSERT(rlen >= len);
411 411 nbp->nbp_frag = NULL;
412 412 if (rlen > len)
413 413 nbp->nbp_frag = m_split(m0, len, 1);
414 414
415 415 if (nbp->nbp_state != NBST_SESSION) {
416 416 /*
417 417 * No session is established.
418 418 * Return whatever packet we got.
419 419 */
420 420 goto out;
421 421 }
422 422
423 423 /*
424 424 * A session is established; the only packets
425 425 * we should see are session message and
426 426 * keep-alive packets. Drop anything else.
427 427 */
428 428 switch (rpcode) {
429 429
430 430 case NB_SSN_KEEPALIVE:
431 431 /*
432 432 * It's a keepalive. Discard any data in it
433 433 * (there's not supposed to be any, but that
434 434 * doesn't mean some server won't send some)
435 435 */
436 436 if (len)
437 437 NBDEBUG("Keepalive with data %d\n", (int)len);
438 438 error = EAGAIN;
439 439 break;
440 440
441 441 case NB_SSN_MESSAGE:
442 442 /*
443 443 * Session message. Does it have any data?
444 444 */
445 445 if (len == 0) {
446 446 /*
447 447 * No data - treat as keepalive (drop).
448 448 */
449 449 error = EAGAIN;
450 450 break;
451 451 }
452 452 /*
453 453 * Yes, has data. Return it.
454 454 */
455 455 error = 0;
456 456 break;
457 457
458 458 default:
459 459 /*
460 460 * Drop anything else.
461 461 */
462 462 NBDEBUG("non-session packet %x\n", rpcode);
463 463 error = EAGAIN;
464 464 break;
465 465 }
466 466
467 467 out:
468 468 if (error) {
469 469 if (m0)
470 470 m_freem(m0);
471 471 return (error);
472 472 }
473 473 if (mpp)
474 474 *mpp = m0;
475 475 else
476 476 m_freem(m0);
477 477 *lenp = (int)len;
478 478 *rpcodep = rpcode;
479 479 return (0);
480 480 }
481 481
482 482 /*
483 483 * SMB transport interface
484 484 *
485 485 * This is called only by the thread creating this endpoint,
486 486 * so we're single-threaded here.
487 487 */
488 488 /*ARGSUSED*/
489 489 static int
490 490 smb_nbst_create(struct smb_vc *vcp, cred_t *cr)
491 491 {
492 492 struct nbpcb *nbp;
493 493
494 494 nbp = kmem_zalloc(sizeof (struct nbpcb), KM_SLEEP);
495 495
496 496 nbp->nbp_timo.tv_sec = SMB_NBTIMO;
497 497 nbp->nbp_state = NBST_CLOSED; /* really IDLE */
498 498 nbp->nbp_vc = vcp;
499 499 nbp->nbp_sndbuf = smb_tcpsndbuf;
500 500 nbp->nbp_rcvbuf = smb_tcprcvbuf;
501 501 nbp->nbp_cred = cr;
502 502 crhold(cr);
503 503 mutex_init(&nbp->nbp_lock, NULL, MUTEX_DRIVER, NULL);
504 504 vcp->vc_tdata = nbp;
505 505
506 506 return (0);
507 507 }
508 508
509 509 /*
510 510 * destroy a transport endpoint
511 511 *
512 512 * This is called only by the thread with the last reference
513 513 * to this endpoint, so we're single-threaded here.
514 514 */
515 515 static int
516 516 smb_nbst_done(struct smb_vc *vcp)
517 517 {
518 518 struct nbpcb *nbp = vcp->vc_tdata;
519 519
520 520 if (nbp == NULL)
521 521 return (ENOTCONN);
522 522 vcp->vc_tdata = NULL;
523 523
524 524 /*
525 525 * Don't really need to disconnect here,
526 526 * because the close following will do it.
527 527 * But it's harmless.
528 528 */
529 529 if (nbp->nbp_flags & NBF_CONNECTED)
530 530 (void) nb_disconnect(nbp);
531 531 if (nbp->nbp_tiptr)
532 532 (void) t_kclose(nbp->nbp_tiptr, 0);
533 533 if (nbp->nbp_laddr)
534 534 smb_free_sockaddr((struct sockaddr *)nbp->nbp_laddr);
535 535 if (nbp->nbp_paddr)
536 536 smb_free_sockaddr((struct sockaddr *)nbp->nbp_paddr);
537 537 if (nbp->nbp_cred)
538 538 crfree(nbp->nbp_cred);
539 539 mutex_destroy(&nbp->nbp_lock);
540 540 kmem_free(nbp, sizeof (*nbp));
541 541 return (0);
542 542 }
543 543
544 544 /*
545 545 * Loan a transport file pointer (from user space) to this
546 546 * IOD endpoint. There should be no other thread using this
547 547 * endpoint when we do this, but lock for consistency.
548 548 */
549 549 static int
550 550 nb_loan_fp(struct nbpcb *nbp, struct file *fp, cred_t *cr)
551 551 {
552 552 TIUSER *tiptr;
553 553 int err;
554 554
555 555 err = t_kopen(fp, 0, 0, &tiptr, cr);
556 556 if (err != 0)
557 557 return (err);
558 558
559 559 mutex_enter(&nbp->nbp_lock);
560 560
561 561 nbp->nbp_tiptr = tiptr;
562 562 nbp->nbp_fmode = tiptr->fp->f_flag;
563 563 nbp->nbp_flags |= NBF_CONNECTED;
564 564 nbp->nbp_state = NBST_SESSION;
565 565
566 566 mutex_exit(&nbp->nbp_lock);
567 567
568 568 return (0);
569 569 }
570 570
571 571 /*
572 572 * Take back the transport file pointer we previously loaned.
573 573 * It's possible there may be another thread in here, so let
574 574 * others get out of the way before we pull the rug out.
575 575 *
576 576 * Some notes about the locking here: The higher-level IOD code
577 577 * serializes activity such that at most one reader and writer
578 578 * thread can be active in this code (and possibly both).
579 579 * Keeping nbp_lock held during the activities of these two
580 580 * threads would lead to the possibility of nbp_lock being
581 581 * held by a blocked thread, so this instead sets one of the
582 582 * flags (NBF_SENDLOCK | NBF_RECVLOCK) when a sender or a
583 583 * receiver is active (respectively). Lastly, tear-down is
584 584 * the only tricky bit (here) where we must wait for any of
585 585 * these activities to get out of current calls so they will
586 586 * notice that we've turned off the NBF_CONNECTED flag.
587 587 */
588 588 static void
|
↓ open down ↓ |
541 lines elided |
↑ open up ↑ |
589 589 nb_unloan_fp(struct nbpcb *nbp)
590 590 {
591 591
592 592 mutex_enter(&nbp->nbp_lock);
593 593
594 594 nbp->nbp_flags &= ~NBF_CONNECTED;
595 595 while (nbp->nbp_flags & (NBF_SENDLOCK | NBF_RECVLOCK)) {
596 596 nbp->nbp_flags |= NBF_LOCKWAIT;
597 597 cv_wait(&nbp->nbp_cv, &nbp->nbp_lock);
598 598 }
599 -
599 + if (nbp->nbp_frag != NULL) {
600 + freemsg(nbp->nbp_frag);
601 + nbp->nbp_frag = NULL;
602 + }
600 603 if (nbp->nbp_tiptr != NULL) {
601 604 (void) t_kclose(nbp->nbp_tiptr, 0);
602 605 nbp->nbp_tiptr = NULL;
603 606 }
604 607 nbp->nbp_state = NBST_CLOSED;
605 608
606 609 mutex_exit(&nbp->nbp_lock);
607 610 }
608 611
609 612 static int
610 613 smb_nbst_loan_fp(struct smb_vc *vcp, struct file *fp, cred_t *cr)
611 614 {
612 615 struct nbpcb *nbp = vcp->vc_tdata;
613 616 int error = 0;
614 617
615 618 /*
616 619 * Un-loan the existing one, if any.
617 620 */
618 621 (void) nb_disconnect(nbp);
619 622 nb_unloan_fp(nbp);
620 623
621 624 /*
622 625 * Loan the new one passed in.
623 626 */
624 627 if (fp != NULL) {
625 628 error = nb_loan_fp(nbp, fp, cr);
626 629 }
627 630
628 631 return (error);
629 632 }
630 633
631 634 /*ARGSUSED*/
632 635 static int
633 636 smb_nbst_bind(struct smb_vc *vcp, struct sockaddr *sap)
634 637 {
635 638 return (ENOTSUP);
636 639 }
637 640
638 641 /*ARGSUSED*/
639 642 static int
640 643 smb_nbst_connect(struct smb_vc *vcp, struct sockaddr *sap)
641 644 {
642 645 return (ENOTSUP);
643 646 }
644 647
645 648 /*ARGSUSED*/
646 649 static int
647 650 smb_nbst_disconnect(struct smb_vc *vcp)
648 651 {
649 652 struct nbpcb *nbp = vcp->vc_tdata;
650 653
651 654 if (nbp == NULL)
652 655 return (ENOTCONN);
653 656
654 657 return (nb_disconnect(nbp));
655 658 }
|
↓ open down ↓ |
46 lines elided |
↑ open up ↑ |
656 659
657 660 static int
658 661 nb_disconnect(struct nbpcb *nbp)
659 662 {
660 663 int err = 0;
661 664
662 665 mutex_enter(&nbp->nbp_lock);
663 666
664 667 if ((nbp->nbp_flags & NBF_CONNECTED) != 0) {
665 668 nbp->nbp_flags &= ~NBF_CONNECTED;
666 -
667 - if (nbp->nbp_frag != NULL) {
668 - freemsg(nbp->nbp_frag);
669 - nbp->nbp_frag = NULL;
670 - }
671 -
672 669 err = nb_snddis(nbp);
673 670 }
674 671
675 672 mutex_exit(&nbp->nbp_lock);
676 673 return (err);
677 674 }
678 675
679 676 /*
680 677 * Add the NetBIOS session header and send.
681 678 *
682 679 * Calls to this are serialized at a higher level.
683 680 */
684 681 static int
685 682 nbssn_send(struct nbpcb *nbp, mblk_t *m)
686 683 {
687 684 ptrdiff_t diff;
688 685 uint32_t mlen;
689 686 int error;
690 687
691 688 /* We should be the only sender. */
692 689 ASSERT(nbp->nbp_flags & NBF_SENDLOCK);
693 690
694 691 if (nbp->nbp_tiptr == NULL) {
695 692 error = EBADF;
696 693 goto errout;
697 694 }
698 695
699 696 /*
700 697 * Get the message length, which
701 698 * does NOT include the NetBIOS header
702 699 */
703 700 mlen = msgdsize(m);
704 701
705 702 /*
706 703 * Normally, mb_init() will have left space
707 704 * for us to prepend the NetBIOS header in
708 705 * the data block of the first mblk.
709 706 * However, we have to check in case other
710 707 * code did not leave this space, or if the
711 708 * message is from dupmsg (db_ref > 1)
712 709 *
713 710 * If don't find room in the first data block,
714 711 * we have to allocb a new message and link it
715 712 * on the front of the chain. We try not to
716 713 * do this becuase it's less efficient. Also,
717 714 * some network drivers will apparently send
718 715 * each mblk in the chain as separate frames.
719 716 * (That's arguably a driver bug.)
720 717 *
721 718 * Not bothering with allocb_cred_wait below
722 719 * because the message we're prepending to
723 720 * should already have a db_credp.
724 721 */
725 722
726 723 diff = MBLKHEAD(m);
727 724 if (diff == 4 && DB_REF(m) == 1) {
728 725 /* We can use the first dblk. */
729 726 m->b_rptr -= 4;
730 727 } else {
731 728 /* Link a new mblk on the head. */
732 729 mblk_t *m0;
733 730
734 731 /* M_PREPEND */
735 732 m0 = allocb_wait(4, BPRI_LO, STR_NOSIG, &error);
736 733 if (m0 == NULL)
737 734 goto errout;
738 735
739 736 m0->b_wptr += 4;
740 737 m0->b_cont = m;
741 738 m = m0;
742 739 }
743 740
744 741 nb_sethdr(m, NB_SSN_MESSAGE, mlen);
745 742 error = tli_send(nbp->nbp_tiptr, m, 0);
746 743 return (error);
747 744
748 745 errout:
749 746 if (m != NULL)
750 747 m_freem(m);
751 748 return (error);
752 749 }
753 750
754 751 /*
755 752 * Always consume the message.
756 753 * (On error too!)
757 754 */
758 755 static int
759 756 smb_nbst_send(struct smb_vc *vcp, mblk_t *m)
760 757 {
761 758 struct nbpcb *nbp = vcp->vc_tdata;
762 759 int err;
763 760
764 761 mutex_enter(&nbp->nbp_lock);
765 762 if ((nbp->nbp_flags & NBF_CONNECTED) == 0) {
766 763 err = ENOTCONN;
767 764 goto out;
768 765 }
769 766 if (nbp->nbp_flags & NBF_SENDLOCK) {
770 767 NBDEBUG("multiple smb_nbst_send!\n");
771 768 err = EWOULDBLOCK;
772 769 goto out;
773 770 }
774 771 nbp->nbp_flags |= NBF_SENDLOCK;
775 772 mutex_exit(&nbp->nbp_lock);
776 773
777 774 err = nbssn_send(nbp, m);
778 775 m = NULL; /* nbssn_send always consumes this */
779 776
780 777 mutex_enter(&nbp->nbp_lock);
781 778 nbp->nbp_flags &= ~NBF_SENDLOCK;
782 779 if (nbp->nbp_flags & NBF_LOCKWAIT) {
783 780 nbp->nbp_flags &= ~NBF_LOCKWAIT;
784 781 cv_broadcast(&nbp->nbp_cv);
785 782 }
786 783 out:
787 784 mutex_exit(&nbp->nbp_lock);
788 785 if (m != NULL)
789 786 m_freem(m);
790 787 return (err);
791 788 }
792 789
793 790 static int
794 791 smb_nbst_recv(struct smb_vc *vcp, mblk_t **mpp)
795 792 {
796 793 struct nbpcb *nbp = vcp->vc_tdata;
797 794 uint8_t rpcode;
798 795 int err, rplen;
799 796
800 797 mutex_enter(&nbp->nbp_lock);
801 798 if ((nbp->nbp_flags & NBF_CONNECTED) == 0) {
802 799 err = ENOTCONN;
803 800 goto out;
804 801 }
805 802 if (nbp->nbp_flags & NBF_RECVLOCK) {
806 803 NBDEBUG("multiple smb_nbst_recv!\n");
807 804 err = EWOULDBLOCK;
808 805 goto out;
809 806 }
810 807 nbp->nbp_flags |= NBF_RECVLOCK;
811 808 mutex_exit(&nbp->nbp_lock);
812 809
813 810 err = nbssn_recv(nbp, mpp, &rplen, &rpcode);
814 811
815 812 mutex_enter(&nbp->nbp_lock);
816 813 nbp->nbp_flags &= ~NBF_RECVLOCK;
817 814 if (nbp->nbp_flags & NBF_LOCKWAIT) {
818 815 nbp->nbp_flags &= ~NBF_LOCKWAIT;
819 816 cv_broadcast(&nbp->nbp_cv);
820 817 }
821 818 out:
822 819 mutex_exit(&nbp->nbp_lock);
823 820 return (err);
824 821 }
825 822
826 823 /*
827 824 * Wait for up to "ticks" clock ticks for input on vcp.
828 825 * Returns zero if input is available, otherwise ETIME
829 826 * indicating time expired, or other error codes.
830 827 */
831 828 /*ARGSUSED*/
832 829 static int
833 830 smb_nbst_poll(struct smb_vc *vcp, int ticks)
834 831 {
835 832 return (ENOTSUP);
836 833 }
837 834
838 835 static int
839 836 smb_nbst_getparam(struct smb_vc *vcp, int param, void *data)
840 837 {
841 838 struct nbpcb *nbp = vcp->vc_tdata;
842 839
843 840 switch (param) {
844 841 case SMBTP_SNDSZ:
845 842 *(int *)data = nbp->nbp_sndbuf;
846 843 break;
847 844 case SMBTP_RCVSZ:
848 845 *(int *)data = nbp->nbp_rcvbuf;
849 846 break;
850 847 case SMBTP_TIMEOUT:
851 848 *(struct timespec *)data = nbp->nbp_timo;
852 849 break;
853 850 #ifdef SMBTP_SELECTID
854 851 case SMBTP_SELECTID:
855 852 *(void **)data = nbp->nbp_selectid;
856 853 break;
857 854 #endif
858 855 #ifdef SMBTP_UPCALL
859 856 case SMBTP_UPCALL:
860 857 *(void **)data = nbp->nbp_upcall;
861 858 break;
862 859 #endif
863 860 default:
864 861 return (EINVAL);
865 862 }
866 863 return (0);
867 864 }
868 865
869 866 /*ARGSUSED*/
870 867 static int
871 868 smb_nbst_setparam(struct smb_vc *vcp, int param, void *data)
872 869 {
873 870 return (EINVAL);
874 871 }
875 872
876 873 /*
877 874 * Check for fatal errors
878 875 */
879 876 /*ARGSUSED*/
880 877 static int
881 878 smb_nbst_fatal(struct smb_vc *vcp, int error)
882 879 {
883 880 switch (error) {
884 881 case ENOTCONN:
885 882 case ENETRESET:
886 883 case ECONNABORTED:
887 884 case EPIPE:
888 885 return (1);
889 886 }
890 887 return (0);
891 888 }
892 889
893 890
894 891 struct smb_tran_desc smb_tran_nbtcp_desc = {
895 892 SMBT_NBTCP,
896 893 smb_nbst_create,
897 894 smb_nbst_done,
898 895 smb_nbst_bind,
899 896 smb_nbst_connect,
900 897 smb_nbst_disconnect,
901 898 smb_nbst_send,
902 899 smb_nbst_recv,
903 900 smb_nbst_poll,
904 901 smb_nbst_loan_fp,
905 902 smb_nbst_getparam,
906 903 smb_nbst_setparam,
907 904 smb_nbst_fatal,
908 905 {NULL, NULL}
909 906 };
|
↓ open down ↓ |
228 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX