1 /* 2 * CDDL HEADER START 3 * 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. 7 * 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. 12 * 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] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2011 Nexenta Systems, Inc. All rights reserved. 23 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 24 */ 25 26 /* 27 * This module provides the interface to NDR RPC. 28 */ 29 30 #include <sys/stat.h> 31 #include <sys/door.h> 32 #include <sys/door_data.h> 33 #include <sys/uio.h> 34 #include <sys/ksynch.h> 35 #include <smbsrv/smb_kproto.h> 36 #include <smbsrv/smb_xdr.h> 37 38 #define SMB_OPIPE_ISOPEN(OPIPE) \ 39 (((OPIPE)->p_hdr.dh_magic == SMB_OPIPE_HDR_MAGIC) && \ 40 ((OPIPE)->p_hdr.dh_fid)) 41 42 extern volatile uint32_t smb_fids; 43 44 static int smb_opipe_do_open(smb_request_t *, smb_opipe_t *); 45 static char *smb_opipe_lookup(const char *); 46 static int smb_opipe_sethdr(smb_opipe_t *, uint32_t, uint32_t); 47 static int smb_opipe_exec(smb_opipe_t *); 48 static void smb_opipe_enter(smb_opipe_t *); 49 static void smb_opipe_exit(smb_opipe_t *); 50 51 static door_handle_t smb_opipe_door_hd = NULL; 52 static int smb_opipe_door_id = -1; 53 static uint64_t smb_opipe_door_ncall = 0; 54 static kmutex_t smb_opipe_door_mutex; 55 static kcondvar_t smb_opipe_door_cv; 56 57 static int smb_opipe_door_call(smb_opipe_t *); 58 static int smb_opipe_door_upcall(smb_opipe_t *); 59 60 smb_opipe_t * 61 smb_opipe_alloc(smb_server_t *sv) 62 { 63 smb_opipe_t *opipe; 64 65 opipe = kmem_cache_alloc(sv->si_cache_opipe, KM_SLEEP); 66 67 bzero(opipe, sizeof (smb_opipe_t)); 68 mutex_init(&opipe->p_mutex, NULL, MUTEX_DEFAULT, NULL); 69 cv_init(&opipe->p_cv, NULL, CV_DEFAULT, NULL); 70 opipe->p_magic = SMB_OPIPE_MAGIC; 71 opipe->p_server = sv; 72 73 smb_llist_enter(&sv->sv_opipe_list, RW_WRITER); 74 smb_llist_insert_tail(&sv->sv_opipe_list, opipe); 75 smb_llist_exit(&sv->sv_opipe_list); 76 77 return (opipe); 78 } 79 80 void 81 smb_opipe_dealloc(smb_opipe_t *opipe) 82 { 83 smb_server_t *sv; 84 85 SMB_OPIPE_VALID(opipe); 86 sv = opipe->p_server; 87 SMB_SERVER_VALID(sv); 88 89 smb_llist_enter(&sv->sv_opipe_list, RW_WRITER); 90 smb_llist_remove(&sv->sv_opipe_list, opipe); 91 smb_llist_exit(&sv->sv_opipe_list); 92 93 opipe->p_magic = (uint32_t)~SMB_OPIPE_MAGIC; 94 smb_event_destroy(opipe->p_event); 95 cv_destroy(&opipe->p_cv); 96 mutex_destroy(&opipe->p_mutex); 97 98 kmem_cache_free(sv->si_cache_opipe, opipe); 99 } 100 101 /* 102 * smb_opipe_open 103 * 104 * Open a well-known RPC named pipe. This routine should be called if 105 * a file open is requested on a share of type STYPE_IPC. 106 * If we recognize the pipe, we setup a new ofile. 107 * 108 * Returns 0 on success, Otherwise an NT status is returned to indicate 109 * an error. 110 */ 111 int 112 smb_opipe_open(smb_request_t *sr) 113 { 114 smb_arg_open_t *op = &sr->sr_open; 115 smb_ofile_t *of; 116 smb_opipe_t *opipe; 117 smb_doorhdr_t hdr; 118 smb_error_t err; 119 char *pipe_name; 120 121 if ((pipe_name = smb_opipe_lookup(op->fqi.fq_path.pn_path)) == NULL) 122 return (NT_STATUS_OBJECT_NAME_NOT_FOUND); 123 124 /* 125 * If printing is disabled, pretend spoolss does not exist. 126 */ 127 if (sr->sr_server->sv_cfg.skc_print_enable == 0 && 128 strcmp(pipe_name, "SPOOLSS") == 0) 129 return (NT_STATUS_OBJECT_NAME_NOT_FOUND); 130 131 op->create_options = 0; 132 133 of = smb_ofile_open(sr->tid_tree, NULL, sr->smb_pid, op, 134 SMB_FTYPE_MESG_PIPE, SMB_UNIQ_FID(), &err); 135 136 if (of == NULL) 137 return (err.status); 138 139 if (!smb_tree_is_connected(sr->tid_tree)) { 140 smb_ofile_close(of, 0); 141 smb_ofile_release(of); 142 return (NT_STATUS_OBJECT_NAME_NOT_FOUND); 143 } 144 145 op->dsize = 0x01000; 146 op->dattr = FILE_ATTRIBUTE_NORMAL; 147 op->ftype = SMB_FTYPE_MESG_PIPE; 148 op->action_taken = SMB_OACT_LOCK | SMB_OACT_OPENED; /* 0x8001 */ 149 op->devstate = SMB_PIPE_READMODE_MESSAGE 150 | SMB_PIPE_TYPE_MESSAGE 151 | SMB_PIPE_UNLIMITED_INSTANCES; /* 0x05ff */ 152 op->fileid = of->f_fid; 153 154 sr->smb_fid = of->f_fid; 155 sr->fid_ofile = of; 156 157 opipe = of->f_pipe; 158 smb_opipe_enter(opipe); 159 160 opipe->p_server = of->f_server; 161 opipe->p_name = pipe_name; 162 opipe->p_doorbuf = kmem_zalloc(SMB_OPIPE_DOOR_BUFSIZE, KM_SLEEP); 163 164 /* 165 * p_data points to the offset within p_doorbuf at which 166 * data will be written or read. 167 */ 168 opipe->p_data = opipe->p_doorbuf + xdr_sizeof(smb_doorhdr_xdr, &hdr); 169 170 if (smb_opipe_do_open(sr, opipe) != 0) { 171 /* 172 * On error, reset the header to clear the fid, 173 * which avoids confusion when smb_opipe_close() is 174 * called by smb_ofile_close(). 175 */ 176 bzero(&opipe->p_hdr, sizeof (smb_doorhdr_t)); 177 kmem_free(opipe->p_doorbuf, SMB_OPIPE_DOOR_BUFSIZE); 178 smb_opipe_exit(opipe); 179 smb_ofile_close(of, 0); 180 return (NT_STATUS_NO_MEMORY); 181 } 182 smb_opipe_exit(opipe); 183 return (NT_STATUS_SUCCESS); 184 } 185 186 /* 187 * smb_opipe_lookup 188 * 189 * Lookup a path to see if it's a well-known RPC named pipe that we support. 190 * The full pipe path will be in the form \\PIPE\\SERVICE. The first part 191 * can be assumed, so all we need here are the service names. 192 * 193 * Returns a pointer to the pipe name (without any leading \'s) on success. 194 * Otherwise returns a null pointer. 195 */ 196 static char * 197 smb_opipe_lookup(const char *path) 198 { 199 static char *named_pipes[] = { 200 "lsass", 201 "LSARPC", 202 "NETLOGON", 203 "SAMR", 204 "SPOOLSS", 205 "SRVSVC", 206 "SVCCTL", 207 "WINREG", 208 "WKSSVC", 209 "EVENTLOG", 210 "NETDFS" 211 }; 212 213 const char *name; 214 int i; 215 216 if (path == NULL) 217 return (NULL); 218 219 name = path; 220 name += strspn(name, "\\"); 221 if (smb_strcasecmp(name, "PIPE", 4) == 0) { 222 path += 4; 223 name += strspn(name, "\\"); 224 } 225 226 for (i = 0; i < sizeof (named_pipes) / sizeof (named_pipes[0]); ++i) { 227 if (smb_strcasecmp(name, named_pipes[i], 0) == 0) 228 return (named_pipes[i]); 229 } 230 231 return (NULL); 232 } 233 234 /* 235 * Initialize the opipe header and context, and make the door call. 236 */ 237 static int 238 smb_opipe_do_open(smb_request_t *sr, smb_opipe_t *opipe) 239 { 240 smb_netuserinfo_t *userinfo = &opipe->p_user; 241 smb_user_t *user = sr->uid_user; 242 uint8_t *buf = opipe->p_doorbuf; 243 uint32_t buflen = SMB_OPIPE_DOOR_BUFSIZE; 244 uint32_t len; 245 246 if ((opipe->p_event = smb_event_create(SMB_EVENT_TIMEOUT)) == NULL) 247 return (-1); 248 249 smb_user_netinfo_init(user, userinfo); 250 len = xdr_sizeof(smb_netuserinfo_xdr, userinfo); 251 252 bzero(&opipe->p_hdr, sizeof (smb_doorhdr_t)); 253 opipe->p_hdr.dh_magic = SMB_OPIPE_HDR_MAGIC; 254 opipe->p_hdr.dh_flags = SMB_DF_SYSSPACE; 255 opipe->p_hdr.dh_fid = smb_event_txid(opipe->p_event); 256 257 if (smb_opipe_sethdr(opipe, SMB_OPIPE_OPEN, len) == -1) 258 return (-1); 259 260 len = xdr_sizeof(smb_doorhdr_xdr, &opipe->p_hdr); 261 buf += len; 262 buflen -= len; 263 264 if (smb_netuserinfo_encode(userinfo, buf, buflen, NULL) == -1) 265 return (-1); 266 267 return (smb_opipe_door_call(opipe)); 268 } 269 270 /* 271 * smb_opipe_close 272 * 273 * Called whenever an IPC file/pipe is closed. 274 */ 275 void 276 smb_opipe_close(smb_ofile_t *of) 277 { 278 smb_opipe_t *opipe; 279 280 ASSERT(of); 281 ASSERT(of->f_ftype == SMB_FTYPE_MESG_PIPE); 282 283 opipe = of->f_pipe; 284 SMB_OPIPE_VALID(opipe); 285 286 (void) smb_server_cancel_event(opipe->p_hdr.dh_fid); 287 smb_opipe_enter(opipe); 288 289 if (SMB_OPIPE_ISOPEN(opipe)) { 290 (void) smb_opipe_sethdr(opipe, SMB_OPIPE_CLOSE, 0); 291 (void) smb_opipe_door_call(opipe); 292 bzero(&opipe->p_hdr, sizeof (smb_doorhdr_t)); 293 kmem_free(opipe->p_doorbuf, SMB_OPIPE_DOOR_BUFSIZE); 294 } 295 296 smb_user_netinfo_fini(&opipe->p_user); 297 smb_opipe_exit(opipe); 298 } 299 300 static int 301 smb_opipe_sethdr(smb_opipe_t *opipe, uint32_t cmd, uint32_t datalen) 302 { 303 opipe->p_hdr.dh_op = cmd; 304 opipe->p_hdr.dh_txid = opipe->p_hdr.dh_fid; 305 opipe->p_hdr.dh_datalen = datalen; 306 opipe->p_hdr.dh_resid = 0; 307 opipe->p_hdr.dh_door_rc = EINVAL; 308 309 return (smb_doorhdr_encode(&opipe->p_hdr, opipe->p_doorbuf, 310 SMB_OPIPE_DOOR_BUFSIZE)); 311 } 312 313 /* 314 * smb_opipe_transact 315 * 316 * This is the entry point for RPC bind and request transactions. 317 * The fid is an arbitrary id used to associate RPC requests with a 318 * particular binding handle. 319 * 320 * If the data to be returned is larger than the client expects, we 321 * return as much as the client can handle and report a buffer overflow 322 * warning, which informs the client that we have more data to return. 323 * The residual data remains in the pipe until the client claims it or 324 * closes the pipe. 325 */ 326 smb_sdrc_t 327 smb_opipe_transact(smb_request_t *sr, struct uio *uio) 328 { 329 smb_xa_t *xa; 330 smb_opipe_t *opipe; 331 struct mbuf *mhead; 332 int mdrcnt; 333 int nbytes; 334 int rc; 335 336 if ((rc = smb_opipe_write(sr, uio)) != 0) { 337 if (rc == EBADF) 338 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, 339 ERRDOS, ERROR_INVALID_HANDLE); 340 else 341 smbsr_error(sr, NT_STATUS_INTERNAL_ERROR, 342 ERRDOS, ERROR_INTERNAL_ERROR); 343 return (SDRC_ERROR); 344 } 345 346 opipe = sr->fid_ofile->f_pipe; 347 348 if ((rc = smb_opipe_exec(opipe)) != 0) { 349 smbsr_error(sr, NT_STATUS_INTERNAL_ERROR, 350 ERRDOS, ERROR_INTERNAL_ERROR); 351 return (SDRC_ERROR); 352 } 353 354 xa = sr->r_xa; 355 mdrcnt = xa->smb_mdrcnt; 356 smb_opipe_enter(opipe); 357 358 if (smb_opipe_sethdr(opipe, SMB_OPIPE_READ, mdrcnt) == -1) { 359 smb_opipe_exit(opipe); 360 smbsr_error(sr, NT_STATUS_INTERNAL_ERROR, 361 ERRDOS, ERROR_INTERNAL_ERROR); 362 return (SDRC_ERROR); 363 } 364 365 rc = smb_opipe_door_call(opipe); 366 nbytes = opipe->p_hdr.dh_datalen; 367 368 if (rc != 0) { 369 smb_opipe_exit(opipe); 370 smbsr_error(sr, NT_STATUS_INTERNAL_ERROR, 371 ERRDOS, ERROR_INTERNAL_ERROR); 372 return (SDRC_ERROR); 373 } 374 375 if (nbytes) { 376 mhead = smb_mbuf_get(opipe->p_data, nbytes); 377 xa->rep_data_mb.max_bytes = nbytes; 378 MBC_ATTACH_MBUF(&xa->rep_data_mb, mhead); 379 } 380 381 if (opipe->p_hdr.dh_resid) { 382 /* 383 * The pipe contains more data than mdrcnt, warn the 384 * client that there is more data in the pipe. 385 * Typically, the client will call SmbReadX, which 386 * will call smb_opipe_read, to get the data. 387 */ 388 smbsr_warn(sr, NT_STATUS_BUFFER_OVERFLOW, 389 ERRDOS, ERROR_MORE_DATA); 390 } 391 392 smb_opipe_exit(opipe); 393 return (SDRC_SUCCESS); 394 } 395 396 /* 397 * smb_opipe_write 398 * 399 * Write RPC request data to the pipe. The client should call smb_opipe_read 400 * to complete the exchange and obtain the RPC response. 401 * 402 * Returns 0 on success or an errno on failure. 403 */ 404 int 405 smb_opipe_write(smb_request_t *sr, struct uio *uio) 406 { 407 smb_opipe_t *opipe; 408 uint32_t buflen; 409 uint32_t len; 410 int rc; 411 412 ASSERT(sr->fid_ofile); 413 ASSERT(sr->fid_ofile->f_ftype == SMB_FTYPE_MESG_PIPE); 414 415 opipe = sr->fid_ofile->f_pipe; 416 SMB_OPIPE_VALID(opipe); 417 smb_opipe_enter(opipe); 418 419 if (!SMB_OPIPE_ISOPEN(opipe)) { 420 smb_opipe_exit(opipe); 421 return (EBADF); 422 } 423 424 rc = smb_opipe_sethdr(opipe, SMB_OPIPE_WRITE, uio->uio_resid); 425 len = xdr_sizeof(smb_doorhdr_xdr, &opipe->p_hdr); 426 if (rc == -1 || len == 0) { 427 smb_opipe_exit(opipe); 428 return (ENOMEM); 429 } 430 431 buflen = SMB_OPIPE_DOOR_BUFSIZE - len; 432 (void) uiomove((caddr_t)opipe->p_data, buflen, UIO_WRITE, uio); 433 434 rc = smb_opipe_door_call(opipe); 435 436 smb_opipe_exit(opipe); 437 return ((rc == 0) ? 0 : EIO); 438 } 439 440 /* 441 * smb_opipe_read 442 * 443 * This interface may be called because smb_opipe_transact could not return 444 * all of the data in the original transaction or to form the second half 445 * of a transaction set up using smb_opipe_write. Either way, we just need 446 * to read data from the pipe and return it. 447 * 448 * The response data is encoded into raw_data as required by the smb_read 449 * functions. The uio_resid value indicates the number of bytes read. 450 */ 451 int 452 smb_opipe_read(smb_request_t *sr, struct uio *uio) 453 { 454 smb_opipe_t *opipe; 455 struct mbuf *mhead; 456 uint32_t nbytes; 457 int rc; 458 459 ASSERT(sr->fid_ofile); 460 ASSERT(sr->fid_ofile->f_ftype == SMB_FTYPE_MESG_PIPE); 461 462 opipe = sr->fid_ofile->f_pipe; 463 SMB_OPIPE_VALID(opipe); 464 465 if ((rc = smb_opipe_exec(opipe)) != 0) 466 return (EIO); 467 468 smb_opipe_enter(opipe); 469 470 if (!SMB_OPIPE_ISOPEN(opipe)) { 471 smb_opipe_exit(opipe); 472 return (EBADF); 473 } 474 475 if (smb_opipe_sethdr(opipe, SMB_OPIPE_READ, uio->uio_resid) == -1) { 476 smb_opipe_exit(opipe); 477 return (ENOMEM); 478 } 479 480 rc = smb_opipe_door_call(opipe); 481 nbytes = opipe->p_hdr.dh_datalen; 482 483 if (rc != 0 || nbytes > uio->uio_resid) { 484 smb_opipe_exit(opipe); 485 return (EIO); 486 } 487 488 if (nbytes) { 489 mhead = smb_mbuf_get(opipe->p_data, nbytes); 490 MBC_SETUP(&sr->raw_data, nbytes); 491 MBC_ATTACH_MBUF(&sr->raw_data, mhead); 492 uio->uio_resid -= nbytes; 493 } 494 495 smb_opipe_exit(opipe); 496 return (rc); 497 } 498 499 static int 500 smb_opipe_exec(smb_opipe_t *opipe) 501 { 502 uint32_t len; 503 int rc; 504 505 smb_opipe_enter(opipe); 506 507 rc = smb_opipe_sethdr(opipe, SMB_OPIPE_EXEC, 0); 508 len = xdr_sizeof(smb_doorhdr_xdr, &opipe->p_hdr); 509 if (rc == -1 || len == 0) { 510 smb_opipe_exit(opipe); 511 return (ENOMEM); 512 } 513 514 if ((rc = smb_opipe_door_call(opipe)) == 0) 515 rc = smb_event_wait(opipe->p_event); 516 517 smb_opipe_exit(opipe); 518 return (rc); 519 } 520 521 /* 522 * Named pipe I/O is serialized per fid to ensure that each request 523 * has exclusive opipe access for the duration of the request. 524 */ 525 static void 526 smb_opipe_enter(smb_opipe_t *opipe) 527 { 528 mutex_enter(&opipe->p_mutex); 529 530 while (opipe->p_busy) 531 cv_wait(&opipe->p_cv, &opipe->p_mutex); 532 533 opipe->p_busy = 1; 534 mutex_exit(&opipe->p_mutex); 535 } 536 537 /* 538 * Exit busy state. If we have exec'd an RPC, we may have 539 * to wait for notification that processing has completed. 540 */ 541 static void 542 smb_opipe_exit(smb_opipe_t *opipe) 543 { 544 mutex_enter(&opipe->p_mutex); 545 opipe->p_busy = 0; 546 cv_signal(&opipe->p_cv); 547 mutex_exit(&opipe->p_mutex); 548 } 549 550 /* 551 * opipe door client (to user space door server). 552 */ 553 void 554 smb_opipe_door_init(void) 555 { 556 mutex_init(&smb_opipe_door_mutex, NULL, MUTEX_DEFAULT, NULL); 557 cv_init(&smb_opipe_door_cv, NULL, CV_DEFAULT, NULL); 558 } 559 560 void 561 smb_opipe_door_fini(void) 562 { 563 smb_opipe_door_close(); 564 cv_destroy(&smb_opipe_door_cv); 565 mutex_destroy(&smb_opipe_door_mutex); 566 } 567 568 /* 569 * Open the (user space) door. If the door is already open, 570 * close it first because the door-id has probably changed. 571 */ 572 int 573 smb_opipe_door_open(int door_id) 574 { 575 smb_opipe_door_close(); 576 577 mutex_enter(&smb_opipe_door_mutex); 578 smb_opipe_door_ncall = 0; 579 580 if (smb_opipe_door_hd == NULL) { 581 smb_opipe_door_id = door_id; 582 smb_opipe_door_hd = door_ki_lookup(door_id); 583 } 584 585 mutex_exit(&smb_opipe_door_mutex); 586 return ((smb_opipe_door_hd == NULL) ? -1 : 0); 587 } 588 589 /* 590 * Close the (user space) door. 591 */ 592 void 593 smb_opipe_door_close(void) 594 { 595 mutex_enter(&smb_opipe_door_mutex); 596 597 if (smb_opipe_door_hd != NULL) { 598 while (smb_opipe_door_ncall > 0) 599 cv_wait(&smb_opipe_door_cv, &smb_opipe_door_mutex); 600 601 door_ki_rele(smb_opipe_door_hd); 602 smb_opipe_door_hd = NULL; 603 } 604 605 mutex_exit(&smb_opipe_door_mutex); 606 } 607 608 /* 609 * opipe door call interface. 610 * Door serialization and call reference accounting is handled here. 611 */ 612 static int 613 smb_opipe_door_call(smb_opipe_t *opipe) 614 { 615 int rc; 616 617 mutex_enter(&smb_opipe_door_mutex); 618 619 if (smb_opipe_door_hd == NULL) { 620 mutex_exit(&smb_opipe_door_mutex); 621 622 if (smb_opipe_door_open(smb_opipe_door_id) != 0) 623 return (-1); 624 625 mutex_enter(&smb_opipe_door_mutex); 626 } 627 628 ++smb_opipe_door_ncall; 629 mutex_exit(&smb_opipe_door_mutex); 630 631 rc = smb_opipe_door_upcall(opipe); 632 633 mutex_enter(&smb_opipe_door_mutex); 634 if ((--smb_opipe_door_ncall) == 0) 635 cv_signal(&smb_opipe_door_cv); 636 mutex_exit(&smb_opipe_door_mutex); 637 return (rc); 638 } 639 640 /* 641 * Door upcall wrapper - handles data marshalling. 642 * This function should only be called by smb_opipe_door_call. 643 */ 644 static int 645 smb_opipe_door_upcall(smb_opipe_t *opipe) 646 { 647 door_arg_t da; 648 smb_doorhdr_t hdr; 649 int i; 650 int rc; 651 652 da.data_ptr = (char *)opipe->p_doorbuf; 653 da.data_size = SMB_OPIPE_DOOR_BUFSIZE; 654 da.desc_ptr = NULL; 655 da.desc_num = 0; 656 da.rbuf = (char *)opipe->p_doorbuf; 657 da.rsize = SMB_OPIPE_DOOR_BUFSIZE; 658 659 for (i = 0; i < 3; ++i) { 660 if (smb_server_is_stopping()) 661 return (-1); 662 663 if ((rc = door_ki_upcall_limited(smb_opipe_door_hd, &da, 664 NULL, SIZE_MAX, 0)) == 0) 665 break; 666 667 if (rc != EAGAIN && rc != EINTR) 668 return (-1); 669 } 670 671 /* Check for door_return(NULL, 0, NULL, 0) */ 672 if (rc != 0 || da.data_size == 0 || da.rsize == 0) 673 return (-1); 674 675 if (smb_doorhdr_decode(&hdr, (uint8_t *)da.data_ptr, da.rsize) == -1) 676 return (-1); 677 678 if ((hdr.dh_magic != SMB_OPIPE_HDR_MAGIC) || 679 (hdr.dh_fid != opipe->p_hdr.dh_fid) || 680 (hdr.dh_op != opipe->p_hdr.dh_op) || 681 (hdr.dh_door_rc != 0) || 682 (hdr.dh_datalen > SMB_OPIPE_DOOR_BUFSIZE)) { 683 return (-1); 684 } 685 686 opipe->p_hdr.dh_datalen = hdr.dh_datalen; 687 opipe->p_hdr.dh_resid = hdr.dh_resid; 688 return (0); 689 } 690