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