xref: /illumos-gate/usr/src/common/smbsrv/smb_xdr.c (revision 3f068ebd9d125396d22997224889b677a22523fe)
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 2014 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
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
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 *
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
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
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
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
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
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
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
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_smb_uid))
242 		return (FALSE);
243 	if (!xdr_uint16_t(xdrs, &objp->ui_domain_len))
244 		return (FALSE);
245 	if (!xdr_string(xdrs, &objp->ui_domain, ~0))
246 		return (FALSE);
247 	if (!xdr_uint16_t(xdrs, &objp->ui_account_len))
248 		return (FALSE);
249 	if (!xdr_string(xdrs, &objp->ui_account, ~0))
250 		return (FALSE);
251 	if (!xdr_uint32_t(xdrs, &objp->ui_posix_uid))
252 		return (FALSE);
253 	if (!xdr_uint16_t(xdrs, &objp->ui_workstation_len))
254 		return (FALSE);
255 	if (!xdr_string(xdrs, &objp->ui_workstation, ~0))
256 		return (FALSE);
257 	if (!smb_inaddr_xdr(xdrs, &objp->ui_ipaddr))
258 		return (FALSE);
259 	if (!xdr_int32_t(xdrs, &objp->ui_native_os))
260 		return (FALSE);
261 	if (!xdr_int64_t(xdrs, &objp->ui_logon_time))
262 		return (FALSE);
263 	if (!xdr_uint32_t(xdrs, &objp->ui_numopens))
264 		return (FALSE);
265 	if (!xdr_uint32_t(xdrs, &objp->ui_flags))
266 		return (FALSE);
267 	return (TRUE);
268 }
269 
270 /*
271  * Encode an smb_netconnectinfo_t into a buffer.
272  */
273 int
274 smb_netconnectinfo_encode(smb_netconnectinfo_t *info, uint8_t *buf,
275     uint32_t buflen, uint_t *nbytes)
276 {
277 	XDR xdrs;
278 	int rc = 0;
279 
280 	xdrmem_create(&xdrs, (const caddr_t)buf, buflen, XDR_ENCODE);
281 
282 	if (!smb_netconnectinfo_xdr(&xdrs, info))
283 		rc = -1;
284 
285 	if (nbytes != NULL)
286 		*nbytes = xdr_getpos(&xdrs);
287 	xdr_destroy(&xdrs);
288 	return (rc);
289 }
290 
291 /*
292  * Decode an XDR buffer into an smb_netconnectinfo_t.
293  */
294 int
295 smb_netconnectinfo_decode(smb_netconnectinfo_t *info, uint8_t *buf,
296     uint32_t buflen, uint_t *nbytes)
297 {
298 	XDR xdrs;
299 	int rc = 0;
300 
301 	xdrmem_create(&xdrs, (const caddr_t)buf, buflen, XDR_DECODE);
302 
303 	bzero(info, sizeof (smb_netconnectinfo_t));
304 	if (!smb_netconnectinfo_xdr(&xdrs, info))
305 		rc = -1;
306 
307 	if (nbytes != NULL)
308 		*nbytes = xdr_getpos(&xdrs);
309 	xdr_destroy(&xdrs);
310 	return (rc);
311 }
312 
313 /*
314  * XDR encode/decode for smb_netconnectinfo_t.
315  */
316 bool_t
317 smb_netconnectinfo_xdr(XDR *xdrs, smb_netconnectinfo_t *objp)
318 {
319 	if (!xdr_uint32_t(xdrs, &objp->ci_id))
320 		return (FALSE);
321 	if (!xdr_uint32_t(xdrs, &objp->ci_type))
322 		return (FALSE);
323 	if (!xdr_uint32_t(xdrs, &objp->ci_numopens))
324 		return (FALSE);
325 	if (!xdr_uint32_t(xdrs, &objp->ci_numusers))
326 		return (FALSE);
327 	if (!xdr_uint32_t(xdrs, &objp->ci_time))
328 		return (FALSE);
329 	if (!xdr_uint32_t(xdrs, &objp->ci_namelen))
330 		return (FALSE);
331 	if (!xdr_uint32_t(xdrs, &objp->ci_sharelen))
332 		return (FALSE);
333 	if (!xdr_string(xdrs, &objp->ci_username, MAXNAMELEN))
334 		return (FALSE);
335 	if (!xdr_string(xdrs, &objp->ci_share, MAXNAMELEN))
336 		return (FALSE);
337 	return (TRUE);
338 }
339 
340 /*
341  * Encode an smb_netfileinfo_t into a buffer.
342  */
343 int
344 smb_netfileinfo_encode(smb_netfileinfo_t *info, uint8_t *buf,
345     uint32_t buflen, uint_t *nbytes)
346 {
347 	XDR xdrs;
348 	int rc = 0;
349 
350 	xdrmem_create(&xdrs, (const caddr_t)buf, buflen, XDR_ENCODE);
351 
352 	if (!smb_netfileinfo_xdr(&xdrs, info))
353 		rc = -1;
354 
355 	if (nbytes != NULL)
356 		*nbytes = xdr_getpos(&xdrs);
357 	xdr_destroy(&xdrs);
358 	return (rc);
359 }
360 
361 /*
362  * Decode an XDR buffer into an smb_netfileinfo_t.
363  */
364 int
365 smb_netfileinfo_decode(smb_netfileinfo_t *info, uint8_t *buf,
366     uint32_t buflen, uint_t *nbytes)
367 {
368 	XDR xdrs;
369 	int rc = 0;
370 
371 	xdrmem_create(&xdrs, (const caddr_t)buf, buflen, XDR_DECODE);
372 
373 	bzero(info, sizeof (smb_netfileinfo_t));
374 	if (!smb_netfileinfo_xdr(&xdrs, info))
375 		rc = -1;
376 
377 	if (nbytes != NULL)
378 		*nbytes = xdr_getpos(&xdrs);
379 	xdr_destroy(&xdrs);
380 	return (rc);
381 }
382 
383 /*
384  * XDR encode/decode for smb_netfileinfo_t.
385  */
386 bool_t
387 smb_netfileinfo_xdr(XDR *xdrs, smb_netfileinfo_t *objp)
388 {
389 	if (!xdr_uint16_t(xdrs, &objp->fi_fid))
390 		return (FALSE);
391 	if (!xdr_uint32_t(xdrs, &objp->fi_uniqid))
392 		return (FALSE);
393 	if (!xdr_uint32_t(xdrs, &objp->fi_permissions))
394 		return (FALSE);
395 	if (!xdr_uint32_t(xdrs, &objp->fi_numlocks))
396 		return (FALSE);
397 	if (!xdr_uint32_t(xdrs, &objp->fi_pathlen))
398 		return (FALSE);
399 	if (!xdr_uint32_t(xdrs, &objp->fi_namelen))
400 		return (FALSE);
401 	if (!xdr_string(xdrs, &objp->fi_path, MAXPATHLEN))
402 		return (FALSE);
403 	if (!xdr_string(xdrs, &objp->fi_username, MAXNAMELEN))
404 		return (FALSE);
405 	return (TRUE);
406 }
407 
408 bool_t
409 smb_gmttoken_query_xdr(XDR *xdrs, smb_gmttoken_query_t *objp)
410 {
411 	if (!xdr_uint32_t(xdrs, &objp->gtq_count)) {
412 		return (FALSE);
413 	}
414 	if (!xdr_string(xdrs, &objp->gtq_path, ~0)) {
415 		return (FALSE);
416 	}
417 	return (TRUE);
418 }
419 
420 static bool_t
421 smb_gmttoken_xdr(XDR *xdrs, smb_gmttoken_t *objp)
422 {
423 	if (!xdr_string(xdrs, objp, SMB_VSS_GMT_SIZE)) {
424 		return (FALSE);
425 	}
426 	return (TRUE);
427 }
428 
429 bool_t
430 smb_gmttoken_response_xdr(XDR *xdrs, smb_gmttoken_response_t *objp)
431 {
432 	if (!xdr_uint32_t(xdrs, &objp->gtr_count)) {
433 		return (FALSE);
434 	}
435 	if (!xdr_array(xdrs, (char **)&objp->gtr_gmttokens.gtr_gmttokens_val,
436 	    (uint_t *)&objp->gtr_gmttokens.gtr_gmttokens_len, ~0,
437 	    sizeof (smb_gmttoken_t), (xdrproc_t)smb_gmttoken_xdr)) {
438 		return (FALSE);
439 	}
440 	return (TRUE);
441 }
442 
443 bool_t
444 smb_gmttoken_snapname_xdr(XDR *xdrs, smb_gmttoken_snapname_t *objp)
445 {
446 	if (!xdr_string(xdrs, &objp->gts_path, MAXPATHLEN)) {
447 		return (FALSE);
448 	}
449 	if (!xdr_string(xdrs, &objp->gts_gmttoken, SMB_VSS_GMT_SIZE)) {
450 		return (FALSE);
451 	}
452 	if (!xdr_uint64_t(xdrs, &objp->gts_toktime)) {
453 		return (FALSE);
454 	}
455 	return (TRUE);
456 }
457 
458 bool_t
459 smb_quota_xdr(XDR *xdrs, smb_quota_t *objp)
460 {
461 	if (!xdr_vector(xdrs, (char *)objp->q_sidstr, SMB_SID_STRSZ,
462 	    sizeof (char), (xdrproc_t)xdr_char))
463 		return (FALSE);
464 	if (!xdr_uint32_t(xdrs, &objp->q_sidtype))
465 		return (FALSE);
466 	if (!xdr_uint64_t(xdrs, &objp->q_used))
467 		return (FALSE);
468 	if (!xdr_uint64_t(xdrs, &objp->q_thresh))
469 		return (FALSE);
470 	if (!xdr_uint64_t(xdrs, &objp->q_limit))
471 		return (FALSE);
472 
473 	return (TRUE);
474 }
475 
476 bool_t
477 smb_quota_sid_xdr(XDR *xdrs, smb_quota_sid_t *objp)
478 {
479 	if (!xdr_vector(xdrs, (char *)objp->qs_sidstr, SMB_SID_STRSZ,
480 	    sizeof (char), (xdrproc_t)xdr_char))
481 		return (FALSE);
482 	return (TRUE);
483 }
484 
485 bool_t
486 smb_quota_query_xdr(XDR *xdrs, smb_quota_query_t *objp)
487 {
488 	if (!xdr_string(xdrs, &objp->qq_root_path, ~0))
489 		return (FALSE);
490 	if (!xdr_uint32_t(xdrs, &objp->qq_query_op))
491 		return (FALSE);
492 	if (!xdr_bool(xdrs, &objp->qq_single))
493 		return (FALSE);
494 	if (!xdr_bool(xdrs, &objp->qq_restart))
495 		return (FALSE);
496 	if (!xdr_uint32_t(xdrs, &objp->qq_max_quota))
497 		return (FALSE);
498 	if (!smb_list_xdr(xdrs, &objp->qq_sid_list,
499 	    offsetof(smb_quota_sid_t, qs_list_node),
500 	    sizeof (smb_quota_sid_t), (xdrproc_t)smb_quota_sid_xdr))
501 		return (FALSE);
502 
503 	return (TRUE);
504 }
505 
506 bool_t
507 smb_quota_response_xdr(XDR *xdrs, smb_quota_response_t *objp)
508 {
509 	if (!xdr_uint32_t(xdrs, &objp->qr_status))
510 		return (FALSE);
511 	if (!smb_list_xdr(xdrs, &objp->qr_quota_list,
512 	    offsetof(smb_quota_t, q_list_node),
513 	    sizeof (smb_quota_t), (xdrproc_t)smb_quota_xdr))
514 		return (FALSE);
515 	return (TRUE);
516 }
517 
518 bool_t
519 smb_quota_set_xdr(XDR *xdrs, smb_quota_set_t *objp)
520 {
521 	if (!xdr_string(xdrs, &objp->qs_root_path, ~0))
522 		return (FALSE);
523 	if (!smb_list_xdr(xdrs, &objp->qs_quota_list,
524 	    offsetof(smb_quota_t, q_list_node),
525 	    sizeof (smb_quota_t), (xdrproc_t)smb_quota_xdr))
526 		return (FALSE);
527 	return (TRUE);
528 }
529 
530 /*
531  * XDR a list_t list of elements
532  * offset - offset of list_node_t in list element
533  * elsize - size of list element
534  * elproc - XDR function for the list element
535  */
536 bool_t
537 smb_list_xdr(XDR *xdrs, list_t *list,  const size_t offset,
538     const size_t elsize, const xdrproc_t elproc)
539 {
540 	void *node;
541 	uint32_t count = 0;
542 
543 	switch (xdrs->x_op) {
544 	case XDR_ENCODE:
545 		node = list_head(list);
546 		while (node) {
547 			++count;
548 			node = list_next(list, node);
549 		}
550 		if (!xdr_uint32_t(xdrs, &count))
551 			return (FALSE);
552 
553 		node = list_head(list);
554 		while (node) {
555 			if (!elproc(xdrs, node))
556 				return (FALSE);
557 			node = list_next(list, node);
558 		}
559 		return (TRUE);
560 
561 	case XDR_DECODE:
562 		if (!xdr_uint32_t(xdrs, &count))
563 			return (FALSE);
564 		list_create(list, elsize, offset);
565 		while (count) {
566 			node = MEM_MALLOC("xdr", elsize);
567 			if (node == NULL)
568 				return (FALSE);
569 			if (!elproc(xdrs, node))
570 				return (FALSE);
571 			list_insert_tail(list, node);
572 			--count;
573 		}
574 		return (TRUE);
575 
576 	case XDR_FREE:
577 		while ((node = list_head(list)) != NULL) {
578 			list_remove(list, node);
579 			(void) elproc(xdrs, node);
580 			MEM_FREE("xdr", node);
581 		}
582 		list_destroy(list);
583 		return (TRUE);
584 	}
585 
586 	return (FALSE);
587 }
588 
589 bool_t
590 dfs_target_pclass_xdr(XDR *xdrs, dfs_target_pclass_t *objp)
591 {
592 	return (xdr_enum(xdrs, (enum_t *)objp));
593 }
594 
595 bool_t
596 dfs_target_priority_xdr(XDR *xdrs, dfs_target_priority_t *objp)
597 {
598 	if (!dfs_target_pclass_xdr(xdrs, &objp->p_class))
599 		return (FALSE);
600 
601 	if (!xdr_uint16_t(xdrs, &objp->p_rank))
602 		return (FALSE);
603 
604 	return (TRUE);
605 }
606 
607 bool_t
608 dfs_target_xdr(XDR *xdrs, dfs_target_t *objp)
609 {
610 	if (!xdr_vector(xdrs, (char *)objp->t_server, DFS_SRVNAME_MAX,
611 	    sizeof (char), (xdrproc_t)xdr_char))
612 		return (FALSE);
613 
614 	if (!xdr_vector(xdrs, (char *)objp->t_share, DFS_NAME_MAX,
615 	    sizeof (char), (xdrproc_t)xdr_char))
616 		return (FALSE);
617 
618 	if (!xdr_uint32_t(xdrs, &objp->t_state))
619 		return (FALSE);
620 
621 	if (!dfs_target_priority_xdr(xdrs, &objp->t_priority))
622 		return (FALSE);
623 
624 	return (TRUE);
625 }
626 
627 bool_t
628 dfs_reftype_xdr(XDR *xdrs, dfs_reftype_t *objp)
629 {
630 	return (xdr_enum(xdrs, (enum_t *)objp));
631 }
632 
633 bool_t
634 dfs_info_xdr(XDR *xdrs, dfs_info_t *objp)
635 {
636 	if (!xdr_vector(xdrs, (char *)objp->i_uncpath, DFS_PATH_MAX,
637 	    sizeof (char), (xdrproc_t)xdr_char))
638 		return (FALSE);
639 
640 	if (!xdr_vector(xdrs, (char *)objp->i_comment, DFS_COMMENT_MAX,
641 	    sizeof (char), (xdrproc_t)xdr_char))
642 		return (FALSE);
643 
644 	if (!xdr_vector(xdrs, (char *)objp->i_guid,
645 	    UUID_PRINTABLE_STRING_LENGTH, sizeof (char), (xdrproc_t)xdr_char))
646 		return (FALSE);
647 
648 	if (!xdr_uint32_t(xdrs, &objp->i_state))
649 		return (FALSE);
650 
651 	if (!xdr_uint32_t(xdrs, &objp->i_timeout))
652 		return (FALSE);
653 
654 	if (!xdr_uint32_t(xdrs, &objp->i_propflags))
655 		return (FALSE);
656 
657 	if (!xdr_uint32_t(xdrs, &objp->i_type))
658 		return (FALSE);
659 
660 	if (!xdr_array(xdrs, (char **)&objp->i_targets,
661 	    (uint32_t *)&objp->i_ntargets, ~0, sizeof (dfs_target_t),
662 	    (xdrproc_t)dfs_target_xdr))
663 		return (FALSE);
664 
665 	return (TRUE);
666 }
667 
668 bool_t
669 dfs_referral_query_xdr(XDR *xdrs, dfs_referral_query_t *objp)
670 {
671 	if (!dfs_reftype_xdr(xdrs, &objp->rq_type))
672 		return (FALSE);
673 
674 	if (!xdr_string(xdrs, &objp->rq_path, ~0))
675 		return (FALSE);
676 
677 	return (TRUE);
678 }
679 
680 bool_t
681 dfs_referral_response_xdr(XDR *xdrs, dfs_referral_response_t *objp)
682 {
683 	if (!dfs_info_xdr(xdrs, &objp->rp_referrals))
684 		return (FALSE);
685 
686 	if (!xdr_uint32_t(xdrs, &objp->rp_status))
687 		return (FALSE);
688 
689 	return (TRUE);
690 }
691 
692 bool_t
693 smb_shr_hostaccess_query_xdr(XDR *xdrs, smb_shr_hostaccess_query_t *objp)
694 {
695 	if (!xdr_string(xdrs, &objp->shq_none, ~0))
696 		return (FALSE);
697 
698 	if (!xdr_string(xdrs, &objp->shq_ro, ~0))
699 		return (FALSE);
700 
701 	if (!xdr_string(xdrs, &objp->shq_rw, ~0))
702 		return (FALSE);
703 
704 	if (!xdr_uint32_t(xdrs, &objp->shq_flag))
705 		return (FALSE);
706 
707 	if (!smb_inaddr_xdr(xdrs, &objp->shq_ipaddr))
708 		return (FALSE);
709 
710 	return (TRUE);
711 }
712 
713 bool_t
714 smb_shr_execinfo_xdr(XDR *xdrs, smb_shr_execinfo_t *objp)
715 {
716 	if (!xdr_string(xdrs, &objp->e_sharename, ~0))
717 		return (FALSE);
718 
719 	if (!xdr_string(xdrs, &objp->e_winname, ~0))
720 		return (FALSE);
721 
722 	if (!xdr_string(xdrs, &objp->e_userdom, ~0))
723 		return (FALSE);
724 
725 	if (!smb_inaddr_xdr(xdrs, &objp->e_srv_ipaddr))
726 		return (FALSE);
727 
728 	if (!smb_inaddr_xdr(xdrs, &objp->e_cli_ipaddr))
729 		return (FALSE);
730 
731 	if (!xdr_string(xdrs, &objp->e_cli_netbiosname, ~0))
732 		return (FALSE);
733 
734 	if (!xdr_u_int(xdrs, &objp->e_uid))
735 		return (FALSE);
736 
737 	if (!xdr_int(xdrs, &objp->e_type))
738 		return (FALSE);
739 
740 	return (TRUE);
741 }
742 
743 /*
744  * The smbsrv ioctl callers include a CRC of the XDR encoded data,
745  * and kmod ioctl handler checks it.  Both use this function.  This
746  * is not really XDR related, but this is as good a place as any.
747  */
748 #define	SMB_CRC_POLYNOMIAL	0xD8B5D8B5
749 uint32_t
750 smb_crc_gen(uint8_t *buf, size_t len)
751 {
752 	uint32_t crc = SMB_CRC_POLYNOMIAL;
753 	uint8_t *p;
754 	int i;
755 
756 	for (p = buf, i = 0; i < len; ++i, ++p) {
757 		crc = (crc ^ (uint32_t)*p) + (crc << 12);
758 
759 		if (crc == 0 || crc == 0xFFFFFFFF)
760 			crc = SMB_CRC_POLYNOMIAL;
761 	}
762 
763 	return (crc);
764 }
765