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