winbindd: Fix indentation
[sfrench/samba-autobuild/.git] / source3 / winbindd / wb_dsgetdcname.c
index 207d1b61ea4c8ce525dfdc894383a9df35c13475..125e98ade74f34717fd84cd7695357d6a144a4a8 100644 (file)
@@ -19,7 +19,8 @@
 
 #include "includes.h"
 #include "winbindd.h"
-#include "librpc/gen_ndr/ndr_wbint_c.h"
+#include "librpc/gen_ndr/ndr_winbind_c.h"
+#include "librpc/gen_ndr/ndr_netlogon.h"
 
 struct wb_dsgetdcname_state {
        struct netr_DsRGetDCNameInfo *dcinfo;
@@ -45,18 +46,28 @@ struct tevent_req *wb_dsgetdcname_send(TALLOC_CTX *mem_ctx,
                return NULL;
        }
 
-       if (strequal(domain_name, "BUILTIN")
-           || strequal(domain_name, get_global_sam_name())) {
+       if (strequal(domain_name, "BUILTIN")) {
                /*
-                * Two options here: Give back our own address, or say there's
-                * nobody around. Right now opting for the latter, one measure
-                * to prevent the loopback connects. This might change if
-                * needed.
+                * This makes no sense
                 */
                tevent_req_nterror(req, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND);
                return tevent_req_post(req, ev);
        }
 
+       if (strequal(domain_name, get_global_sam_name())) {
+               int role = lp_server_role();
+               if ( role != ROLE_ACTIVE_DIRECTORY_DC ) {
+                       /*
+                        * Two options here: Give back our own address, or say there's
+                        * nobody around. Right now opting for the latter, one measure
+                        * to prevent the loopback connects. This might change if
+                        * needed.
+                        */
+                       tevent_req_nterror(req, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND);
+                       return tevent_req_post(req, ev);
+               }
+       }
+
        if (IS_DC) {
                /*
                 * We have to figure out the DC ourselves
@@ -113,3 +124,113 @@ NTSTATUS wb_dsgetdcname_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
        *pdcinfo = talloc_move(mem_ctx, &state->dcinfo);
        return NT_STATUS_OK;
 }
+
+NTSTATUS wb_dsgetdcname_gencache_set(const char *domname,
+                                    struct netr_DsRGetDCNameInfo *dcinfo)
+{
+       DATA_BLOB blob;
+       enum ndr_err_code ndr_err;
+       char *key;
+       bool ok;
+
+       key = talloc_asprintf_strupper_m(talloc_tos(), "DCINFO/%s", domname);
+       if (key == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       if (DEBUGLEVEL >= 10) {
+               NDR_PRINT_DEBUG(netr_DsRGetDCNameInfo, dcinfo);
+       }
+
+       ndr_err = ndr_push_struct_blob(
+               &blob, key, dcinfo,
+               (ndr_push_flags_fn_t)ndr_push_netr_DsRGetDCNameInfo);
+       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+               NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
+               DBG_WARNING("ndr_push_struct_blob failed: %s\n",
+                           ndr_errstr(ndr_err));
+               TALLOC_FREE(key);
+               return status;
+       }
+
+       ok = gencache_set_data_blob(key, &blob, time(NULL)+3600);
+
+       if (!ok) {
+               DBG_WARNING("gencache_set_data_blob for key %s failed\n", key);
+               TALLOC_FREE(key);
+               return NT_STATUS_UNSUCCESSFUL;
+       }
+
+       TALLOC_FREE(key);
+       return NT_STATUS_OK;
+}
+
+struct dcinfo_parser_state {
+       NTSTATUS status;
+       TALLOC_CTX *mem_ctx;
+       struct netr_DsRGetDCNameInfo *dcinfo;
+};
+
+static void dcinfo_parser(time_t timeout, DATA_BLOB blob, void *private_data)
+{
+       struct dcinfo_parser_state *state = private_data;
+       enum ndr_err_code ndr_err;
+
+       if (timeout <= time(NULL)) {
+               return;
+       }
+
+       state->dcinfo = talloc(state->mem_ctx, struct netr_DsRGetDCNameInfo);
+       if (state->dcinfo == NULL) {
+               state->status = NT_STATUS_NO_MEMORY;
+               return;
+       }
+
+       ndr_err = ndr_pull_struct_blob_all(
+               &blob, state->dcinfo, state->dcinfo,
+               (ndr_pull_flags_fn_t)ndr_pull_netr_DsRGetDCNameInfo);
+
+       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+               DBG_ERR("ndr_pull_struct_blob failed\n");
+               state->status = ndr_map_error2ntstatus(ndr_err);
+               return;
+       }
+
+       state->status = NT_STATUS_OK;
+}
+
+NTSTATUS wb_dsgetdcname_gencache_get(TALLOC_CTX *mem_ctx,
+                                    const char *domname,
+                                    struct netr_DsRGetDCNameInfo **dcinfo)
+{
+       struct dcinfo_parser_state state;
+       char *key;
+       bool ok;
+
+       key = talloc_asprintf_strupper_m(mem_ctx, "DCINFO/%s", domname);
+       if (key == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       state = (struct dcinfo_parser_state) {
+               .status = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND,
+               .mem_ctx = mem_ctx,
+       };
+
+       ok = gencache_parse(key, dcinfo_parser, &state);
+       TALLOC_FREE(key);
+       if (!ok) {
+               return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
+       }
+
+       if (!NT_STATUS_IS_OK(state.status)) {
+               return state.status;
+       }
+
+       if (DEBUGLEVEL >= 10) {
+               NDR_PRINT_DEBUG(netr_DsRGetDCNameInfo, state.dcinfo);
+       }
+
+       *dcinfo = state.dcinfo;
+       return NT_STATUS_OK;
+}