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