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