1*adee6784SGordon Ross /*
2*adee6784SGordon Ross  * Copyright (c) 2011  Apple Inc. All rights reserved.
3*adee6784SGordon Ross  *
4*adee6784SGordon Ross  * @APPLE_LICENSE_HEADER_START@
5*adee6784SGordon Ross  *
6*adee6784SGordon Ross  * This file contains Original Code and/or Modifications of Original Code
7*adee6784SGordon Ross  * as defined in and that are subject to the Apple Public Source License
8*adee6784SGordon Ross  * Version 2.0 (the 'License'). You may not use this file except in
9*adee6784SGordon Ross  * compliance with the License. Please obtain a copy of the License at
10*adee6784SGordon Ross  * http://www.opensource.apple.com/apsl/ and read it before using this
11*adee6784SGordon Ross  * file.
12*adee6784SGordon Ross  *
13*adee6784SGordon Ross  * The Original Code and all software distributed under the License are
14*adee6784SGordon Ross  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15*adee6784SGordon Ross  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16*adee6784SGordon Ross  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17*adee6784SGordon Ross  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18*adee6784SGordon Ross  * Please see the License for the specific language governing rights and
19*adee6784SGordon Ross  * limitations under the License.
20*adee6784SGordon Ross  *
21*adee6784SGordon Ross  * @APPLE_LICENSE_HEADER_END@
22*adee6784SGordon Ross  */
23*adee6784SGordon Ross 
24*adee6784SGordon Ross /*
25*adee6784SGordon Ross  * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
26*adee6784SGordon Ross  */
27*adee6784SGordon Ross 
28*adee6784SGordon Ross #include <sys/param.h>
29*adee6784SGordon Ross #include <sys/systm.h>
30*adee6784SGordon Ross #include <sys/time.h>
31*adee6784SGordon Ross #include <sys/kmem.h>
32*adee6784SGordon Ross #include <sys/proc.h>
33*adee6784SGordon Ross #include <sys/lock.h>
34*adee6784SGordon Ross #include <sys/socket.h>
35*adee6784SGordon Ross #include <sys/mount.h>
36*adee6784SGordon Ross #include <sys/sunddi.h>
37*adee6784SGordon Ross #include <sys/cmn_err.h>
38*adee6784SGordon Ross #include <sys/atomic.h>
39*adee6784SGordon Ross #include <sys/sdt.h>
40*adee6784SGordon Ross 
41*adee6784SGordon Ross #include <netsmb/smb_osdep.h>
42*adee6784SGordon Ross 
43*adee6784SGordon Ross #include <netsmb/smb.h>
44*adee6784SGordon Ross #include <netsmb/smb2.h>
45*adee6784SGordon Ross #include <netsmb/smb_conn.h>
46*adee6784SGordon Ross #include <netsmb/smb_subr.h>
47*adee6784SGordon Ross #include <netsmb/smb_tran.h>
48*adee6784SGordon Ross #include <netsmb/smb_rq.h>
49*adee6784SGordon Ross #include <netsmb/smb2_rq.h>
50*adee6784SGordon Ross 
51*adee6784SGordon Ross static const uint8_t SMB2_SIGNATURE[4] = SMB2_PROTOCOL_ID;
52*adee6784SGordon Ross 
53*adee6784SGordon Ross static int  smb2_rq_enqueue(struct smb_rq *rqp);
54*adee6784SGordon Ross static int  smb2_rq_reply(struct smb_rq *rqp);
55*adee6784SGordon Ross 
56*adee6784SGordon Ross /*
57*adee6784SGordon Ross  * Given a request with it's body already composed,
58*adee6784SGordon Ross  * rewind to the start and fill in the SMB2 header.
59*adee6784SGordon Ross  * This is called when the request is enqueued,
60*adee6784SGordon Ross  * so we have the final message ID etc.
61*adee6784SGordon Ross  */
62*adee6784SGordon Ross void
smb2_rq_fillhdr(struct smb_rq * rqp)63*adee6784SGordon Ross smb2_rq_fillhdr(struct smb_rq *rqp)
64*adee6784SGordon Ross {
65*adee6784SGordon Ross 	struct mbchain mbtmp, *mbp = &mbtmp;
66*adee6784SGordon Ross 	uint16_t creditcharge, creditrequest;
67*adee6784SGordon Ross 	size_t len;
68*adee6784SGordon Ross 	mblk_t *m;
69*adee6784SGordon Ross 
70*adee6784SGordon Ross 	ASSERT((rqp->sr2_nextcmd & 7) == 0);
71*adee6784SGordon Ross 	if (rqp->sr2_nextcmd != 0) {
72*adee6784SGordon Ross 		len = msgdsize(rqp->sr_rq.mb_top);
73*adee6784SGordon Ross 		ASSERT((len & 7) == 0);
74*adee6784SGordon Ross 	}
75*adee6784SGordon Ross 
76*adee6784SGordon Ross 	/*
77*adee6784SGordon Ross 	 * When sending negotiate, we don't technically know yet
78*adee6784SGordon Ross 	 * if the server handles SMB 2.1 or later and credits.
79*adee6784SGordon Ross 	 * Negotiate is supposed to set these to zero.
80*adee6784SGordon Ross 	 */
81*adee6784SGordon Ross 	if (rqp->sr2_command == SMB2_NEGOTIATE) {
82*adee6784SGordon Ross 		creditcharge = creditrequest = 0;
83*adee6784SGordon Ross 	} else {
84*adee6784SGordon Ross 		creditcharge = rqp->sr2_creditcharge;
85*adee6784SGordon Ross 		creditrequest = rqp->sr2_creditsrequested;
86*adee6784SGordon Ross 	}
87*adee6784SGordon Ross 
88*adee6784SGordon Ross 	/*
89*adee6784SGordon Ross 	 * Fill in the SMB2 header using a dup of the first mblk,
90*adee6784SGordon Ross 	 * which points at the same data but has its own wptr,
91*adee6784SGordon Ross 	 * so we can rewind without trashing the message.
92*adee6784SGordon Ross 	 */
93*adee6784SGordon Ross 	m = dupb(rqp->sr_rq.mb_top);
94*adee6784SGordon Ross 	m->b_wptr = m->b_rptr;	/* rewind */
95*adee6784SGordon Ross 	mb_initm(mbp, m);
96*adee6784SGordon Ross 
97*adee6784SGordon Ross 	mb_put_mem(mbp, SMB2_SIGNATURE, 4, MB_MSYSTEM);
98*adee6784SGordon Ross 	mb_put_uint16le(mbp, SMB2_HDR_SIZE);		/* Struct Size */
99*adee6784SGordon Ross 	mb_put_uint16le(mbp, creditcharge);
100*adee6784SGordon Ross 	mb_put_uint32le(mbp, 0);	/* Status */
101*adee6784SGordon Ross 	mb_put_uint16le(mbp, rqp->sr2_command);
102*adee6784SGordon Ross 	mb_put_uint16le(mbp, creditrequest);
103*adee6784SGordon Ross 	mb_put_uint32le(mbp, rqp->sr2_rqflags);
104*adee6784SGordon Ross 	mb_put_uint32le(mbp, rqp->sr2_nextcmd);
105*adee6784SGordon Ross 	mb_put_uint64le(mbp, rqp->sr2_messageid);
106*adee6784SGordon Ross 
107*adee6784SGordon Ross 	mb_put_uint32le(mbp, rqp->sr_pid);		/* Process ID */
108*adee6784SGordon Ross 	mb_put_uint32le(mbp, rqp->sr2_rqtreeid);	/* Tree ID */
109*adee6784SGordon Ross 	mb_put_uint64le(mbp, rqp->sr2_rqsessionid);	/* Session ID */
110*adee6784SGordon Ross 	/* The MAC signature is filled in by smb2_vc_sign() */
111*adee6784SGordon Ross 
112*adee6784SGordon Ross 	/* This will free the mblk from dupb. */
113*adee6784SGordon Ross 	mb_done(mbp);
114*adee6784SGordon Ross }
115*adee6784SGordon Ross 
116*adee6784SGordon Ross int
smb2_rq_simple(struct smb_rq * rqp)117*adee6784SGordon Ross smb2_rq_simple(struct smb_rq *rqp)
118*adee6784SGordon Ross {
119*adee6784SGordon Ross 	return (smb2_rq_simple_timed(rqp, smb2_timo_default));
120*adee6784SGordon Ross }
121*adee6784SGordon Ross 
122*adee6784SGordon Ross /*
123*adee6784SGordon Ross  * Simple request-reply exchange
124*adee6784SGordon Ross  */
125*adee6784SGordon Ross int
smb2_rq_simple_timed(struct smb_rq * rqp,int timeout)126*adee6784SGordon Ross smb2_rq_simple_timed(struct smb_rq *rqp, int timeout)
127*adee6784SGordon Ross {
128*adee6784SGordon Ross 	int error;
129*adee6784SGordon Ross 
130*adee6784SGordon Ross 	rqp->sr_flags &= ~SMBR_RESTART;
131*adee6784SGordon Ross 	rqp->sr_timo = timeout;	/* in seconds */
132*adee6784SGordon Ross 	rqp->sr_state = SMBRQ_NOTSENT;
133*adee6784SGordon Ross 
134*adee6784SGordon Ross 	error = smb2_rq_enqueue(rqp);
135*adee6784SGordon Ross 	if (error == 0)
136*adee6784SGordon Ross 		error = smb2_rq_reply(rqp);
137*adee6784SGordon Ross 
138*adee6784SGordon Ross 	return (error);
139*adee6784SGordon Ross }
140*adee6784SGordon Ross 
141*adee6784SGordon Ross 
142*adee6784SGordon Ross static int
smb2_rq_enqueue(struct smb_rq * rqp)143*adee6784SGordon Ross smb2_rq_enqueue(struct smb_rq *rqp)
144*adee6784SGordon Ross {
145*adee6784SGordon Ross 	struct smb_vc *vcp = rqp->sr_vc;
146*adee6784SGordon Ross 	struct smb_share *ssp = rqp->sr_share;
147*adee6784SGordon Ross 	int error = 0;
148*adee6784SGordon Ross 
149*adee6784SGordon Ross 	ASSERT((vcp->vc_flags & SMBV_SMB2) != 0);
150*adee6784SGordon Ross 
151*adee6784SGordon Ross 	/*
152*adee6784SGordon Ross 	 * Normal requests may initiate a reconnect,
153*adee6784SGordon Ross 	 * and/or wait for state changes to finish.
154*adee6784SGordon Ross 	 * Some requests set the NORECONNECT flag
155*adee6784SGordon Ross 	 * to avoid all that (i.e. tree discon)
156*adee6784SGordon Ross 	 */
157*adee6784SGordon Ross 	if (rqp->sr_flags & SMBR_NORECONNECT) {
158*adee6784SGordon Ross 		if (vcp->vc_state != SMBIOD_ST_VCACTIVE) {
159*adee6784SGordon Ross 			SMBSDEBUG("bad vc_state=%d\n", vcp->vc_state);
160*adee6784SGordon Ross 			return (ENOTCONN);
161*adee6784SGordon Ross 		}
162*adee6784SGordon Ross 		if (ssp != NULL &&
163*adee6784SGordon Ross 		    ((ssp->ss_flags & SMBS_CONNECTED) == 0))
164*adee6784SGordon Ross 			return (ENOTCONN);
165*adee6784SGordon Ross 		goto ok_out;
166*adee6784SGordon Ross 	}
167*adee6784SGordon Ross 
168*adee6784SGordon Ross 	/*
169*adee6784SGordon Ross 	 * If we're not connected, initiate a reconnect
170*adee6784SGordon Ross 	 * and/or wait for an existing one to finish.
171*adee6784SGordon Ross 	 */
172*adee6784SGordon Ross 	if (vcp->vc_state != SMBIOD_ST_VCACTIVE) {
173*adee6784SGordon Ross 		error = smb_iod_reconnect(vcp);
174*adee6784SGordon Ross 		if (error != 0)
175*adee6784SGordon Ross 			return (error);
176*adee6784SGordon Ross 	}
177*adee6784SGordon Ross 
178*adee6784SGordon Ross 	/*
179*adee6784SGordon Ross 	 * If this request has a "share" object
180*adee6784SGordon Ross 	 * that needs a tree connect, do it now.
181*adee6784SGordon Ross 	 */
182*adee6784SGordon Ross 	if (ssp != NULL && (ssp->ss_flags & SMBS_CONNECTED) == 0) {
183*adee6784SGordon Ross 		error = smb_share_tcon(ssp, rqp->sr_cred);
184*adee6784SGordon Ross 		if (error)
185*adee6784SGordon Ross 			return (error);
186*adee6784SGordon Ross 	}
187*adee6784SGordon Ross 
188*adee6784SGordon Ross 	/*
189*adee6784SGordon Ross 	 * We now know what UID + TID to use.
190*adee6784SGordon Ross 	 * Store them in the request.
191*adee6784SGordon Ross 	 */
192*adee6784SGordon Ross ok_out:
193*adee6784SGordon Ross 	rqp->sr2_rqsessionid = vcp->vc2_session_id;
194*adee6784SGordon Ross 	rqp->sr2_rqtreeid = ssp ? ssp->ss2_tree_id : SMB2_TID_UNKNOWN;
195*adee6784SGordon Ross 	error = smb2_iod_addrq(rqp);
196*adee6784SGordon Ross 
197*adee6784SGordon Ross 	return (error);
198*adee6784SGordon Ross }
199*adee6784SGordon Ross 
200*adee6784SGordon Ross /*
201*adee6784SGordon Ross  * Used by the IOD thread during connection setup,
202*adee6784SGordon Ross  * and for smb2_echo after network timeouts.  Note that
203*adee6784SGordon Ross  * unlike smb2_rq_simple, callers must check sr_error.
204*adee6784SGordon Ross  */
205*adee6784SGordon Ross int
smb2_rq_internal(struct smb_rq * rqp,int timeout)206*adee6784SGordon Ross smb2_rq_internal(struct smb_rq *rqp, int timeout)
207*adee6784SGordon Ross {
208*adee6784SGordon Ross 	struct smb_vc *vcp = rqp->sr_vc;
209*adee6784SGordon Ross 	int error;
210*adee6784SGordon Ross 
211*adee6784SGordon Ross 	ASSERT((vcp->vc_flags & SMBV_SMB2) != 0);
212*adee6784SGordon Ross 
213*adee6784SGordon Ross 	rqp->sr_flags &= ~SMBR_RESTART;
214*adee6784SGordon Ross 	rqp->sr_timo = timeout;	/* in seconds */
215*adee6784SGordon Ross 	rqp->sr_state = SMBRQ_NOTSENT;
216*adee6784SGordon Ross 
217*adee6784SGordon Ross 	/*
218*adee6784SGordon Ross 	 * In-line smb2_rq_enqueue(rqp) here, as we don't want it
219*adee6784SGordon Ross 	 * trying to reconnect etc. for an internal request.
220*adee6784SGordon Ross 	 */
221*adee6784SGordon Ross 	rqp->sr2_rqsessionid = vcp->vc2_session_id;
222*adee6784SGordon Ross 	rqp->sr2_rqtreeid = SMB2_TID_UNKNOWN;
223*adee6784SGordon Ross 	rqp->sr_flags |= SMBR_INTERNAL;
224*adee6784SGordon Ross 	error = smb2_iod_addrq(rqp);
225*adee6784SGordon Ross 	if (error != 0)
226*adee6784SGordon Ross 		return (error);
227*adee6784SGordon Ross 
228*adee6784SGordon Ross 	/*
229*adee6784SGordon Ross 	 * In-line a variant of smb2_rq_reply(rqp) here as we may
230*adee6784SGordon Ross 	 * need to do custom parsing for SMB1-to-SMB2 negotiate.
231*adee6784SGordon Ross 	 */
232*adee6784SGordon Ross 	if (rqp->sr_timo == SMBNOREPLYWAIT) {
233*adee6784SGordon Ross 		smb_iod_removerq(rqp);
234*adee6784SGordon Ross 		return (0);
235*adee6784SGordon Ross 	}
236*adee6784SGordon Ross 
237*adee6784SGordon Ross 	error = smb_iod_waitrq_int(rqp);
238*adee6784SGordon Ross 	if (error)
239*adee6784SGordon Ross 		return (error);
240*adee6784SGordon Ross 
241*adee6784SGordon Ross 	/*
242*adee6784SGordon Ross 	 * If the request was signed, validate the
243*adee6784SGordon Ross 	 * signature on the response.
244*adee6784SGordon Ross 	 */
245*adee6784SGordon Ross 	if (rqp->sr2_rqflags & SMB2_FLAGS_SIGNED) {
246*adee6784SGordon Ross 		error = smb2_rq_verify(rqp);
247*adee6784SGordon Ross 		if (error)
248*adee6784SGordon Ross 			return (error);
249*adee6784SGordon Ross 	}
250*adee6784SGordon Ross 
251*adee6784SGordon Ross 	/*
252*adee6784SGordon Ross 	 * Parse the SMB2 header.
253*adee6784SGordon Ross 	 */
254*adee6784SGordon Ross 	error = smb2_rq_parsehdr(rqp);
255*adee6784SGordon Ross 
256*adee6784SGordon Ross 	/*
257*adee6784SGordon Ross 	 * Skip the error translation smb2_rq_reply does.
258*adee6784SGordon Ross 	 * Callers of this expect "raw" NT status.
259*adee6784SGordon Ross 	 */
260*adee6784SGordon Ross 
261*adee6784SGordon Ross 	return (error);
262*adee6784SGordon Ross }
263*adee6784SGordon Ross 
264*adee6784SGordon Ross /*
265*adee6784SGordon Ross  * Wait for a reply to this request, then parse it.
266*adee6784SGordon Ross  */
267*adee6784SGordon Ross static int
smb2_rq_reply(struct smb_rq * rqp)268*adee6784SGordon Ross smb2_rq_reply(struct smb_rq *rqp)
269*adee6784SGordon Ross {
270*adee6784SGordon Ross 	int error;
271*adee6784SGordon Ross 
272*adee6784SGordon Ross 	if (rqp->sr_timo == SMBNOREPLYWAIT) {
273*adee6784SGordon Ross 		smb_iod_removerq(rqp);
274*adee6784SGordon Ross 		return (0);
275*adee6784SGordon Ross 	}
276*adee6784SGordon Ross 
277*adee6784SGordon Ross 	error = smb_iod_waitrq(rqp);
278*adee6784SGordon Ross 	if (error)
279*adee6784SGordon Ross 		return (error);
280*adee6784SGordon Ross 
281*adee6784SGordon Ross 	/*
282*adee6784SGordon Ross 	 * If the request was signed, validate the
283*adee6784SGordon Ross 	 * signature on the response.
284*adee6784SGordon Ross 	 */
285*adee6784SGordon Ross 	if (rqp->sr2_rqflags & SMB2_FLAGS_SIGNED) {
286*adee6784SGordon Ross 		error = smb2_rq_verify(rqp);
287*adee6784SGordon Ross 		if (error)
288*adee6784SGordon Ross 			return (error);
289*adee6784SGordon Ross 	}
290*adee6784SGordon Ross 
291*adee6784SGordon Ross 	/*
292*adee6784SGordon Ross 	 * Parse the SMB2 header
293*adee6784SGordon Ross 	 */
294*adee6784SGordon Ross 	error = smb2_rq_parsehdr(rqp);
295*adee6784SGordon Ross 	if (error != 0)
296*adee6784SGordon Ross 		return (error);
297*adee6784SGordon Ross 
298*adee6784SGordon Ross 	if (rqp->sr_error != 0) {
299*adee6784SGordon Ross 		error = smb_maperr32(rqp->sr_error);
300*adee6784SGordon Ross 	}
301*adee6784SGordon Ross 
302*adee6784SGordon Ross 	if (error != 0) {
303*adee6784SGordon Ross 		/*
304*adee6784SGordon Ross 		 * Do a special check for STATUS_BUFFER_OVERFLOW;
305*adee6784SGordon Ross 		 * it's not an error.
306*adee6784SGordon Ross 		 */
307*adee6784SGordon Ross 		if (rqp->sr_error == NT_STATUS_BUFFER_OVERFLOW) {
308*adee6784SGordon Ross 			/*
309*adee6784SGordon Ross 			 * Don't report it as an error to our caller;
310*adee6784SGordon Ross 			 * they can look at rqp->sr_error if they
311*adee6784SGordon Ross 			 * need to know whether we got a
312*adee6784SGordon Ross 			 * STATUS_BUFFER_OVERFLOW.
313*adee6784SGordon Ross 			 */
314*adee6784SGordon Ross 			rqp->sr_flags |= SMBR_MOREDATA;
315*adee6784SGordon Ross 			error = 0;
316*adee6784SGordon Ross 		}
317*adee6784SGordon Ross 	} else {
318*adee6784SGordon Ross 		rqp->sr_flags &= ~SMBR_MOREDATA;
319*adee6784SGordon Ross 	}
320*adee6784SGordon Ross 
321*adee6784SGordon Ross 	return (error);
322*adee6784SGordon Ross }
323*adee6784SGordon Ross 
324*adee6784SGordon Ross /*
325*adee6784SGordon Ross  * Parse the SMB 2+ Header
326*adee6784SGordon Ross  */
327*adee6784SGordon Ross int
smb2_rq_parsehdr(struct smb_rq * rqp)328*adee6784SGordon Ross smb2_rq_parsehdr(struct smb_rq *rqp)
329*adee6784SGordon Ross {
330*adee6784SGordon Ross 	struct mdchain *mdp = &rqp->sr_rp;
331*adee6784SGordon Ross 	uint32_t protocol_id;
332*adee6784SGordon Ross 	uint16_t length = 0;
333*adee6784SGordon Ross 	uint16_t credit_charge;
334*adee6784SGordon Ross 	uint16_t command;
335*adee6784SGordon Ross 	uint64_t message_id = 0;
336*adee6784SGordon Ross 	int error = 0;
337*adee6784SGordon Ross 
338*adee6784SGordon Ross 	/* Get Protocol ID */
339*adee6784SGordon Ross 	md_get_uint32le(mdp, &protocol_id);
340*adee6784SGordon Ross 
341*adee6784SGordon Ross 	/* Get/Check structure size is 64 */
342*adee6784SGordon Ross 	md_get_uint16le(mdp, &length);
343*adee6784SGordon Ross 	if (length != 64)
344*adee6784SGordon Ross 		return (EBADRPC);
345*adee6784SGordon Ross 
346*adee6784SGordon Ross 	md_get_uint16le(mdp, &credit_charge);
347*adee6784SGordon Ross 	md_get_uint32le(mdp, &rqp->sr_error);
348*adee6784SGordon Ross 	md_get_uint16le(mdp, &command);
349*adee6784SGordon Ross 	md_get_uint16le(mdp, &rqp->sr2_rspcreditsgranted);
350*adee6784SGordon Ross 	md_get_uint32le(mdp, &rqp->sr2_rspflags);
351*adee6784SGordon Ross 	md_get_uint32le(mdp, &rqp->sr2_rspnextcmd);
352*adee6784SGordon Ross 	md_get_uint64le(mdp, &message_id);
353*adee6784SGordon Ross 
354*adee6784SGordon Ross 	if ((rqp->sr2_rspflags & SMB2_FLAGS_ASYNC_COMMAND) == 0) {
355*adee6784SGordon Ross 		/*
356*adee6784SGordon Ross 		 * Sync Header
357*adee6784SGordon Ross 		 */
358*adee6784SGordon Ross 
359*adee6784SGordon Ross 		/* Get Process ID */
360*adee6784SGordon Ross 		md_get_uint32le(mdp, &rqp->sr2_rsppid);
361*adee6784SGordon Ross 
362*adee6784SGordon Ross 		/* Get Tree ID */
363*adee6784SGordon Ross 		md_get_uint32le(mdp, &rqp->sr2_rsptreeid);
364*adee6784SGordon Ross 	} else {
365*adee6784SGordon Ross 		/*
366*adee6784SGordon Ross 		 * Async Header
367*adee6784SGordon Ross 		 */
368*adee6784SGordon Ross 
369*adee6784SGordon Ross 		/* Get Async ID */
370*adee6784SGordon Ross 		md_get_uint64le(mdp, &rqp->sr2_rspasyncid);
371*adee6784SGordon Ross 	}
372*adee6784SGordon Ross 
373*adee6784SGordon Ross 	/* Get Session ID */
374*adee6784SGordon Ross 	error = md_get_uint64le(mdp, &rqp->sr2_rspsessionid);
375*adee6784SGordon Ross 	if (error)
376*adee6784SGordon Ross 		return (error);
377*adee6784SGordon Ross 
378*adee6784SGordon Ross 	/* Skip MAC Signature */
379*adee6784SGordon Ross 	error = md_get_mem(mdp, NULL, 16, MB_MSYSTEM);
380*adee6784SGordon Ross 
381*adee6784SGordon Ross 	return (error);
382*adee6784SGordon Ross }
383