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 2012 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" }
104 for (i
= 0; i
< (sizeof (ops
) / sizeof (ops
[0])); ++i
) {
106 return (ops
[i
].name
);
113 * Encode a door header structure into an XDR buffer.
116 smb_doorhdr_encode(smb_doorhdr_t
*hdr
, uint8_t *buf
, uint32_t buflen
)
121 xdrmem_create(&xdrs
, (const caddr_t
)buf
, buflen
, XDR_ENCODE
);
123 if (!smb_doorhdr_xdr(&xdrs
, hdr
))
131 * Decode an XDR buffer into a door header structure.
134 smb_doorhdr_decode(smb_doorhdr_t
*hdr
, uint8_t *buf
, uint32_t buflen
)
139 bzero(hdr
, sizeof (smb_doorhdr_t
));
140 xdrmem_create(&xdrs
, (const caddr_t
)buf
, buflen
, XDR_DECODE
);
142 if (!smb_doorhdr_xdr(&xdrs
, hdr
))
150 smb_doorhdr_xdr(XDR
*xdrs
, smb_doorhdr_t
*objp
)
152 if (!xdr_uint32_t(xdrs
, &objp
->dh_magic
))
154 if (!xdr_uint32_t(xdrs
, &objp
->dh_flags
))
156 if (!xdr_uint32_t(xdrs
, &objp
->dh_fid
))
158 if (!xdr_uint32_t(xdrs
, &objp
->dh_op
))
160 if (!xdr_uint32_t(xdrs
, &objp
->dh_txid
))
162 if (!xdr_uint32_t(xdrs
, &objp
->dh_datalen
))
164 if (!xdr_uint32_t(xdrs
, &objp
->dh_resid
))
166 if (!xdr_uint32_t(xdrs
, &objp
->dh_door_rc
))
168 if (!xdr_uint32_t(xdrs
, &objp
->dh_status
))
174 * Encode an smb_netuserinfo_t into a buffer.
177 smb_netuserinfo_encode(smb_netuserinfo_t
*info
, uint8_t *buf
,
178 uint32_t buflen
, uint_t
*nbytes
)
183 xdrmem_create(&xdrs
, (const caddr_t
)buf
, buflen
, XDR_ENCODE
);
185 if (!smb_netuserinfo_xdr(&xdrs
, info
))
189 *nbytes
= xdr_getpos(&xdrs
);
195 * Decode an XDR buffer into an smb_netuserinfo_t.
198 smb_netuserinfo_decode(smb_netuserinfo_t
*info
, uint8_t *buf
,
199 uint32_t buflen
, uint_t
*nbytes
)
204 xdrmem_create(&xdrs
, (const caddr_t
)buf
, buflen
, XDR_DECODE
);
206 bzero(info
, sizeof (smb_netuserinfo_t
));
207 if (!smb_netuserinfo_xdr(&xdrs
, info
))
211 *nbytes
= xdr_getpos(&xdrs
);
217 smb_inaddr_xdr(XDR
*xdrs
, smb_inaddr_t
*objp
)
219 if (!xdr_int32_t(xdrs
, &objp
->a_family
))
221 if (objp
->a_family
== AF_INET
) {
222 if (!xdr_uint32_t(xdrs
, (in_addr_t
*)&objp
->a_ipv4
))
225 if (!xdr_vector(xdrs
, (char *)&objp
->a_ipv6
,
226 sizeof (objp
->a_ipv6
), sizeof (char), (xdrproc_t
)xdr_char
))
233 * XDR encode/decode for smb_netuserinfo_t.
236 smb_netuserinfo_xdr(XDR
*xdrs
, smb_netuserinfo_t
*objp
)
238 if (!xdr_uint64_t(xdrs
, &objp
->ui_session_id
))
240 if (!xdr_uint16_t(xdrs
, &objp
->ui_smb_uid
))
242 if (!xdr_uint16_t(xdrs
, &objp
->ui_domain_len
))
244 if (!xdr_string(xdrs
, &objp
->ui_domain
, ~0))
246 if (!xdr_uint16_t(xdrs
, &objp
->ui_account_len
))
248 if (!xdr_string(xdrs
, &objp
->ui_account
, ~0))
250 if (!xdr_uint32_t(xdrs
, &objp
->ui_posix_uid
))
252 if (!xdr_uint16_t(xdrs
, &objp
->ui_workstation_len
))
254 if (!xdr_string(xdrs
, &objp
->ui_workstation
, ~0))
256 if (!smb_inaddr_xdr(xdrs
, &objp
->ui_ipaddr
))
258 if (!xdr_int32_t(xdrs
, &objp
->ui_native_os
))
260 if (!xdr_int64_t(xdrs
, &objp
->ui_logon_time
))
262 if (!xdr_uint32_t(xdrs
, &objp
->ui_numopens
))
264 if (!xdr_uint32_t(xdrs
, &objp
->ui_flags
))
270 * Encode an smb_netconnectinfo_t into a buffer.
273 smb_netconnectinfo_encode(smb_netconnectinfo_t
*info
, uint8_t *buf
,
274 uint32_t buflen
, uint_t
*nbytes
)
279 xdrmem_create(&xdrs
, (const caddr_t
)buf
, buflen
, XDR_ENCODE
);
281 if (!smb_netconnectinfo_xdr(&xdrs
, info
))
285 *nbytes
= xdr_getpos(&xdrs
);
291 * Decode an XDR buffer into an smb_netconnectinfo_t.
294 smb_netconnectinfo_decode(smb_netconnectinfo_t
*info
, uint8_t *buf
,
295 uint32_t buflen
, uint_t
*nbytes
)
300 xdrmem_create(&xdrs
, (const caddr_t
)buf
, buflen
, XDR_DECODE
);
302 bzero(info
, sizeof (smb_netconnectinfo_t
));
303 if (!smb_netconnectinfo_xdr(&xdrs
, info
))
307 *nbytes
= xdr_getpos(&xdrs
);
313 * XDR encode/decode for smb_netconnectinfo_t.
316 smb_netconnectinfo_xdr(XDR
*xdrs
, smb_netconnectinfo_t
*objp
)
318 if (!xdr_uint32_t(xdrs
, &objp
->ci_id
))
320 if (!xdr_uint32_t(xdrs
, &objp
->ci_type
))
322 if (!xdr_uint32_t(xdrs
, &objp
->ci_numopens
))
324 if (!xdr_uint32_t(xdrs
, &objp
->ci_numusers
))
326 if (!xdr_uint32_t(xdrs
, &objp
->ci_time
))
328 if (!xdr_uint32_t(xdrs
, &objp
->ci_namelen
))
330 if (!xdr_uint32_t(xdrs
, &objp
->ci_sharelen
))
332 if (!xdr_string(xdrs
, &objp
->ci_username
, MAXNAMELEN
))
334 if (!xdr_string(xdrs
, &objp
->ci_share
, MAXNAMELEN
))
340 * Encode an smb_netfileinfo_t into a buffer.
343 smb_netfileinfo_encode(smb_netfileinfo_t
*info
, uint8_t *buf
,
344 uint32_t buflen
, uint_t
*nbytes
)
349 xdrmem_create(&xdrs
, (const caddr_t
)buf
, buflen
, XDR_ENCODE
);
351 if (!smb_netfileinfo_xdr(&xdrs
, info
))
355 *nbytes
= xdr_getpos(&xdrs
);
361 * Decode an XDR buffer into an smb_netfileinfo_t.
364 smb_netfileinfo_decode(smb_netfileinfo_t
*info
, uint8_t *buf
,
365 uint32_t buflen
, uint_t
*nbytes
)
370 xdrmem_create(&xdrs
, (const caddr_t
)buf
, buflen
, XDR_DECODE
);
372 bzero(info
, sizeof (smb_netfileinfo_t
));
373 if (!smb_netfileinfo_xdr(&xdrs
, info
))
377 *nbytes
= xdr_getpos(&xdrs
);
383 * XDR encode/decode for smb_netfileinfo_t.
386 smb_netfileinfo_xdr(XDR
*xdrs
, smb_netfileinfo_t
*objp
)
388 if (!xdr_uint16_t(xdrs
, &objp
->fi_fid
))
390 if (!xdr_uint32_t(xdrs
, &objp
->fi_uniqid
))
392 if (!xdr_uint32_t(xdrs
, &objp
->fi_permissions
))
394 if (!xdr_uint32_t(xdrs
, &objp
->fi_numlocks
))
396 if (!xdr_uint32_t(xdrs
, &objp
->fi_pathlen
))
398 if (!xdr_uint32_t(xdrs
, &objp
->fi_namelen
))
400 if (!xdr_string(xdrs
, &objp
->fi_path
, MAXPATHLEN
))
402 if (!xdr_string(xdrs
, &objp
->fi_username
, MAXNAMELEN
))
408 smb_gmttoken_query_xdr(XDR
*xdrs
, smb_gmttoken_query_t
*objp
)
410 if (!xdr_uint32_t(xdrs
, &objp
->gtq_count
)) {
413 if (!xdr_string(xdrs
, &objp
->gtq_path
, ~0)) {
420 smb_gmttoken_xdr(XDR
*xdrs
, smb_gmttoken_t
*objp
)
422 if (!xdr_string(xdrs
, objp
, SMB_VSS_GMT_SIZE
)) {
429 smb_gmttoken_response_xdr(XDR
*xdrs
, smb_gmttoken_response_t
*objp
)
431 if (!xdr_uint32_t(xdrs
, &objp
->gtr_count
)) {
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
)) {
443 smb_gmttoken_snapname_xdr(XDR
*xdrs
, smb_gmttoken_snapname_t
*objp
)
445 if (!xdr_string(xdrs
, &objp
->gts_path
, MAXPATHLEN
)) {
448 if (!xdr_string(xdrs
, &objp
->gts_gmttoken
, SMB_VSS_GMT_SIZE
)) {
455 smb_quota_xdr(XDR
*xdrs
, smb_quota_t
*objp
)
457 if (!xdr_vector(xdrs
, (char *)objp
->q_sidstr
, SMB_SID_STRSZ
,
458 sizeof (char), (xdrproc_t
)xdr_char
))
460 if (!xdr_uint32_t(xdrs
, &objp
->q_sidtype
))
462 if (!xdr_uint64_t(xdrs
, &objp
->q_used
))
464 if (!xdr_uint64_t(xdrs
, &objp
->q_thresh
))
466 if (!xdr_uint64_t(xdrs
, &objp
->q_limit
))
473 smb_quota_sid_xdr(XDR
*xdrs
, smb_quota_sid_t
*objp
)
475 if (!xdr_vector(xdrs
, (char *)objp
->qs_sidstr
, SMB_SID_STRSZ
,
476 sizeof (char), (xdrproc_t
)xdr_char
))
482 smb_quota_query_xdr(XDR
*xdrs
, smb_quota_query_t
*objp
)
484 if (!xdr_string(xdrs
, &objp
->qq_root_path
, ~0))
486 if (!xdr_uint32_t(xdrs
, &objp
->qq_query_op
))
488 if (!xdr_bool(xdrs
, &objp
->qq_single
))
490 if (!xdr_bool(xdrs
, &objp
->qq_restart
))
492 if (!xdr_uint32_t(xdrs
, &objp
->qq_max_quota
))
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
))
503 smb_quota_response_xdr(XDR
*xdrs
, smb_quota_response_t
*objp
)
505 if (!xdr_uint32_t(xdrs
, &objp
->qr_status
))
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
))
515 smb_quota_set_xdr(XDR
*xdrs
, smb_quota_set_t
*objp
)
517 if (!xdr_string(xdrs
, &objp
->qs_root_path
, ~0))
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
))
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
533 smb_list_xdr(XDR
*xdrs
, list_t
*list
, const size_t offset
,
534 const size_t elsize
, const xdrproc_t elproc
)
539 switch (xdrs
->x_op
) {
541 node
= list_head(list
);
544 node
= list_next(list
, node
);
546 if (!xdr_uint32_t(xdrs
, &count
))
549 node
= list_head(list
);
551 if (!elproc(xdrs
, node
))
553 node
= list_next(list
, node
);
558 if (!xdr_uint32_t(xdrs
, &count
))
560 list_create(list
, elsize
, offset
);
562 node
= MEM_MALLOC("xdr", elsize
);
565 if (!elproc(xdrs
, node
))
567 list_insert_tail(list
, node
);
573 while ((node
= list_head(list
)) != NULL
) {
574 list_remove(list
, node
);
575 (void) elproc(xdrs
, node
);
576 MEM_FREE("xdr", node
);
586 dfs_target_pclass_xdr(XDR
*xdrs
, dfs_target_pclass_t
*objp
)
588 return (xdr_enum(xdrs
, (enum_t
*)objp
));
592 dfs_target_priority_xdr(XDR
*xdrs
, dfs_target_priority_t
*objp
)
594 if (!dfs_target_pclass_xdr(xdrs
, &objp
->p_class
))
597 if (!xdr_uint16_t(xdrs
, &objp
->p_rank
))
604 dfs_target_xdr(XDR
*xdrs
, dfs_target_t
*objp
)
606 if (!xdr_vector(xdrs
, (char *)objp
->t_server
, DFS_SRVNAME_MAX
,
607 sizeof (char), (xdrproc_t
)xdr_char
))
610 if (!xdr_vector(xdrs
, (char *)objp
->t_share
, DFS_NAME_MAX
,
611 sizeof (char), (xdrproc_t
)xdr_char
))
614 if (!xdr_uint32_t(xdrs
, &objp
->t_state
))
617 if (!dfs_target_priority_xdr(xdrs
, &objp
->t_priority
))
624 dfs_reftype_xdr(XDR
*xdrs
, dfs_reftype_t
*objp
)
626 return (xdr_enum(xdrs
, (enum_t
*)objp
));
630 dfs_info_xdr(XDR
*xdrs
, dfs_info_t
*objp
)
632 if (!xdr_vector(xdrs
, (char *)objp
->i_uncpath
, DFS_PATH_MAX
,
633 sizeof (char), (xdrproc_t
)xdr_char
))
636 if (!xdr_vector(xdrs
, (char *)objp
->i_comment
, DFS_COMMENT_MAX
,
637 sizeof (char), (xdrproc_t
)xdr_char
))
640 if (!xdr_vector(xdrs
, (char *)objp
->i_guid
,
641 UUID_PRINTABLE_STRING_LENGTH
, sizeof (char), (xdrproc_t
)xdr_char
))
644 if (!xdr_uint32_t(xdrs
, &objp
->i_state
))
647 if (!xdr_uint32_t(xdrs
, &objp
->i_timeout
))
650 if (!xdr_uint32_t(xdrs
, &objp
->i_propflags
))
653 if (!xdr_uint32_t(xdrs
, &objp
->i_type
))
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
))
665 dfs_referral_query_xdr(XDR
*xdrs
, dfs_referral_query_t
*objp
)
667 if (!dfs_reftype_xdr(xdrs
, &objp
->rq_type
))
670 if (!xdr_string(xdrs
, &objp
->rq_path
, ~0))
677 dfs_referral_response_xdr(XDR
*xdrs
, dfs_referral_response_t
*objp
)
679 if (!dfs_info_xdr(xdrs
, &objp
->rp_referrals
))
682 if (!xdr_uint32_t(xdrs
, &objp
->rp_status
))
689 smb_shr_hostaccess_query_xdr(XDR
*xdrs
, smb_shr_hostaccess_query_t
*objp
)
691 if (!xdr_string(xdrs
, &objp
->shq_none
, ~0))
694 if (!xdr_string(xdrs
, &objp
->shq_ro
, ~0))
697 if (!xdr_string(xdrs
, &objp
->shq_rw
, ~0))
700 if (!xdr_uint32_t(xdrs
, &objp
->shq_flag
))
703 if (!smb_inaddr_xdr(xdrs
, &objp
->shq_ipaddr
))
710 smb_shr_execinfo_xdr(XDR
*xdrs
, smb_shr_execinfo_t
*objp
)
712 if (!xdr_string(xdrs
, &objp
->e_sharename
, ~0))
715 if (!xdr_string(xdrs
, &objp
->e_winname
, ~0))
718 if (!xdr_string(xdrs
, &objp
->e_userdom
, ~0))
721 if (!smb_inaddr_xdr(xdrs
, &objp
->e_srv_ipaddr
))
724 if (!smb_inaddr_xdr(xdrs
, &objp
->e_cli_ipaddr
))
727 if (!xdr_string(xdrs
, &objp
->e_cli_netbiosname
, ~0))
730 if (!xdr_u_int(xdrs
, &objp
->e_uid
))
733 if (!xdr_int(xdrs
, &objp
->e_type
))
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.
744 #define SMB_CRC_POLYNOMIAL 0xD8B5D8B5
746 smb_crc_gen(uint8_t *buf
, size_t len
)
748 uint32_t crc
= SMB_CRC_POLYNOMIAL
;
752 for (p
= buf
, i
= 0; i
< len
; ++i
, ++p
) {
753 crc
= (crc
^ (uint32_t)*p
) + (crc
<< 12);
755 if (crc
== 0 || crc
== 0xFFFFFFFF)
756 crc
= SMB_CRC_POLYNOMIAL
;