Print this page
1575 untangle libmlrpc ... (smbsrv)

Split Close
Expand all
Collapse all
          --- old/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_client.c
          +++ new/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_client.c
↓ open down ↓ 31 lines elided ↑ open up ↑
  32   32  #include <sys/errno.h>
  33   33  #include <sys/fcntl.h>
  34   34  #include <time.h>
  35   35  #include <strings.h>
  36   36  #include <assert.h>
  37   37  #include <errno.h>
  38   38  #include <thread.h>
  39   39  #include <syslog.h>
  40   40  #include <synch.h>
  41   41  
       42 +#include <libmlrpc/libmlrpc.h>
  42   43  #include <netsmb/smbfs_api.h>
       44 +
  43   45  #include <smbsrv/libsmb.h>
  44      -#include <smbsrv/libsmbns.h>
  45      -#include <smbsrv/libmlrpc.h>
  46   46  #include <smbsrv/libmlsvc.h>
  47      -#include <smbsrv/ndl/srvsvc.ndl>
  48   47  #include <libsmbrdr.h>
  49   48  #include <mlsvc.h>
  50   49  
  51   50  
  52   51  /*
  53   52   * This call must be made to initialize an RPC client structure and bind
  54   53   * to the remote service before any RPCs can be exchanged with that service.
  55   54   *
  56   55   * The mlsvc_handle_t is a wrapper that is used to associate an RPC handle
  57   56   * with the client context for an instance of the interface.  The handle
  58   57   * is zeroed to ensure that it doesn't look like a valid handle -
  59   58   * handle content is provided by the remove service.
  60   59   *
  61   60   * The client points to this top-level handle so that we know when to
  62   61   * unbind and teardown the connection.  As each handle is initialized it
  63   62   * will inherit a reference to the client context.
  64   63   *
  65      - * Returns 0 or an NT_STATUS:
       64 + * Returns 0 or an NT_STATUS:           (failed in...)
       65 + *
  66   66   *      NT_STATUS_BAD_NETWORK_PATH      (get server addr)
  67   67   *      NT_STATUS_NETWORK_ACCESS_DENIED (connect, auth)
  68      - *      NT_STATUS_BAD_NETWORK_NAME      (tcon, open)
       68 + *      NT_STATUS_BAD_NETWORK_NAME      (tcon)
       69 + *      RPC_NT_SERVER_TOO_BUSY          (open pipe)
       70 + *      RPC_NT_SERVER_UNAVAILABLE       (open pipe)
  69   71   *      NT_STATUS_ACCESS_DENIED         (open pipe)
  70   72   *      NT_STATUS_INVALID_PARAMETER     (rpc bind)
  71      - *
  72   73   *      NT_STATUS_INTERNAL_ERROR        (bad args etc)
  73   74   *      NT_STATUS_NO_MEMORY
  74   75   */
  75   76  DWORD
  76   77  ndr_rpc_bind(mlsvc_handle_t *handle, char *server, char *domain,
  77   78      char *username, const char *service)
  78   79  {
  79   80          struct smb_ctx          *ctx = NULL;
  80      -        ndr_client_t            *clnt = NULL;
  81   81          ndr_service_t           *svc;
  82   82          DWORD                   status;
  83      -        int                     fd = -1;
  84   83          int                     rc;
  85   84  
  86   85          if (handle == NULL || server == NULL || server[0] == '\0' ||
  87   86              domain == NULL || username == NULL)
  88   87                  return (NT_STATUS_INTERNAL_ERROR);
  89   88  
  90   89          /* In case the service was not registered... */
  91   90          if ((svc = ndr_svc_lookup_name(service)) == NULL)
  92   91                  return (NT_STATUS_INTERNAL_ERROR);
  93   92  
↓ open down ↓ 12 lines elided ↑ open up ↑
 106  105           *      NT_STATUS_BAD_NETWORK_PATH      (get server addr)
 107  106           *      NT_STATUS_NETWORK_ACCESS_DENIED (connect, auth)
 108  107           *      NT_STATUS_BAD_NETWORK_NAME      (tcon)
 109  108           */
 110  109          status = smbrdr_ctx_new(&ctx, server, domain, username);
 111  110          if (status != NT_STATUS_SUCCESS) {
 112  111                  syslog(LOG_ERR, "ndr_rpc_bind: smbrdr_ctx_new"
 113  112                      "(Srv=%s Dom=%s User=%s), %s (0x%x)",
 114  113                      server, domain, username,
 115  114                      xlate_nt_status(status), status);
 116      -                /* Tell the DC Locator this DC failed. */
 117      -                smb_ddiscover_bad_dc(server);
 118      -                goto errout;
 119      -        }
 120      -
 121      -        /*
 122      -         * Open the named pipe.
 123      -         */
 124      -        fd = smb_fh_open(ctx, svc->endpoint, O_RDWR);
 125      -        if (fd < 0) {
 126      -                rc = errno;
 127      -                syslog(LOG_DEBUG, "ndr_rpc_bind: "
 128      -                    "smb_fh_open (%s) err=%d",
 129      -                    svc->endpoint, rc);
 130      -                switch (rc) {
 131      -                case EACCES:
 132      -                        status = NT_STATUS_ACCESS_DENIED;
 133      -                        break;
      115 +                /*
      116 +                 * If the error is one where changing to a new DC
      117 +                 * might help, try looking for a different DC.
      118 +                 */
      119 +                switch (status) {
      120 +                case NT_STATUS_BAD_NETWORK_PATH:
      121 +                case NT_STATUS_BAD_NETWORK_NAME:
      122 +                        /* Look for a new DC */
      123 +                        smb_ddiscover_bad_dc(server);
 134  124                  default:
 135      -                        status = NT_STATUS_BAD_NETWORK_NAME;
 136  125                          break;
 137  126                  }
 138      -                goto errout;
      127 +                return (status);
 139  128          }
 140  129  
 141  130          /*
 142  131           * Setup the RPC client handle.
 143  132           */
 144      -        if ((clnt = malloc(sizeof (ndr_client_t))) == NULL) {
 145      -                status = NT_STATUS_NO_MEMORY;
 146      -                goto errout;
      133 +        rc = mlrpc_clh_create(handle, ctx);
      134 +        if (rc != 0) {
      135 +                syslog(LOG_ERR, "ndr_rpc_bind: mlrpc_clh_create: rc=%d", rc);
      136 +                smbrdr_ctx_free(ctx);
      137 +                switch (rc) {
      138 +                case ENOMEM:
      139 +                        return (NT_STATUS_NO_MEMORY);
      140 +                case EINVAL:
      141 +                        return (NT_STATUS_INVALID_PARAMETER);
      142 +                default:
      143 +                        return (NT_STATUS_INTERNAL_ERROR);
      144 +                }
 147  145          }
 148      -        bzero(clnt, sizeof (ndr_client_t));
 149  146  
 150      -        clnt->handle = &handle->handle;
 151      -        clnt->xa_init = ndr_xa_init;
 152      -        clnt->xa_exchange = ndr_xa_exchange;
 153      -        clnt->xa_read = ndr_xa_read;
 154      -        clnt->xa_preserve = ndr_xa_preserve;
 155      -        clnt->xa_destruct = ndr_xa_destruct;
 156      -        clnt->xa_release = ndr_xa_release;
 157      -        clnt->xa_private = ctx;
 158      -        clnt->xa_fd = fd;
 159      -
 160      -        ndr_svc_binding_pool_init(&clnt->binding_list,
 161      -            clnt->binding_pool, NDR_N_BINDING_POOL);
 162      -
 163      -        if ((clnt->heap = ndr_heap_create()) == NULL) {
 164      -                status = NT_STATUS_NO_MEMORY;
 165      -                goto errout;
 166      -        }
 167      -
 168  147          /*
 169      -         * Fill in the caller's handle.
      148 +         * This does the pipe open and OtW RPC bind.
      149 +         * Handles pipe open retries.
 170  150           */
 171      -        bzero(&handle->handle, sizeof (ndr_hdid_t));
 172      -        handle->clnt = clnt;
 173      -
 174      -        /*
 175      -         * Do the OtW RPC bind.
 176      -         */
 177      -        rc = ndr_clnt_bind(clnt, service, &clnt->binding);
 178      -        switch (rc) {
 179      -        case NDR_DRC_FAULT_OUT_OF_MEMORY:
 180      -                status = NT_STATUS_NO_MEMORY;
 181      -                break;
 182      -        case NDR_DRC_FAULT_API_SERVICE_INVALID: /* not registered */
 183      -                status = NT_STATUS_INTERNAL_ERROR;
 184      -                break;
 185      -        default:
 186      -                if (NDR_DRC_IS_FAULT(rc)) {
 187      -                        status = NT_STATUS_INVALID_PARAMETER;
      151 +        status = mlrpc_clh_bind(handle, svc);
      152 +        if (status != 0) {
      153 +                syslog(LOG_DEBUG, "ndr_rpc_bind: "
      154 +                    "mlrpc_clh_bind, %s (0x%x)",
      155 +                    xlate_nt_status(status), status);
      156 +                switch (status) {
      157 +                case RPC_NT_SERVER_TOO_BUSY:
      158 +                        /* Look for a new DC */
      159 +                        smb_ddiscover_bad_dc(server);
 188  160                          break;
      161 +                default:
      162 +                        break;
 189  163                  }
 190      -                /* FALLTHROUGH */
 191      -        case NDR_DRC_OK:
 192      -                return (NT_STATUS_SUCCESS);
      164 +                ctx = mlrpc_clh_free(handle);
      165 +                if (ctx != NULL) {
      166 +                        smbrdr_ctx_free(ctx);
      167 +                }
 193  168          }
 194  169  
 195      -        syslog(LOG_DEBUG, "ndr_rpc_bind: "
 196      -            "ndr_clnt_bind, %s (0x%x)",
 197      -            xlate_nt_status(status), status);
 198      -
 199      -errout:
 200      -        handle->clnt = NULL;
 201      -        if (clnt != NULL) {
 202      -                ndr_heap_destroy(clnt->heap);
 203      -                free(clnt);
 204      -        }
 205      -        if (ctx != NULL) {
 206      -                if (fd != -1)
 207      -                        (void) smb_fh_close(fd);
 208      -                smbrdr_ctx_free(ctx);
 209      -        }
 210      -
 211  170          return (status);
 212  171  }
 213  172  
 214  173  /*
 215      - * Unbind and close the pipe to an RPC service.
      174 + * Unbind and close the pipe to an RPC service
      175 + * and cleanup the smb_ctx.
 216  176   *
 217      - * If the heap has been preserved we need to go through an xa release.
 218      - * The heap is preserved during an RPC call because that's where data
 219      - * returned from the server is stored.
 220      - *
 221      - * Otherwise we destroy the heap directly.
      177 + * The heap may or may not be destroyed (see mlrpc_clh_free)
 222  178   */
 223  179  void
 224  180  ndr_rpc_unbind(mlsvc_handle_t *handle)
 225  181  {
 226      -        ndr_client_t *clnt = handle->clnt;
 227      -        struct smb_ctx *ctx = clnt->xa_private;
      182 +        struct smb_ctx *ctx;
 228  183  
 229      -        if (clnt->heap_preserved)
 230      -                ndr_clnt_free_heap(clnt);
 231      -        else
 232      -                ndr_heap_destroy(clnt->heap);
      184 +        ctx = mlrpc_clh_free(handle);
      185 +        if (ctx != NULL)
      186 +                smbrdr_ctx_free(ctx);
 233  187  
 234      -        (void) smb_fh_close(clnt->xa_fd);
 235      -        smbrdr_ctx_free(ctx);
 236      -        free(clnt);
 237  188          bzero(handle, sizeof (mlsvc_handle_t));
 238  189  }
 239  190  
 240  191  void
 241  192  ndr_rpc_status(mlsvc_handle_t *handle, int opnum, DWORD status)
 242  193  {
 243  194          ndr_service_t *svc;
 244  195          char *name = "NDR RPC";
 245  196          char *s = "unknown";
 246  197  
↓ open down ↓ 23 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX