s3-librpc: Add dcerpc_binding_vector_replace_iface().
[mat/samba.git] / source3 / librpc / rpc / dcerpc_ep.c
index 76f7e91fb0518e9fb5083959a0e1c64a710e29e5..e734be3b2b700b6021a931f4e1fac8e4fc4cd235 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Endpoint Mapper Functions
  *  DCERPC local endpoint mapper client routines
- *  Copyright (c) 2010      Andreas Schneider.
+ *  Copyright (c) 2010-2011 Andreas Schneider.
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
 #include "../librpc/gen_ndr/ndr_epmapper_c.h"
 #include "rpc_client/cli_pipe.h"
 #include "auth.h"
+#include "rpc_server/rpc_ncacn_np.h"
+#include "../lib/tsocket/tsocket.h"
 
 #define EPM_MAX_ANNOTATION_SIZE 64
 
+static bool binding_vector_realloc(struct dcerpc_binding_vector *bvec)
+{
+       if (bvec->count >= bvec->allocated) {
+               struct dcerpc_binding *tmp;
+
+               tmp = talloc_realloc(bvec,
+                                    bvec->bindings,
+                                    struct dcerpc_binding,
+                                    bvec->allocated * 2);
+               if (tmp == NULL) {
+                       return false;
+               }
+               bvec->bindings = tmp;
+               bvec->allocated = bvec->allocated * 2;
+       }
+
+       return true;
+}
+
+NTSTATUS dcerpc_binding_vector_new(TALLOC_CTX *mem_ctx,
+                                  struct dcerpc_binding_vector **pbvec)
+{
+       struct dcerpc_binding_vector *bvec;
+       NTSTATUS status;
+       TALLOC_CTX *tmp_ctx;
+
+       tmp_ctx = talloc_stackframe();
+       if (tmp_ctx == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       bvec = talloc_zero(tmp_ctx, struct dcerpc_binding_vector);
+       if (bvec == NULL) {
+               status = NT_STATUS_NO_MEMORY;
+               goto done;
+       }
+
+       bvec->bindings = talloc_zero_array(bvec,
+                                          struct dcerpc_binding,
+                                          4);
+       if (bvec->bindings == NULL) {
+               status = NT_STATUS_NO_MEMORY;
+               goto done;
+       }
+
+       bvec->allocated = 4;
+       bvec->count = 0;
+
+       *pbvec = talloc_move(mem_ctx, &bvec);
+
+       status = NT_STATUS_OK;
+done:
+       talloc_free(tmp_ctx);
+
+       return status;
+}
+
+NTSTATUS dcerpc_binding_vector_add_np_default(const struct ndr_interface_table *iface,
+                                             struct dcerpc_binding_vector *bvec)
+{
+       uint32_t ep_count = iface->endpoints->count;
+       uint32_t i;
+       NTSTATUS status;
+       bool ok;
+
+       for (i = 0; i < ep_count; i++) {
+               struct dcerpc_binding *b;
+
+               b = talloc_zero(bvec->bindings, struct dcerpc_binding);
+               if (b == NULL) {
+                       return NT_STATUS_NO_MEMORY;
+               }
+
+               status = dcerpc_parse_binding(b, iface->endpoints->names[i], &b);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return NT_STATUS_UNSUCCESSFUL;
+               }
+
+               /* Only add the named pipes defined in the iface endpoints */
+               if (b->transport != NCACN_NP) {
+                       talloc_free(b);
+                       continue;
+               }
+
+               b->object = iface->syntax_id;
+
+               b->host = talloc_asprintf(b, "\\\\%s", lp_netbios_name());
+               if (b->host == NULL) {
+                       talloc_free(b);
+                       return NT_STATUS_NO_MEMORY;
+               }
+
+               ok = binding_vector_realloc(bvec);
+               if (!ok) {
+                       talloc_free(b);
+                       return NT_STATUS_NO_MEMORY;
+               }
+
+               bvec->bindings[bvec->count] = *b;
+               bvec->count++;
+       }
+
+       return NT_STATUS_OK;
+}
+
+NTSTATUS dcerpc_binding_vector_add_port(const struct ndr_interface_table *iface,
+                                       struct dcerpc_binding_vector *bvec,
+                                       const char *host,
+                                       uint16_t port)
+{
+       uint32_t ep_count = iface->endpoints->count;
+       uint32_t i;
+       NTSTATUS status;
+       bool ok;
+
+       for (i = 0; i < ep_count; i++) {
+               struct dcerpc_binding *b;
+
+               b = talloc_zero(bvec->bindings, struct dcerpc_binding);
+               if (b == NULL) {
+                       return NT_STATUS_NO_MEMORY;
+               }
+
+               status = dcerpc_parse_binding(b, iface->endpoints->names[i], &b);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return NT_STATUS_UNSUCCESSFUL;
+               }
+
+               if (b->transport != NCACN_IP_TCP) {
+                       talloc_free(b);
+                       continue;
+               }
+
+               b->object = iface->syntax_id;
+
+               b->host = talloc_strdup(b, host);
+               if (b->host == NULL) {
+                       talloc_free(b);
+                       return NT_STATUS_NO_MEMORY;
+               }
+
+               b->endpoint = talloc_asprintf(b, "%u", port);
+               if (b->endpoint == NULL) {
+                       talloc_free(b);
+                       return NT_STATUS_NO_MEMORY;
+               }
+
+               ok = binding_vector_realloc(bvec);
+               if (!ok) {
+                       talloc_free(b);
+                       return NT_STATUS_NO_MEMORY;
+               }
+
+               bvec->bindings[bvec->count] = *b;
+               bvec->count++;
+
+               break;
+       }
+
+       return NT_STATUS_OK;
+}
+
+NTSTATUS dcerpc_binding_vector_add_unix(const struct ndr_interface_table *iface,
+                                       struct dcerpc_binding_vector *bvec,
+                                       const char *name)
+{
+       uint32_t ep_count = iface->endpoints->count;
+       uint32_t i;
+       NTSTATUS status;
+       bool ok;
+
+       for (i = 0; i < ep_count; i++) {
+               struct dcerpc_binding *b;
+
+               b = talloc_zero(bvec->bindings, struct dcerpc_binding);
+               if (b == NULL) {
+                       return NT_STATUS_NO_MEMORY;
+               }
+
+               status = dcerpc_parse_binding(b, iface->endpoints->names[i], &b);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return NT_STATUS_UNSUCCESSFUL;
+               }
+
+               if (b->transport != NCALRPC) {
+                       talloc_free(b);
+                       continue;
+               }
+
+               b->object = iface->syntax_id;
+
+               b->endpoint = talloc_asprintf(b,
+                                             "%s/%s",
+                                             lp_ncalrpc_dir(),
+                                             name);
+               if (b->endpoint == NULL) {
+                       talloc_free(b);
+                       return NT_STATUS_NO_MEMORY;
+               }
+
+               ok = binding_vector_realloc(bvec);
+               if (!ok) {
+                       talloc_free(b);
+                       return NT_STATUS_NO_MEMORY;
+               }
+
+               bvec->bindings[bvec->count] = *b;
+               bvec->count++;
+
+               break;
+       }
+
+       return NT_STATUS_OK;
+}
+
+NTSTATUS dcerpc_binding_vector_replace_iface(const struct ndr_interface_table *iface,
+                                            struct dcerpc_binding_vector *v)
+{
+       uint32_t i;
+
+       for (i = 0; i < v->count; i++) {
+               struct dcerpc_binding *b;
+
+               b = &(v->bindings[i]);
+               b->object = iface->syntax_id;
+       }
+
+       return NT_STATUS_OK;
+}
+
+struct dcerpc_binding_vector *dcerpc_binding_vector_dup(TALLOC_CTX *mem_ctx,
+                                                       const struct dcerpc_binding_vector *bvec)
+{
+       struct dcerpc_binding_vector *v;
+       uint32_t i;
+
+       v = talloc(mem_ctx, struct dcerpc_binding_vector);
+       if (v == NULL) {
+               return NULL;
+       }
+
+       v->bindings = talloc_array(v, struct dcerpc_binding, bvec->allocated);
+       if (v->bindings == NULL) {
+               talloc_free(v);
+               return NULL;
+       }
+       v->allocated = bvec->allocated;
+
+       for (i = 0; i < bvec->count; i++) {
+               struct dcerpc_binding *b;
+
+               b = dcerpc_binding_dup(v->bindings, &bvec->bindings[i]);
+               if (b == NULL) {
+                       talloc_free(v);
+                       return NULL;
+               }
+               v->bindings[i] = *b;
+       }
+       v->count = bvec->count;
+
+       return v;
+}
+
 NTSTATUS dcerpc_binding_vector_create(TALLOC_CTX *mem_ctx,
                                      const struct ndr_interface_table *iface,
                                      uint16_t port,
@@ -77,7 +342,7 @@ NTSTATUS dcerpc_binding_vector_create(TALLOC_CTX *mem_ctx,
 
                switch (b->transport) {
                        case NCACN_NP:
-                               b->host = talloc_asprintf(b, "\\\\%s", global_myname());
+                               b->host = talloc_asprintf(b, "\\\\%s", lp_netbios_name());
                                if (b->host == NULL) {
                                        status = NT_STATUS_NO_MEMORY;
                                        goto done;
@@ -132,6 +397,7 @@ done:
 }
 
 static NTSTATUS ep_register(TALLOC_CTX *mem_ctx,
+                           struct messaging_context *msg_ctx,
                            const struct ndr_interface_table *iface,
                            const struct dcerpc_binding_vector *bind_vec,
                            const struct GUID *object_guid,
@@ -168,24 +434,31 @@ static NTSTATUS ep_register(TALLOC_CTX *mem_ctx,
                                           "rpc_server", "epmapper",
                                           "none");
 
-       if (StrCaseCmp(rpcsrv_type, "embedded") == 0) {
-               static struct client_address client_id;
-
-               strlcpy(client_id.addr, "localhost", sizeof(client_id.addr));
-               client_id.name = "localhost";
+       if (strcasecmp_m(rpcsrv_type, "embedded") == 0) {
+               struct tsocket_address *local;
+               int rc;
+
+               rc = tsocket_address_inet_from_strings(tmp_ctx,
+                                                      "ip",
+                                                      "127.0.0.1",
+                                                      0,
+                                                      &local);
+               if (rc < 0) {
+                       return NT_STATUS_NO_MEMORY;
+               }
 
                status = rpcint_binding_handle(tmp_ctx,
                                               &ndr_table_epmapper,
-                                              &client_id,
+                                              local,
                                               get_session_info_system(),
-                                              server_messaging_context(),
+                                              msg_ctx,
                                               &h);
                if (!NT_STATUS_IS_OK(status)) {
                        DEBUG(1, ("dcerpc_ep_register: Could not connect to "
                                  "epmapper (%s)", nt_errstr(status)));
                        goto done;
                }
-       } else if (StrCaseCmp(rpcsrv_type, "daemon") == 0) {
+       } else if (strcasecmp_m(rpcsrv_type, "daemon") == 0) {
                /* Connect to the endpoint mapper locally */
                ncalrpc_sock = talloc_asprintf(tmp_ctx,
                                              "%s/%s",
@@ -300,6 +573,7 @@ done:
 }
 
 NTSTATUS dcerpc_ep_register(TALLOC_CTX *mem_ctx,
+                           struct messaging_context *msg_ctx,
                            const struct ndr_interface_table *iface,
                            const struct dcerpc_binding_vector *bind_vec,
                            const struct GUID *object_guid,
@@ -307,6 +581,7 @@ NTSTATUS dcerpc_ep_register(TALLOC_CTX *mem_ctx,
                            struct dcerpc_binding_handle **ph)
 {
        return ep_register(mem_ctx,
+                          msg_ctx,
                           iface,
                           bind_vec,
                           object_guid,
@@ -317,6 +592,7 @@ NTSTATUS dcerpc_ep_register(TALLOC_CTX *mem_ctx,
 }
 
 NTSTATUS dcerpc_ep_register_noreplace(TALLOC_CTX *mem_ctx,
+                                     struct messaging_context *msg_ctx,
                                      const struct ndr_interface_table *iface,
                                      const struct dcerpc_binding_vector *bind_vec,
                                      const struct GUID *object_guid,
@@ -324,6 +600,7 @@ NTSTATUS dcerpc_ep_register_noreplace(TALLOC_CTX *mem_ctx,
                                      struct dcerpc_binding_handle **ph)
 {
        return ep_register(mem_ctx,
+                          msg_ctx,
                           iface,
                           bind_vec,
                           object_guid,
@@ -333,11 +610,13 @@ NTSTATUS dcerpc_ep_register_noreplace(TALLOC_CTX *mem_ctx,
                           ph);
 }
 
-NTSTATUS dcerpc_ep_unregister(const struct ndr_interface_table *iface,
+NTSTATUS dcerpc_ep_unregister(struct messaging_context *msg_ctx,
+                             const struct ndr_interface_table *iface,
                              const struct dcerpc_binding_vector *bind_vec,
                              const struct GUID *object_guid)
 {
        return ep_register(NULL,
+                          msg_ctx,
                           iface,
                           bind_vec,
                           object_guid,