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

@@ -37,16 +37,15 @@
 #include <errno.h>
 #include <thread.h>
 #include <syslog.h>
 #include <synch.h>
 
+#include <libmlrpc/libmlrpc.h>
 #include <netsmb/smbfs_api.h>
+
 #include <smbsrv/libsmb.h>
-#include <smbsrv/libsmbns.h>
-#include <smbsrv/libmlrpc.h>
 #include <smbsrv/libmlsvc.h>
-#include <smbsrv/ndl/srvsvc.ndl>
 #include <libsmbrdr.h>
 #include <mlsvc.h>
 
 
 /*

@@ -60,29 +59,29 @@
  *
  * The client points to this top-level handle so that we know when to
  * unbind and teardown the connection.  As each handle is initialized it
  * will inherit a reference to the client context.
  *
- * Returns 0 or an NT_STATUS:
+ * Returns 0 or an NT_STATUS:           (failed in...)
+ *
  *      NT_STATUS_BAD_NETWORK_PATH      (get server addr)
  *      NT_STATUS_NETWORK_ACCESS_DENIED (connect, auth)
- *      NT_STATUS_BAD_NETWORK_NAME      (tcon, open)
+ *      NT_STATUS_BAD_NETWORK_NAME      (tcon)
+ *      RPC_NT_SERVER_TOO_BUSY          (open pipe)
+ *      RPC_NT_SERVER_UNAVAILABLE       (open pipe)
  *      NT_STATUS_ACCESS_DENIED         (open pipe)
  *      NT_STATUS_INVALID_PARAMETER     (rpc bind)
- *
  *      NT_STATUS_INTERNAL_ERROR        (bad args etc)
  *      NT_STATUS_NO_MEMORY
  */
 DWORD
 ndr_rpc_bind(mlsvc_handle_t *handle, char *server, char *domain,
     char *username, const char *service)
 {
         struct smb_ctx          *ctx = NULL;
-        ndr_client_t            *clnt = NULL;
         ndr_service_t           *svc;
         DWORD                   status;
-        int                     fd = -1;
         int                     rc;
 
         if (handle == NULL || server == NULL || server[0] == '\0' ||
             domain == NULL || username == NULL)
                 return (NT_STATUS_INTERNAL_ERROR);

@@ -111,131 +110,83 @@
         if (status != NT_STATUS_SUCCESS) {
                 syslog(LOG_ERR, "ndr_rpc_bind: smbrdr_ctx_new"
                     "(Srv=%s Dom=%s User=%s), %s (0x%x)",
                     server, domain, username,
                     xlate_nt_status(status), status);
-                /* Tell the DC Locator this DC failed. */
-                smb_ddiscover_bad_dc(server);
-                goto errout;
-        }
-
         /*
-         * Open the named pipe.
+                 * If the error is one where changing to a new DC
+                 * might help, try looking for a different DC.
          */
-        fd = smb_fh_open(ctx, svc->endpoint, O_RDWR);
-        if (fd < 0) {
-                rc = errno;
-                syslog(LOG_DEBUG, "ndr_rpc_bind: "
-                    "smb_fh_open (%s) err=%d",
-                    svc->endpoint, rc);
-                switch (rc) {
-                case EACCES:
-                        status = NT_STATUS_ACCESS_DENIED;
-                        break;
+                switch (status) {
+                case NT_STATUS_BAD_NETWORK_PATH:
+                case NT_STATUS_BAD_NETWORK_NAME:
+                        /* Look for a new DC */
+                        smb_ddiscover_bad_dc(server);
                 default:
-                        status = NT_STATUS_BAD_NETWORK_NAME;
                         break;
                 }
-                goto errout;
+                return (status);
         }
 
         /*
          * Setup the RPC client handle.
          */
-        if ((clnt = malloc(sizeof (ndr_client_t))) == NULL) {
-                status = NT_STATUS_NO_MEMORY;
-                goto errout;
+        rc = mlrpc_clh_create(handle, ctx);
+        if (rc != 0) {
+                syslog(LOG_ERR, "ndr_rpc_bind: mlrpc_clh_create: rc=%d", rc);
+                smbrdr_ctx_free(ctx);
+                switch (rc) {
+                case ENOMEM:
+                        return (NT_STATUS_NO_MEMORY);
+                case EINVAL:
+                        return (NT_STATUS_INVALID_PARAMETER);
+                default:
+                        return (NT_STATUS_INTERNAL_ERROR);
         }
-        bzero(clnt, sizeof (ndr_client_t));
-
-        clnt->handle = &handle->handle;
-        clnt->xa_init = ndr_xa_init;
-        clnt->xa_exchange = ndr_xa_exchange;
-        clnt->xa_read = ndr_xa_read;
-        clnt->xa_preserve = ndr_xa_preserve;
-        clnt->xa_destruct = ndr_xa_destruct;
-        clnt->xa_release = ndr_xa_release;
-        clnt->xa_private = ctx;
-        clnt->xa_fd = fd;
-
-        ndr_svc_binding_pool_init(&clnt->binding_list,
-            clnt->binding_pool, NDR_N_BINDING_POOL);
-
-        if ((clnt->heap = ndr_heap_create()) == NULL) {
-                status = NT_STATUS_NO_MEMORY;
-                goto errout;
         }
 
         /*
-         * Fill in the caller's handle.
+         * This does the pipe open and OtW RPC bind.
+         * Handles pipe open retries.
          */
-        bzero(&handle->handle, sizeof (ndr_hdid_t));
-        handle->clnt = clnt;
-
-        /*
-         * Do the OtW RPC bind.
-         */
-        rc = ndr_clnt_bind(clnt, service, &clnt->binding);
-        switch (rc) {
-        case NDR_DRC_FAULT_OUT_OF_MEMORY:
-                status = NT_STATUS_NO_MEMORY;
+        status = mlrpc_clh_bind(handle, svc);
+        if (status != 0) {
+                syslog(LOG_DEBUG, "ndr_rpc_bind: "
+                    "mlrpc_clh_bind, %s (0x%x)",
+                    xlate_nt_status(status), status);
+                switch (status) {
+                case RPC_NT_SERVER_TOO_BUSY:
+                        /* Look for a new DC */
+                        smb_ddiscover_bad_dc(server);
                 break;
-        case NDR_DRC_FAULT_API_SERVICE_INVALID: /* not registered */
-                status = NT_STATUS_INTERNAL_ERROR;
-                break;
         default:
-                if (NDR_DRC_IS_FAULT(rc)) {
-                        status = NT_STATUS_INVALID_PARAMETER;
                         break;
                 }
-                /* FALLTHROUGH */
-        case NDR_DRC_OK:
-                return (NT_STATUS_SUCCESS);
-        }
-
-        syslog(LOG_DEBUG, "ndr_rpc_bind: "
-            "ndr_clnt_bind, %s (0x%x)",
-            xlate_nt_status(status), status);
-
-errout:
-        handle->clnt = NULL;
-        if (clnt != NULL) {
-                ndr_heap_destroy(clnt->heap);
-                free(clnt);
-        }
+                ctx = mlrpc_clh_free(handle);
         if (ctx != NULL) {
-                if (fd != -1)
-                        (void) smb_fh_close(fd);
                 smbrdr_ctx_free(ctx);
         }
+        }
 
         return (status);
 }
 
 /*
- * Unbind and close the pipe to an RPC service.
+ * Unbind and close the pipe to an RPC service
+ * and cleanup the smb_ctx.
  *
- * If the heap has been preserved we need to go through an xa release.
- * The heap is preserved during an RPC call because that's where data
- * returned from the server is stored.
- *
- * Otherwise we destroy the heap directly.
+ * The heap may or may not be destroyed (see mlrpc_clh_free)
  */
 void
 ndr_rpc_unbind(mlsvc_handle_t *handle)
 {
-        ndr_client_t *clnt = handle->clnt;
-        struct smb_ctx *ctx = clnt->xa_private;
+        struct smb_ctx *ctx;
 
-        if (clnt->heap_preserved)
-                ndr_clnt_free_heap(clnt);
-        else
-                ndr_heap_destroy(clnt->heap);
-
-        (void) smb_fh_close(clnt->xa_fd);
+        ctx = mlrpc_clh_free(handle);
+        if (ctx != NULL)
         smbrdr_ctx_free(ctx);
-        free(clnt);
+
         bzero(handle, sizeof (mlsvc_handle_t));
 }
 
 void
 ndr_rpc_status(mlsvc_handle_t *handle, int opnum, DWORD status)