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