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.
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.
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]
22 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
26 #include <sys/sunddi.h>
27 #if !defined(_KERNEL) && !defined(_FAKE_KERNEL)
32 #include <smbsrv/smb_door.h>
33 #include <smbsrv/alloc.h>
34 #include <sys/socket.h>
35 #include <sys/sysmacros.h>
37 #define SMB_XDRMAX32_SZ 0xFFFFFFFF
39 bool_t
smb_list_xdr(XDR
*, list_t
*, const size_t, const size_t,
43 smb_buf32_xdr(XDR
*xdrs
, smb_buf32_t
*objp
)
45 uint_t maxsize
= SMB_XDRMAX32_SZ
;
48 if (xdrs
->x_op
!= XDR_DECODE
)
49 maxsize
= size
= (uint_t
)objp
->len
;
51 if (xdr_bytes(xdrs
, (char **)&objp
->val
, &size
, maxsize
)) {
52 if (xdrs
->x_op
== XDR_DECODE
)
53 objp
->len
= (uint32_t)size
;
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.
65 * If objp->buf is NULL, xdr_string will allocate memory for the
66 * string. Otherwise it will copy into the available buffer.
69 smb_string_xdr(XDR
*xdrs
, smb_string_t
*objp
)
71 if (!xdr_string(xdrs
, &objp
->buf
, ~0))
77 smb_doorhdr_opname(uint32_t op
)
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" }
105 for (i
= 0; i
< (sizeof (ops
) / sizeof (ops
[0])); ++i
) {
107 return (ops
[i
].name
);
114 * Encode a door header structure into an XDR buffer.
117 smb_doorhdr_encode(smb_doorhdr_t
*hdr
, uint8_t *buf
, uint32_t buflen
)
122 xdrmem_create(&xdrs
, (const caddr_t
)buf
, buflen
, XDR_ENCODE
);
124 if (!smb_doorhdr_xdr(&xdrs
, hdr
))
132 * Decode an XDR buffer into a door header structure.
135 smb_doorhdr_decode(smb_doorhdr_t
*hdr
, uint8_t *buf
, uint32_t buflen
)
140 bzero(hdr
, sizeof (smb_doorhdr_t
));
141 xdrmem_create(&xdrs
, (const caddr_t
)buf
, buflen
, XDR_DECODE
);
143 if (!smb_doorhdr_xdr(&xdrs
, hdr
))
151 smb_doorhdr_xdr(XDR
*xdrs
, smb_doorhdr_t
*objp
)
153 if (!xdr_uint32_t(xdrs
, &objp
->dh_magic
))
155 if (!xdr_uint32_t(xdrs
, &objp
->dh_flags
))
157 if (!xdr_uint32_t(xdrs
, &objp
->dh_fid
))
159 if (!xdr_uint32_t(xdrs
, &objp
->dh_op
))
161 if (!xdr_uint32_t(xdrs
, &objp
->dh_txid
))
163 if (!xdr_uint32_t(xdrs
, &objp
->dh_datalen
))
165 if (!xdr_uint32_t(xdrs
, &objp
->dh_resid
))
167 if (!xdr_uint32_t(xdrs
, &objp
->dh_door_rc
))
169 if (!xdr_uint32_t(xdrs
, &objp
->dh_status
))
175 * Encode an smb_netuserinfo_t into a buffer.
178 smb_netuserinfo_encode(smb_netuserinfo_t
*info
, uint8_t *buf
,
179 uint32_t buflen
, uint_t
*nbytes
)
184 xdrmem_create(&xdrs
, (const caddr_t
)buf
, buflen
, XDR_ENCODE
);
186 if (!smb_netuserinfo_xdr(&xdrs
, info
))
190 *nbytes
= xdr_getpos(&xdrs
);
196 * Decode an XDR buffer into an smb_netuserinfo_t.
199 smb_netuserinfo_decode(smb_netuserinfo_t
*info
, uint8_t *buf
,
200 uint32_t buflen
, uint_t
*nbytes
)
205 xdrmem_create(&xdrs
, (const caddr_t
)buf
, buflen
, XDR_DECODE
);
207 bzero(info
, sizeof (smb_netuserinfo_t
));
208 if (!smb_netuserinfo_xdr(&xdrs
, info
))
212 *nbytes
= xdr_getpos(&xdrs
);
218 smb_inaddr_xdr(XDR
*xdrs
, smb_inaddr_t
*objp
)
220 if (!xdr_int32_t(xdrs
, &objp
->a_family
))
222 if (objp
->a_family
== AF_INET
) {
223 if (!xdr_uint32_t(xdrs
, (in_addr_t
*)&objp
->a_ipv4
))
226 if (!xdr_vector(xdrs
, (char *)&objp
->a_ipv6
,
227 sizeof (objp
->a_ipv6
), sizeof (char), (xdrproc_t
)xdr_char
))
234 * XDR encode/decode for smb_netuserinfo_t.
237 smb_netuserinfo_xdr(XDR
*xdrs
, smb_netuserinfo_t
*objp
)
239 if (!xdr_uint64_t(xdrs
, &objp
->ui_session_id
))
241 if (!xdr_uint16_t(xdrs
, &objp
->ui_smb_uid
))
243 if (!xdr_uint16_t(xdrs
, &objp
->ui_domain_len
))
245 if (!xdr_string(xdrs
, &objp
->ui_domain
, ~0))
247 if (!xdr_uint16_t(xdrs
, &objp
->ui_account_len
))
249 if (!xdr_string(xdrs
, &objp
->ui_account
, ~0))
251 if (!xdr_uint32_t(xdrs
, &objp
->ui_posix_uid
))
253 if (!xdr_uint16_t(xdrs
, &objp
->ui_workstation_len
))
255 if (!xdr_string(xdrs
, &objp
->ui_workstation
, ~0))
257 if (!smb_inaddr_xdr(xdrs
, &objp
->ui_ipaddr
))
259 if (!xdr_int32_t(xdrs
, &objp
->ui_native_os
))
261 if (!xdr_int64_t(xdrs
, &objp
->ui_logon_time
))
263 if (!xdr_uint32_t(xdrs
, &objp
->ui_numopens
))
265 if (!xdr_uint32_t(xdrs
, &objp
->ui_flags
))
271 * Encode an smb_netconnectinfo_t into a buffer.
274 smb_netconnectinfo_encode(smb_netconnectinfo_t
*info
, uint8_t *buf
,
275 uint32_t buflen
, uint_t
*nbytes
)
280 xdrmem_create(&xdrs
, (const caddr_t
)buf
, buflen
, XDR_ENCODE
);
282 if (!smb_netconnectinfo_xdr(&xdrs
, info
))
286 *nbytes
= xdr_getpos(&xdrs
);
292 * Decode an XDR buffer into an smb_netconnectinfo_t.
295 smb_netconnectinfo_decode(smb_netconnectinfo_t
*info
, uint8_t *buf
,
296 uint32_t buflen
, uint_t
*nbytes
)
301 xdrmem_create(&xdrs
, (const caddr_t
)buf
, buflen
, XDR_DECODE
);
303 bzero(info
, sizeof (smb_netconnectinfo_t
));
304 if (!smb_netconnectinfo_xdr(&xdrs
, info
))
308 *nbytes
= xdr_getpos(&xdrs
);
314 * XDR encode/decode for smb_netconnectinfo_t.
317 smb_netconnectinfo_xdr(XDR
*xdrs
, smb_netconnectinfo_t
*objp
)
319 if (!xdr_uint32_t(xdrs
, &objp
->ci_id
))
321 if (!xdr_uint32_t(xdrs
, &objp
->ci_type
))
323 if (!xdr_uint32_t(xdrs
, &objp
->ci_numopens
))
325 if (!xdr_uint32_t(xdrs
, &objp
->ci_numusers
))
327 if (!xdr_uint32_t(xdrs
, &objp
->ci_time
))
329 if (!xdr_uint32_t(xdrs
, &objp
->ci_namelen
))
331 if (!xdr_uint32_t(xdrs
, &objp
->ci_sharelen
))
333 if (!xdr_string(xdrs
, &objp
->ci_username
, MAXNAMELEN
))
335 if (!xdr_string(xdrs
, &objp
->ci_share
, MAXNAMELEN
))
341 * Encode an smb_netfileinfo_t into a buffer.
344 smb_netfileinfo_encode(smb_netfileinfo_t
*info
, uint8_t *buf
,
345 uint32_t buflen
, uint_t
*nbytes
)
350 xdrmem_create(&xdrs
, (const caddr_t
)buf
, buflen
, XDR_ENCODE
);
352 if (!smb_netfileinfo_xdr(&xdrs
, info
))
356 *nbytes
= xdr_getpos(&xdrs
);
362 * Decode an XDR buffer into an smb_netfileinfo_t.
365 smb_netfileinfo_decode(smb_netfileinfo_t
*info
, uint8_t *buf
,
366 uint32_t buflen
, uint_t
*nbytes
)
371 xdrmem_create(&xdrs
, (const caddr_t
)buf
, buflen
, XDR_DECODE
);
373 bzero(info
, sizeof (smb_netfileinfo_t
));
374 if (!smb_netfileinfo_xdr(&xdrs
, info
))
378 *nbytes
= xdr_getpos(&xdrs
);
384 * XDR encode/decode for smb_netfileinfo_t.
387 smb_netfileinfo_xdr(XDR
*xdrs
, smb_netfileinfo_t
*objp
)
389 if (!xdr_uint16_t(xdrs
, &objp
->fi_fid
))
391 if (!xdr_uint32_t(xdrs
, &objp
->fi_uniqid
))
393 if (!xdr_uint32_t(xdrs
, &objp
->fi_permissions
))
395 if (!xdr_uint32_t(xdrs
, &objp
->fi_numlocks
))
397 if (!xdr_uint32_t(xdrs
, &objp
->fi_pathlen
))
399 if (!xdr_uint32_t(xdrs
, &objp
->fi_namelen
))
401 if (!xdr_string(xdrs
, &objp
->fi_path
, MAXPATHLEN
))
403 if (!xdr_string(xdrs
, &objp
->fi_username
, MAXNAMELEN
))
409 smb_gmttoken_query_xdr(XDR
*xdrs
, smb_gmttoken_query_t
*objp
)
411 if (!xdr_uint32_t(xdrs
, &objp
->gtq_count
)) {
414 if (!xdr_string(xdrs
, &objp
->gtq_path
, ~0)) {
421 smb_gmttoken_xdr(XDR
*xdrs
, smb_gmttoken_t
*objp
)
423 if (!xdr_string(xdrs
, objp
, SMB_VSS_GMT_SIZE
)) {
430 smb_gmttoken_response_xdr(XDR
*xdrs
, smb_gmttoken_response_t
*objp
)
432 if (!xdr_uint32_t(xdrs
, &objp
->gtr_count
)) {
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
)) {
444 smb_gmttoken_snapname_xdr(XDR
*xdrs
, smb_gmttoken_snapname_t
*objp
)
446 if (!xdr_string(xdrs
, &objp
->gts_path
, MAXPATHLEN
)) {
449 if (!xdr_string(xdrs
, &objp
->gts_gmttoken
, SMB_VSS_GMT_SIZE
)) {
452 if (!xdr_uint64_t(xdrs
, &objp
->gts_toktime
)) {
459 smb_quota_xdr(XDR
*xdrs
, smb_quota_t
*objp
)
461 if (!xdr_vector(xdrs
, (char *)objp
->q_sidstr
, SMB_SID_STRSZ
,
462 sizeof (char), (xdrproc_t
)xdr_char
))
464 if (!xdr_uint32_t(xdrs
, &objp
->q_sidtype
))
466 if (!xdr_uint64_t(xdrs
, &objp
->q_used
))
468 if (!xdr_uint64_t(xdrs
, &objp
->q_thresh
))
470 if (!xdr_uint64_t(xdrs
, &objp
->q_limit
))
477 smb_quota_sid_xdr(XDR
*xdrs
, smb_quota_sid_t
*objp
)
479 if (!xdr_vector(xdrs
, (char *)objp
->qs_sidstr
, SMB_SID_STRSZ
,
480 sizeof (char), (xdrproc_t
)xdr_char
))
486 smb_quota_query_xdr(XDR
*xdrs
, smb_quota_query_t
*objp
)
488 if (!xdr_string(xdrs
, &objp
->qq_root_path
, ~0))
490 if (!xdr_uint32_t(xdrs
, &objp
->qq_query_op
))
492 if (!xdr_bool(xdrs
, &objp
->qq_single
))
494 if (!xdr_bool(xdrs
, &objp
->qq_restart
))
496 if (!xdr_uint32_t(xdrs
, &objp
->qq_max_quota
))
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
))
507 smb_quota_response_xdr(XDR
*xdrs
, smb_quota_response_t
*objp
)
509 if (!xdr_uint32_t(xdrs
, &objp
->qr_status
))
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
))
519 smb_quota_set_xdr(XDR
*xdrs
, smb_quota_set_t
*objp
)
521 if (!xdr_string(xdrs
, &objp
->qs_root_path
, ~0))
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
))
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
537 smb_list_xdr(XDR
*xdrs
, list_t
*list
, const size_t offset
,
538 const size_t elsize
, const xdrproc_t elproc
)
543 switch (xdrs
->x_op
) {
545 node
= list_head(list
);
548 node
= list_next(list
, node
);
550 if (!xdr_uint32_t(xdrs
, &count
))
553 node
= list_head(list
);
555 if (!elproc(xdrs
, node
))
557 node
= list_next(list
, node
);
562 if (!xdr_uint32_t(xdrs
, &count
))
564 list_create(list
, elsize
, offset
);
566 node
= MEM_MALLOC("xdr", elsize
);
569 if (!elproc(xdrs
, node
))
571 list_insert_tail(list
, node
);
577 while ((node
= list_head(list
)) != NULL
) {
578 list_remove(list
, node
);
579 (void) elproc(xdrs
, node
);
580 MEM_FREE("xdr", node
);
590 dfs_target_pclass_xdr(XDR
*xdrs
, dfs_target_pclass_t
*objp
)
592 return (xdr_enum(xdrs
, (enum_t
*)objp
));
596 dfs_target_priority_xdr(XDR
*xdrs
, dfs_target_priority_t
*objp
)
598 if (!dfs_target_pclass_xdr(xdrs
, &objp
->p_class
))
601 if (!xdr_uint16_t(xdrs
, &objp
->p_rank
))
608 dfs_target_xdr(XDR
*xdrs
, dfs_target_t
*objp
)
610 if (!xdr_vector(xdrs
, (char *)objp
->t_server
, DFS_SRVNAME_MAX
,
611 sizeof (char), (xdrproc_t
)xdr_char
))
614 if (!xdr_vector(xdrs
, (char *)objp
->t_share
, DFS_NAME_MAX
,
615 sizeof (char), (xdrproc_t
)xdr_char
))
618 if (!xdr_uint32_t(xdrs
, &objp
->t_state
))
621 if (!dfs_target_priority_xdr(xdrs
, &objp
->t_priority
))
628 dfs_reftype_xdr(XDR
*xdrs
, dfs_reftype_t
*objp
)
630 return (xdr_enum(xdrs
, (enum_t
*)objp
));
634 dfs_info_xdr(XDR
*xdrs
, dfs_info_t
*objp
)
636 if (!xdr_vector(xdrs
, (char *)objp
->i_uncpath
, DFS_PATH_MAX
,
637 sizeof (char), (xdrproc_t
)xdr_char
))
640 if (!xdr_vector(xdrs
, (char *)objp
->i_comment
, DFS_COMMENT_MAX
,
641 sizeof (char), (xdrproc_t
)xdr_char
))
644 if (!xdr_vector(xdrs
, (char *)objp
->i_guid
,
645 UUID_PRINTABLE_STRING_LENGTH
, sizeof (char), (xdrproc_t
)xdr_char
))
648 if (!xdr_uint32_t(xdrs
, &objp
->i_state
))
651 if (!xdr_uint32_t(xdrs
, &objp
->i_timeout
))
654 if (!xdr_uint32_t(xdrs
, &objp
->i_propflags
))
657 if (!xdr_uint32_t(xdrs
, &objp
->i_type
))
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
))
669 dfs_referral_query_xdr(XDR
*xdrs
, dfs_referral_query_t
*objp
)
671 if (!dfs_reftype_xdr(xdrs
, &objp
->rq_type
))
674 if (!xdr_string(xdrs
, &objp
->rq_path
, ~0))
681 dfs_referral_response_xdr(XDR
*xdrs
, dfs_referral_response_t
*objp
)
683 if (!dfs_info_xdr(xdrs
, &objp
->rp_referrals
))
686 if (!xdr_uint32_t(xdrs
, &objp
->rp_status
))
693 smb_shr_hostaccess_query_xdr(XDR
*xdrs
, smb_shr_hostaccess_query_t
*objp
)
695 if (!xdr_string(xdrs
, &objp
->shq_none
, ~0))
698 if (!xdr_string(xdrs
, &objp
->shq_ro
, ~0))
701 if (!xdr_string(xdrs
, &objp
->shq_rw
, ~0))
704 if (!xdr_uint32_t(xdrs
, &objp
->shq_flag
))
707 if (!smb_inaddr_xdr(xdrs
, &objp
->shq_ipaddr
))
714 smb_shr_execinfo_xdr(XDR
*xdrs
, smb_shr_execinfo_t
*objp
)
716 if (!xdr_string(xdrs
, &objp
->e_sharename
, ~0))
719 if (!xdr_string(xdrs
, &objp
->e_winname
, ~0))
722 if (!xdr_string(xdrs
, &objp
->e_userdom
, ~0))
725 if (!smb_inaddr_xdr(xdrs
, &objp
->e_srv_ipaddr
))
728 if (!smb_inaddr_xdr(xdrs
, &objp
->e_cli_ipaddr
))
731 if (!xdr_string(xdrs
, &objp
->e_cli_netbiosname
, ~0))
734 if (!xdr_u_int(xdrs
, &objp
->e_uid
))
737 if (!xdr_int(xdrs
, &objp
->e_type
))
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.
748 #define SMB_CRC_POLYNOMIAL 0xD8B5D8B5
750 smb_crc_gen(uint8_t *buf
, size_t len
)
752 uint32_t crc
= SMB_CRC_POLYNOMIAL
;
756 for (p
= buf
, i
= 0; i
< len
; ++i
, ++p
) {
757 crc
= (crc
^ (uint32_t)*p
) + (crc
<< 12);
759 if (crc
== 0 || crc
== 0xFFFFFFFF)
760 crc
= SMB_CRC_POLYNOMIAL
;