xref: /illumos-gate/usr/src/common/smbsrv/smb_xdr.c (revision 811599a4)
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 (c) 2010, Oracle and/or its affiliates. All rights reserved.
23  * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
24  */
25 
26 #include <sys/sunddi.h>
27 #if !defined(_KERNEL) && !defined(_FAKE_KERNEL)
28 #include <string.h>
29 #include <strings.h>
30 #include <stddef.h>
31 #endif /* _KERNEL */
32 #include <smbsrv/smb_door.h>
33 #include <smbsrv/alloc.h>
34 #include <sys/socket.h>
35 #include <sys/sysmacros.h>
36 
37 #define	SMB_XDRMAX32_SZ		0xFFFFFFFF
38 
39 bool_t smb_list_xdr(XDR *, list_t *,  const size_t, const size_t,
40     const xdrproc_t);
41 
42 bool_t
smb_buf32_xdr(XDR * xdrs,smb_buf32_t * objp)43 smb_buf32_xdr(XDR *xdrs, smb_buf32_t *objp)
44 {
45 	uint_t	maxsize = SMB_XDRMAX32_SZ;
46 	uint_t	size;
47 
48 	if (xdrs->x_op != XDR_DECODE)
49 		maxsize = size = (uint_t)objp->len;
50 
51 	if (xdr_bytes(xdrs, (char **)&objp->val, &size, maxsize)) {
52 		if (xdrs->x_op == XDR_DECODE)
53 			objp->len = (uint32_t)size;
54 		return (TRUE);
55 	}
56 
57 	return (FALSE);
58 }
59 
60 /*
61  * When decoding into a string, ensure that objp->buf is NULL or
62  * is pointing at a buffer large enough to receive the string.
63  * Don't leave it as an uninitialized pointer.
64  *
65  * If objp->buf is NULL, xdr_string will allocate memory for the
66  * string.  Otherwise it will copy into the available buffer.
67  */
68 bool_t
smb_string_xdr(XDR * xdrs,smb_string_t * objp)69 smb_string_xdr(XDR *xdrs, smb_string_t *objp)
70 {
71 	if (!xdr_string(xdrs, &objp->buf, ~0))
72 		return (FALSE);
73 	return (TRUE);
74 }
75 
76 const char *
smb_doorhdr_opname(uint32_t op)77 smb_doorhdr_opname(uint32_t op)
78 {
79 	struct {
80 		uint32_t	op;
81 		const char	*name;
82 	} ops[] = {
83 		{ SMB_DR_NULL,			"null" },
84 		{ SMB_DR_ASYNC_RESPONSE,	"async_response" },
85 		{ SMB_DR_USER_AUTH_LOGON,	"user_auth_logon" },
86 		{ SMB_DR_USER_NONAUTH_LOGON,	"user_nonauth_logon" },
87 		{ SMB_DR_USER_AUTH_LOGOFF,	"user_auth_logoff" },
88 		{ SMB_DR_LOOKUP_SID,		"lookup_sid" },
89 		{ SMB_DR_LOOKUP_NAME,		"lookup_name" },
90 		{ SMB_DR_JOIN,			"join" },
91 		{ SMB_DR_GET_DCINFO,		"get_dcinfo" },
92 		{ SMB_DR_VSS_GET_COUNT,		"vss_get_count" },
93 		{ SMB_DR_VSS_GET_SNAPSHOTS,	"vss_get_snapshots" },
94 		{ SMB_DR_VSS_MAP_GMTTOKEN,	"vss_map_gmttoken" },
95 		{ SMB_DR_ADS_FIND_HOST,		"ads_find_host" },
96 		{ SMB_DR_QUOTA_QUERY,		"quota_query" },
97 		{ SMB_DR_QUOTA_SET,		"quota_set" },
98 		{ SMB_DR_DFS_GET_REFERRALS,	"dfs_get_referrals" },
99 		{ SMB_DR_SHR_HOSTACCESS,	"share_hostaccess" },
100 		{ SMB_DR_SHR_EXEC,		"share_exec" },
101 		{ SMB_DR_NOTIFY_DC_CHANGED,	"notify_dc_changed" }
102 	};
103 	int	i;
104 
105 	for (i = 0; i < (sizeof (ops) / sizeof (ops[0])); ++i) {
106 		if (ops[i].op == op)
107 			return (ops[i].name);
108 	}
109 
110 	return ("unknown");
111 }
112 
113 /*
114  * Encode a door header structure into an XDR buffer.
115  */
116 int
smb_doorhdr_encode(smb_doorhdr_t * hdr,uint8_t * buf,uint32_t buflen)117 smb_doorhdr_encode(smb_doorhdr_t *hdr, uint8_t *buf, uint32_t buflen)
118 {
119 	XDR xdrs;
120 	int rc = 0;
121 
122 	xdrmem_create(&xdrs, (const caddr_t)buf, buflen, XDR_ENCODE);
123 
124 	if (!smb_doorhdr_xdr(&xdrs, hdr))
125 		rc = -1;
126 
127 	xdr_destroy(&xdrs);
128 	return (rc);
129 }
130 
131 /*
132  * Decode an XDR buffer into a door header structure.
133  */
134 int
smb_doorhdr_decode(smb_doorhdr_t * hdr,uint8_t * buf,uint32_t buflen)135 smb_doorhdr_decode(smb_doorhdr_t *hdr, uint8_t *buf, uint32_t buflen)
136 {
137 	XDR xdrs;
138 	int rc = 0;
139 
140 	bzero(hdr, sizeof (smb_doorhdr_t));
141 	xdrmem_create(&xdrs, (const caddr_t)buf, buflen, XDR_DECODE);
142 
143 	if (!smb_doorhdr_xdr(&xdrs, hdr))
144 		rc = -1;
145 
146 	xdr_destroy(&xdrs);
147 	return (rc);
148 }
149 
150 bool_t
smb_doorhdr_xdr(XDR * xdrs,smb_doorhdr_t * objp)151 smb_doorhdr_xdr(XDR *xdrs, smb_doorhdr_t *objp)
152 {
153 	if (!xdr_uint32_t(xdrs, &objp->dh_magic))
154 		return (FALSE);
155 	if (!xdr_uint32_t(xdrs, &objp->dh_flags))
156 		return (FALSE);
157 	if (!xdr_uint32_t(xdrs, &objp->dh_fid))
158 		return (FALSE);
159 	if (!xdr_uint32_t(xdrs, &objp->dh_op))
160 		return (FALSE);
161 	if (!xdr_uint32_t(xdrs, &objp->dh_txid))
162 		return (FALSE);
163 	if (!xdr_uint32_t(xdrs, &objp->dh_datalen))
164 		return (FALSE);
165 	if (!xdr_uint32_t(xdrs, &objp->dh_resid))
166 		return (FALSE);
167 	if (!xdr_uint32_t(xdrs, &objp->dh_door_rc))
168 		return (FALSE);
169 	if (!xdr_uint32_t(xdrs, &objp->dh_status))
170 		return (FALSE);
171 	return (TRUE);
172 }
173 
174 /*
175  * Encode an smb_netuserinfo_t into a buffer.
176  */
177 int
smb_netuserinfo_encode(smb_netuserinfo_t * info,uint8_t * buf,uint32_t buflen,uint_t * nbytes)178 smb_netuserinfo_encode(smb_netuserinfo_t *info, uint8_t *buf,
179     uint32_t buflen, uint_t *nbytes)
180 {
181 	XDR xdrs;
182 	int rc = 0;
183 
184 	xdrmem_create(&xdrs, (const caddr_t)buf, buflen, XDR_ENCODE);
185 
186 	if (!smb_netuserinfo_xdr(&xdrs, info))
187 		rc = -1;
188 
189 	if (nbytes != NULL)
190 		*nbytes = xdr_getpos(&xdrs);
191 	xdr_destroy(&xdrs);
192 	return (rc);
193 }
194 
195 /*
196  * Decode an XDR buffer into an smb_netuserinfo_t.
197  */
198 int
smb_netuserinfo_decode(smb_netuserinfo_t * info,uint8_t * buf,uint32_t buflen,uint_t * nbytes)199 smb_netuserinfo_decode(smb_netuserinfo_t *info, uint8_t *buf,
200     uint32_t buflen, uint_t *nbytes)
201 {
202 	XDR xdrs;
203 	int rc = 0;
204 
205 	xdrmem_create(&xdrs, (const caddr_t)buf, buflen, XDR_DECODE);
206 
207 	bzero(info, sizeof (smb_netuserinfo_t));
208 	if (!smb_netuserinfo_xdr(&xdrs, info))
209 		rc = -1;
210 
211 	if (nbytes != NULL)
212 		*nbytes = xdr_getpos(&xdrs);
213 	xdr_destroy(&xdrs);
214 	return (rc);
215 }
216 
217 bool_t
smb_inaddr_xdr(XDR * xdrs,smb_inaddr_t * objp)218 smb_inaddr_xdr(XDR *xdrs, smb_inaddr_t *objp)
219 {
220 	if (!xdr_int32_t(xdrs, &objp->a_family))
221 		return (FALSE);
222 	if (objp->a_family == AF_INET) {
223 		if (!xdr_uint32_t(xdrs, (in_addr_t *)&objp->a_ipv4))
224 			return (FALSE);
225 	} else {
226 		if (!xdr_vector(xdrs, (char *)&objp->a_ipv6,
227 		    sizeof (objp->a_ipv6), sizeof (char), (xdrproc_t)xdr_char))
228 			return (FALSE);
229 	}
230 	return (TRUE);
231 }
232 
233 /*
234  * XDR encode/decode for smb_netuserinfo_t.
235  */
236 bool_t
smb_netuserinfo_xdr(XDR * xdrs,smb_netuserinfo_t * objp)237 smb_netuserinfo_xdr(XDR *xdrs, smb_netuserinfo_t *objp)
238 {
239 	if (!xdr_uint64_t(xdrs, &objp->ui_session_id))
240 		return (FALSE);
241 	if (!xdr_uint16_t(xdrs, &objp->ui_domain_len))
242 		return (FALSE);
243 	if (!xdr_string(xdrs, &objp->ui_domain, ~0))
244 		return (FALSE);
245 	if (!xdr_uint16_t(xdrs, &objp->ui_account_len))
246 		return (FALSE);
247 	if (!xdr_string(xdrs, &objp->ui_account, ~0))
248 		return (FALSE);
249 	if (!xdr_uint32_t(xdrs, &objp->ui_posix_uid))
250 		return (FALSE);
251 	if (!xdr_uint16_t(xdrs, &objp->ui_workstation_len))
252 		return (FALSE);
253 	if (!xdr_string(xdrs, &objp->ui_workstation, ~0))
254 		return (FALSE);
255 	if (!smb_inaddr_xdr(xdrs, &objp->ui_ipaddr))
256 		return (FALSE);
257 	if (!xdr_int32_t(xdrs, &objp->ui_native_os))
258 		return (FALSE);
259 	if (!xdr_int64_t(xdrs, &objp->ui_logon_time))
260 		return (FALSE);
261 	if (!xdr_uint32_t(xdrs, &objp->ui_numopens))
262 		return (FALSE);
263 	if (!xdr_uint32_t(xdrs, &objp->ui_flags))
264 		return (FALSE);
265 	return (TRUE);
266 }
267 
268 /*
269  * Encode an smb_netconnectinfo_t into a buffer.
270  */
271 int
smb_netconnectinfo_encode(smb_netconnectinfo_t * info,uint8_t * buf,uint32_t buflen,uint_t * nbytes)272 smb_netconnectinfo_encode(smb_netconnectinfo_t *info, uint8_t *buf,
273     uint32_t buflen, uint_t *nbytes)
274 {
275 	XDR xdrs;
276 	int rc = 0;
277 
278 	xdrmem_create(&xdrs, (const caddr_t)buf, buflen, XDR_ENCODE);
279 
280 	if (!smb_netconnectinfo_xdr(&xdrs, info))
281 		rc = -1;
282 
283 	if (nbytes != NULL)
284 		*nbytes = xdr_getpos(&xdrs);
285 	xdr_destroy(&xdrs);
286 	return (rc);
287 }
288 
289 /*
290  * Decode an XDR buffer into an smb_netconnectinfo_t.
291  */
292 int
smb_netconnectinfo_decode(smb_netconnectinfo_t * info,uint8_t * buf,uint32_t buflen,uint_t * nbytes)293 smb_netconnectinfo_decode(smb_netconnectinfo_t *info, uint8_t *buf,
294     uint32_t buflen, uint_t *nbytes)
295 {
296 	XDR xdrs;
297 	int rc = 0;
298 
299 	xdrmem_create(&xdrs, (const caddr_t)buf, buflen, XDR_DECODE);
300 
301 	bzero(info, sizeof (smb_netconnectinfo_t));
302 	if (!smb_netconnectinfo_xdr(&xdrs, info))
303 		rc = -1;
304 
305 	if (nbytes != NULL)
306 		*nbytes = xdr_getpos(&xdrs);
307 	xdr_destroy(&xdrs);
308 	return (rc);
309 }
310 
311 /*
312  * XDR encode/decode for smb_netconnectinfo_t.
313  */
314 bool_t
smb_netconnectinfo_xdr(XDR * xdrs,smb_netconnectinfo_t * objp)315 smb_netconnectinfo_xdr(XDR *xdrs, smb_netconnectinfo_t *objp)
316 {
317 	if (!xdr_uint32_t(xdrs, &objp->ci_id))
318 		return (FALSE);
319 	if (!xdr_uint32_t(xdrs, &objp->ci_type))
320 		return (FALSE);
321 	if (!xdr_uint32_t(xdrs, &objp->ci_numopens))
322 		return (FALSE);
323 	if (!xdr_uint32_t(xdrs, &objp->ci_numusers))
324 		return (FALSE);
325 	if (!xdr_uint32_t(xdrs, &objp->ci_time))
326 		return (FALSE);
327 	if (!xdr_uint32_t(xdrs, &objp->ci_namelen))
328 		return (FALSE);
329 	if (!xdr_uint32_t(xdrs, &objp->ci_sharelen))
330 		return (FALSE);
331 	if (!xdr_string(xdrs, &objp->ci_username, MAXNAMELEN))
332 		return (FALSE);
333 	if (!xdr_string(xdrs, &objp->ci_share, MAXNAMELEN))
334 		return (FALSE);
335 	return (TRUE);
336 }
337 
338 /*
339  * Encode an smb_netfileinfo_t into a buffer.
340  */
341 int
smb_netfileinfo_encode(smb_netfileinfo_t * info,uint8_t * buf,uint32_t buflen,uint_t * nbytes)342 smb_netfileinfo_encode(smb_netfileinfo_t *info, uint8_t *buf,
343     uint32_t buflen, uint_t *nbytes)
344 {
345 	XDR xdrs;
346 	int rc = 0;
347 
348 	xdrmem_create(&xdrs, (const caddr_t)buf, buflen, XDR_ENCODE);
349 
350 	if (!smb_netfileinfo_xdr(&xdrs, info))
351 		rc = -1;
352 
353 	if (nbytes != NULL)
354 		*nbytes = xdr_getpos(&xdrs);
355 	xdr_destroy(&xdrs);
356 	return (rc);
357 }
358 
359 /*
360  * Decode an XDR buffer into an smb_netfileinfo_t.
361  */
362 int
smb_netfileinfo_decode(smb_netfileinfo_t * info,uint8_t * buf,uint32_t buflen,uint_t * nbytes)363 smb_netfileinfo_decode(smb_netfileinfo_t *info, uint8_t *buf,
364     uint32_t buflen, uint_t *nbytes)
365 {
366 	XDR xdrs;
367 	int rc = 0;
368 
369 	xdrmem_create(&xdrs, (const caddr_t)buf, buflen, XDR_DECODE);
370 
371 	bzero(info, sizeof (smb_netfileinfo_t));
372 	if (!smb_netfileinfo_xdr(&xdrs, info))
373 		rc = -1;
374 
375 	if (nbytes != NULL)
376 		*nbytes = xdr_getpos(&xdrs);
377 	xdr_destroy(&xdrs);
378 	return (rc);
379 }
380 
381 /*
382  * XDR encode/decode for smb_netfileinfo_t.
383  */
384 bool_t
smb_netfileinfo_xdr(XDR * xdrs,smb_netfileinfo_t * objp)385 smb_netfileinfo_xdr(XDR *xdrs, smb_netfileinfo_t *objp)
386 {
387 	if (!xdr_uint16_t(xdrs, &objp->fi_fid))
388 		return (FALSE);
389 	if (!xdr_uint32_t(xdrs, &objp->fi_uniqid))
390 		return (FALSE);
391 	if (!xdr_uint32_t(xdrs, &objp->fi_permissions))
392 		return (FALSE);
393 	if (!xdr_uint32_t(xdrs, &objp->fi_numlocks))
394 		return (FALSE);
395 	if (!xdr_uint32_t(xdrs, &objp->fi_pathlen))
396 		return (FALSE);
397 	if (!xdr_uint32_t(xdrs, &objp->fi_namelen))
398 		return (FALSE);
399 	if (!xdr_string(xdrs, &objp->fi_path, MAXPATHLEN))
400 		return (FALSE);
401 	if (!xdr_string(xdrs, &objp->fi_username, MAXNAMELEN))
402 		return (FALSE);
403 	return (TRUE);
404 }
405 
406 bool_t
smb_gmttoken_query_xdr(XDR * xdrs,smb_gmttoken_query_t * objp)407 smb_gmttoken_query_xdr(XDR *xdrs, smb_gmttoken_query_t *objp)
408 {
409 	if (!xdr_uint32_t(xdrs, &objp->gtq_count)) {
410 		return (FALSE);
411 	}
412 	if (!xdr_string(xdrs, &objp->gtq_path, ~0)) {
413 		return (FALSE);
414 	}
415 	return (TRUE);
416 }
417 
418 static bool_t
smb_gmttoken_xdr(XDR * xdrs,smb_gmttoken_t * objp)419 smb_gmttoken_xdr(XDR *xdrs, smb_gmttoken_t *objp)
420 {
421 	if (!xdr_string(xdrs, objp, SMB_VSS_GMT_SIZE)) {
422 		return (FALSE);
423 	}
424 	return (TRUE);
425 }
426 
427 bool_t
smb_gmttoken_response_xdr(XDR * xdrs,smb_gmttoken_response_t * objp)428 smb_gmttoken_response_xdr(XDR *xdrs, smb_gmttoken_response_t *objp)
429 {
430 	if (!xdr_uint32_t(xdrs, &objp->gtr_count)) {
431 		return (FALSE);
432 	}
433 	if (!xdr_array(xdrs, (char **)&objp->gtr_gmttokens.gtr_gmttokens_val,
434 	    (uint_t *)&objp->gtr_gmttokens.gtr_gmttokens_len, ~0,
435 	    sizeof (smb_gmttoken_t), (xdrproc_t)smb_gmttoken_xdr)) {
436 		return (FALSE);
437 	}
438 	return (TRUE);
439 }
440 
441 bool_t
smb_gmttoken_snapname_xdr(XDR * xdrs,smb_gmttoken_snapname_t * objp)442 smb_gmttoken_snapname_xdr(XDR *xdrs, smb_gmttoken_snapname_t *objp)
443 {
444 	if (!xdr_string(xdrs, &objp->gts_path, MAXPATHLEN)) {
445 		return (FALSE);
446 	}
447 	if (!xdr_string(xdrs, &objp->gts_gmttoken, SMB_VSS_GMT_SIZE)) {
448 		return (FALSE);
449 	}
450 	if (!xdr_uint64_t(xdrs, &objp->gts_toktime)) {
451 		return (FALSE);
452 	}
453 	return (TRUE);
454 }
455 
456 bool_t
smb_quota_xdr(XDR * xdrs,smb_quota_t * objp)457 smb_quota_xdr(XDR *xdrs, smb_quota_t *objp)
458 {
459 	if (!xdr_vector(xdrs, (char *)objp->q_sidstr, SMB_SID_STRSZ,
460 	    sizeof (char), (xdrproc_t)xdr_char))
461 		return (FALSE);
462 	if (!xdr_uint32_t(xdrs, &objp->q_sidtype))
463 		return (FALSE);
464 	if (!xdr_uint64_t(xdrs, &objp->q_used))
465 		return (FALSE);
466 	if (!xdr_uint64_t(xdrs, &objp->q_thresh))
467 		return (FALSE);
468 	if (!xdr_uint64_t(xdrs, &objp->q_limit))
469 		return (FALSE);
470 
471 	return (TRUE);
472 }
473 
474 bool_t
smb_quota_sid_xdr(XDR * xdrs,smb_quota_sid_t * objp)475 smb_quota_sid_xdr(XDR *xdrs, smb_quota_sid_t *objp)
476 {
477 	if (!xdr_vector(xdrs, (char *)objp->qs_sidstr, SMB_SID_STRSZ,
478 	    sizeof (char), (xdrproc_t)xdr_char))
479 		return (FALSE);
480 	return (TRUE);
481 }
482 
483 bool_t
smb_quota_query_xdr(XDR * xdrs,smb_quota_query_t * objp)484 smb_quota_query_xdr(XDR *xdrs, smb_quota_query_t *objp)
485 {
486 	if (!xdr_string(xdrs, &objp->qq_root_path, ~0))
487 		return (FALSE);
488 	if (!xdr_uint32_t(xdrs, &objp->qq_query_op))
489 		return (FALSE);
490 	if (!xdr_bool(xdrs, &objp->qq_single))
491 		return (FALSE);
492 	if (!xdr_bool(xdrs, &objp->qq_restart))
493 		return (FALSE);
494 	if (!xdr_uint32_t(xdrs, &objp->qq_max_quota))
495 		return (FALSE);
496 	if (!smb_list_xdr(xdrs, &objp->qq_sid_list,
497 	    offsetof(smb_quota_sid_t, qs_list_node),
498 	    sizeof (smb_quota_sid_t), (xdrproc_t)smb_quota_sid_xdr))
499 		return (FALSE);
500 
501 	return (TRUE);
502 }
503 
504 bool_t
smb_quota_response_xdr(XDR * xdrs,smb_quota_response_t * objp)505 smb_quota_response_xdr(XDR *xdrs, smb_quota_response_t *objp)
506 {
507 	if (!xdr_uint32_t(xdrs, &objp->qr_status))
508 		return (FALSE);
509 	if (!smb_list_xdr(xdrs, &objp->qr_quota_list,
510 	    offsetof(smb_quota_t, q_list_node),
511 	    sizeof (smb_quota_t), (xdrproc_t)smb_quota_xdr))
512 		return (FALSE);
513 	return (TRUE);
514 }
515 
516 bool_t
smb_quota_set_xdr(XDR * xdrs,smb_quota_set_t * objp)517 smb_quota_set_xdr(XDR *xdrs, smb_quota_set_t *objp)
518 {
519 	if (!xdr_string(xdrs, &objp->qs_root_path, ~0))
520 		return (FALSE);
521 	if (!smb_list_xdr(xdrs, &objp->qs_quota_list,
522 	    offsetof(smb_quota_t, q_list_node),
523 	    sizeof (smb_quota_t), (xdrproc_t)smb_quota_xdr))
524 		return (FALSE);
525 	return (TRUE);
526 }
527 
528 /*
529  * XDR a list_t list of elements
530  * offset - offset of list_node_t in list element
531  * elsize - size of list element
532  * elproc - XDR function for the list element
533  */
534 bool_t
smb_list_xdr(XDR * xdrs,list_t * list,const size_t offset,const size_t elsize,const xdrproc_t elproc)535 smb_list_xdr(XDR *xdrs, list_t *list,  const size_t offset,
536     const size_t elsize, const xdrproc_t elproc)
537 {
538 	void *node;
539 	uint32_t count = 0;
540 
541 	switch (xdrs->x_op) {
542 	case XDR_ENCODE:
543 		node = list_head(list);
544 		while (node) {
545 			++count;
546 			node = list_next(list, node);
547 		}
548 		if (!xdr_uint32_t(xdrs, &count))
549 			return (FALSE);
550 
551 		node = list_head(list);
552 		while (node) {
553 			if (!elproc(xdrs, node))
554 				return (FALSE);
555 			node = list_next(list, node);
556 		}
557 		return (TRUE);
558 
559 	case XDR_DECODE:
560 		if (!xdr_uint32_t(xdrs, &count))
561 			return (FALSE);
562 		list_create(list, elsize, offset);
563 		while (count) {
564 			node = MEM_MALLOC("xdr", elsize);
565 			if (node == NULL)
566 				return (FALSE);
567 			if (!elproc(xdrs, node))
568 				return (FALSE);
569 			list_insert_tail(list, node);
570 			--count;
571 		}
572 		return (TRUE);
573 
574 	case XDR_FREE:
575 		while ((node = list_head(list)) != NULL) {
576 			list_remove(list, node);
577 			(void) elproc(xdrs, node);
578 			MEM_FREE("xdr", node);
579 		}
580 		list_destroy(list);
581 		return (TRUE);
582 	}
583 
584 	return (FALSE);
585 }
586 
587 bool_t
dfs_target_pclass_xdr(XDR * xdrs,dfs_target_pclass_t * objp)588 dfs_target_pclass_xdr(XDR *xdrs, dfs_target_pclass_t *objp)
589 {
590 	return (xdr_enum(xdrs, (enum_t *)objp));
591 }
592 
593 bool_t
dfs_target_priority_xdr(XDR * xdrs,dfs_target_priority_t * objp)594 dfs_target_priority_xdr(XDR *xdrs, dfs_target_priority_t *objp)
595 {
596 	if (!dfs_target_pclass_xdr(xdrs, &objp->p_class))
597 		return (FALSE);
598 
599 	if (!xdr_uint16_t(xdrs, &objp->p_rank))
600 		return (FALSE);
601 
602 	return (TRUE);
603 }
604 
605 bool_t
dfs_target_xdr(XDR * xdrs,dfs_target_t * objp)606 dfs_target_xdr(XDR *xdrs, dfs_target_t *objp)
607 {
608 	if (!xdr_vector(xdrs, (char *)objp->t_server, DFS_SRVNAME_MAX,
609 	    sizeof (char), (xdrproc_t)xdr_char))
610 		return (FALSE);
611 
612 	if (!xdr_vector(xdrs, (char *)objp->t_share, DFS_NAME_MAX,
613 	    sizeof (char), (xdrproc_t)xdr_char))
614 		return (FALSE);
615 
616 	if (!xdr_uint32_t(xdrs, &objp->t_state))
617 		return (FALSE);
618 
619 	if (!dfs_target_priority_xdr(xdrs, &objp->t_priority))
620 		return (FALSE);
621 
622 	return (TRUE);
623 }
624 
625 bool_t
dfs_reftype_xdr(XDR * xdrs,dfs_reftype_t * objp)626 dfs_reftype_xdr(XDR *xdrs, dfs_reftype_t *objp)
627 {
628 	return (xdr_enum(xdrs, (enum_t *)objp));
629 }
630 
631 bool_t
dfs_info_xdr(XDR * xdrs,dfs_info_t * objp)632 dfs_info_xdr(XDR *xdrs, dfs_info_t *objp)
633 {
634 	if (!xdr_vector(xdrs, (char *)objp->i_uncpath, DFS_PATH_MAX,
635 	    sizeof (char), (xdrproc_t)xdr_char))
636 		return (FALSE);
637 
638 	if (!xdr_vector(xdrs, (char *)objp->i_comment, DFS_COMMENT_MAX,
639 	    sizeof (char), (xdrproc_t)xdr_char))
640 		return (FALSE);
641 
642 	if (!xdr_vector(xdrs, (char *)objp->i_guid,
643 	    UUID_PRINTABLE_STRING_LENGTH, sizeof (char), (xdrproc_t)xdr_char))
644 		return (FALSE);
645 
646 	if (!xdr_uint32_t(xdrs, &objp->i_state))
647 		return (FALSE);
648 
649 	if (!xdr_uint32_t(xdrs, &objp->i_timeout))
650 		return (FALSE);
651 
652 	if (!xdr_uint32_t(xdrs, &objp->i_propflags))
653 		return (FALSE);
654 
655 	if (!xdr_uint32_t(xdrs, &objp->i_type))
656 		return (FALSE);
657 
658 	if (!xdr_array(xdrs, (char **)&objp->i_targets,
659 	    (uint32_t *)&objp->i_ntargets, ~0, sizeof (dfs_target_t),
660 	    (xdrproc_t)dfs_target_xdr))
661 		return (FALSE);
662 
663 	return (TRUE);
664 }
665 
666 bool_t
dfs_referral_query_xdr(XDR * xdrs,dfs_referral_query_t * objp)667 dfs_referral_query_xdr(XDR *xdrs, dfs_referral_query_t *objp)
668 {
669 	if (!dfs_reftype_xdr(xdrs, &objp->rq_type))
670 		return (FALSE);
671 
672 	if (!xdr_string(xdrs, &objp->rq_path, ~0))
673 		return (FALSE);
674 
675 	return (TRUE);
676 }
677 
678 bool_t
dfs_referral_response_xdr(XDR * xdrs,dfs_referral_response_t * objp)679 dfs_referral_response_xdr(XDR *xdrs, dfs_referral_response_t *objp)
680 {
681 	if (!dfs_info_xdr(xdrs, &objp->rp_referrals))
682 		return (FALSE);
683 
684 	if (!xdr_uint32_t(xdrs, &objp->rp_status))
685 		return (FALSE);
686 
687 	return (TRUE);
688 }
689 
690 bool_t
smb_shr_hostaccess_query_xdr(XDR * xdrs,smb_shr_hostaccess_query_t * objp)691 smb_shr_hostaccess_query_xdr(XDR *xdrs, smb_shr_hostaccess_query_t *objp)
692 {
693 	if (!xdr_string(xdrs, &objp->shq_none, ~0))
694 		return (FALSE);
695 
696 	if (!xdr_string(xdrs, &objp->shq_ro, ~0))
697 		return (FALSE);
698 
699 	if (!xdr_string(xdrs, &objp->shq_rw, ~0))
700 		return (FALSE);
701 
702 	if (!xdr_uint32_t(xdrs, &objp->shq_flag))
703 		return (FALSE);
704 
705 	if (!smb_inaddr_xdr(xdrs, &objp->shq_ipaddr))
706 		return (FALSE);
707 
708 	return (TRUE);
709 }
710 
711 bool_t
smb_shr_execinfo_xdr(XDR * xdrs,smb_shr_execinfo_t * objp)712 smb_shr_execinfo_xdr(XDR *xdrs, smb_shr_execinfo_t *objp)
713 {
714 	if (!xdr_string(xdrs, &objp->e_sharename, ~0))
715 		return (FALSE);
716 
717 	if (!xdr_string(xdrs, &objp->e_winname, ~0))
718 		return (FALSE);
719 
720 	if (!xdr_string(xdrs, &objp->e_userdom, ~0))
721 		return (FALSE);
722 
723 	if (!smb_inaddr_xdr(xdrs, &objp->e_srv_ipaddr))
724 		return (FALSE);
725 
726 	if (!smb_inaddr_xdr(xdrs, &objp->e_cli_ipaddr))
727 		return (FALSE);
728 
729 	if (!xdr_string(xdrs, &objp->e_cli_netbiosname, ~0))
730 		return (FALSE);
731 
732 	if (!xdr_u_int(xdrs, &objp->e_uid))
733 		return (FALSE);
734 
735 	if (!xdr_int(xdrs, &objp->e_type))
736 		return (FALSE);
737 
738 	return (TRUE);
739 }
740 
741 /*
742  * The smbsrv ioctl callers include a CRC of the XDR encoded data,
743  * and kmod ioctl handler checks it.  Both use this function.  This
744  * is not really XDR related, but this is as good a place as any.
745  */
746 #define	SMB_CRC_POLYNOMIAL	0xD8B5D8B5
747 uint32_t
smb_crc_gen(uint8_t * buf,size_t len)748 smb_crc_gen(uint8_t *buf, size_t len)
749 {
750 	uint32_t crc = SMB_CRC_POLYNOMIAL;
751 	uint8_t *p;
752 	int i;
753 
754 	for (p = buf, i = 0; i < len; ++i, ++p) {
755 		crc = (crc ^ (uint32_t)*p) + (crc << 12);
756 
757 		if (crc == 0 || crc == 0xFFFFFFFF)
758 			crc = SMB_CRC_POLYNOMIAL;
759 	}
760 
761 	return (crc);
762 }
763