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