From 7f4199c2d4dc9147be436005d75e03fc468f5349 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20B=C5=99ezina?= Date: Mon, 27 Jun 2016 13:56:13 +0200 Subject: [PATCH 096/102] sssctl: print active server and server list MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Resolves: https://fedorahosted.org/sssd/ticket/3069 Reviewed-by: Lukáš Slebodník Reviewed-by: Jakub Hrozek (cherry picked from commit bd4c2ed5aec7f57ea04500f0e43f151eedfdde45) --- src/providers/data_provider/dp_iface.c | 6 +- src/providers/data_provider/dp_iface.h | 8 + src/providers/data_provider/dp_iface.xml | 8 + src/providers/data_provider/dp_iface_failover.c | 297 ++++++++++++++++++++++- src/providers/data_provider/dp_iface_generated.c | 52 ++++ src/providers/data_provider/dp_iface_generated.h | 10 + src/providers/fail_over.c | 42 ++++ src/providers/fail_over.h | 4 + src/responder/ifp/ifp_domains.c | 48 ++++ src/responder/ifp/ifp_domains.h | 8 + src/responder/ifp/ifp_iface.c | 4 +- src/responder/ifp/ifp_iface.xml | 10 + src/responder/ifp/ifp_iface_generated.c | 52 ++++ src/responder/ifp/ifp_iface_generated.h | 10 + src/tools/sssctl/sssctl_domains.c | 182 +++++++++++++- 15 files changed, 722 insertions(+), 19 deletions(-) diff --git a/src/providers/data_provider/dp_iface.c b/src/providers/data_provider/dp_iface.c index 8ed7274f0dd7b59598e2cf21e0dd59d16666df0b..4b2b0ddca68be8899f7285b4d881a91444b99362 100644 --- a/src/providers/data_provider/dp_iface.c +++ b/src/providers/data_provider/dp_iface.c @@ -42,8 +42,10 @@ struct iface_dp_backend iface_dp_backend = { }; struct iface_dp_failover iface_dp_failover = { - {&iface_dp_failover_meta, 0}, - .ListServices = dp_failover_list_services + { &iface_dp_failover_meta, 0 }, + .ListServices = dp_failover_list_services, + .ActiveServer = dp_failover_active_server, + .ListServers = dp_failover_list_servers }; static struct sbus_iface_map dp_map[] = { diff --git a/src/providers/data_provider/dp_iface.h b/src/providers/data_provider/dp_iface.h index 76e623d21c413fd68f8f3c9a91ea32fd707dc54d..5c6f0eb2f5dd68b63bda389e6fdd2446ca9efb21 100644 --- a/src/providers/data_provider/dp_iface.h +++ b/src/providers/data_provider/dp_iface.h @@ -69,4 +69,12 @@ errno_t dp_failover_list_services(struct sbus_request *sbus_req, void *dp_cli, const char *domname); +errno_t dp_failover_active_server(struct sbus_request *sbus_req, + void *dp_cli, + const char *service_name); + +errno_t dp_failover_list_servers(struct sbus_request *sbus_req, + void *dp_cli, + const char *service_name); + #endif /* DP_IFACE_H_ */ diff --git a/src/providers/data_provider/dp_iface.xml b/src/providers/data_provider/dp_iface.xml index eab7fc0f1500bf8890030352421da62c134115b9..992848a048ef9fe813d6ae05bbcabd0913ecb277 100644 --- a/src/providers/data_provider/dp_iface.xml +++ b/src/providers/data_provider/dp_iface.xml @@ -22,6 +22,14 @@ + + + + + + + + diff --git a/src/providers/data_provider/dp_iface_failover.c b/src/providers/data_provider/dp_iface_failover.c index 038791088eeab7e9c5923996db77d2a107ff067d..7d95ffdd627604eb8c7e1b2882bf1665f792b660 100644 --- a/src/providers/data_provider/dp_iface_failover.c +++ b/src/providers/data_provider/dp_iface_failover.c @@ -28,20 +28,208 @@ #include "providers/backend.h" #include "util/util.h" +static errno_t +dp_failover_list_services_ldap(struct be_ctx *be_ctx, + const char **services, + int *_count) +{ + struct be_svc_data *svc; + int count; + + count = 0; + DLIST_FOR_EACH(svc, be_ctx->be_fo->svcs) { + services[count] = talloc_strdup(services, svc->name); + if (services[count] == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "talloc_strdup() failed\n"); + return ENOMEM; + } + count++; + } + + *_count = count; + + return EOK; +} + +static errno_t +dp_failover_list_services_ad(struct be_ctx *be_ctx, + struct sss_domain_info *domain, + const char **services, + int *_count) +{ + char *fo_svc_name = NULL; + struct be_svc_data *svc; + errno_t ret; + int count; + + fo_svc_name = talloc_asprintf(services, "sd_%s", domain->name); + if (fo_svc_name == NULL) { + ret = ENOMEM; + goto done; + } + + count = 0; + DLIST_FOR_EACH(svc, be_ctx->be_fo->svcs) { + /* Drop each sd_gc_* since this service is not used with AD at all, + * we only connect to AD_GC for global catalog. */ + if (strncasecmp(svc->name, "sd_gc_", strlen("sd_gc_")) == 0) { + continue; + } + + /* Drop all subdomain services for different domain. */ + if (strncasecmp(svc->name, "sd_", strlen("sd_")) == 0) { + if (!IS_SUBDOMAIN(domain)) { + continue; + } + + if (strcasecmp(svc->name, fo_svc_name) != 0) { + continue; + } + } + + if (IS_SUBDOMAIN(domain)) { + /* Drop AD since we connect to subdomain.com for LDAP. */ + if (strcasecmp(svc->name, "AD") == 0) { + continue; + } + } + + services[count] = talloc_strdup(services, svc->name); + if (services[count] == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "talloc_strdup() failed\n"); + ret = ENOMEM; + goto done; + } + count++; + } + + *_count = count; + + ret = EOK; + +done: + talloc_free(fo_svc_name); + return ret; +} + +static errno_t +dp_failover_list_services_ipa(struct be_ctx *be_ctx, + struct sss_domain_info *domain, + const char **services, + int *_count) +{ + struct be_svc_data *svc; + char *fo_svc_name = NULL; + char *fo_gc_name = NULL; + errno_t ret; + int count; + + fo_svc_name = talloc_asprintf(services, "sd_%s", domain->name); + if (fo_svc_name == NULL) { + ret = ENOMEM; + goto done; + } + + fo_gc_name = talloc_asprintf(services, "sd_gc_%s", domain->name); + if (fo_gc_name == NULL) { + ret = ENOMEM; + goto done; + } + + count = 0; + DLIST_FOR_EACH(svc, be_ctx->be_fo->svcs) { + /* Drop all subdomain services for different domain. */ + if (strncasecmp(svc->name, "sd_", strlen("sd_")) == 0) { + if (!IS_SUBDOMAIN(domain)) { + continue; + } + + if (strcasecmp(svc->name, fo_svc_name) != 0 + && strcasecmp(svc->name, fo_gc_name) != 0) { + continue; + } + } + + services[count] = talloc_strdup(services, svc->name); + if (services[count] == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "talloc_strdup() failed\n"); + return ENOMEM; + } + count++; + } + + *_count = count; + + ret = EOK; + +done: + talloc_free(fo_svc_name); + talloc_free(fo_gc_name); + + return ret; +} + +enum dp_fo_svc_type { + DP_FO_SVC_LDAP = 0, + DP_FO_SVC_AD = 1, + DP_FO_SVC_IPA = 1 << 1, + DP_FO_SVC_MIXED = DP_FO_SVC_AD | DP_FO_SVC_IPA +}; + errno_t dp_failover_list_services(struct sbus_request *sbus_req, void *dp_cli, const char *domname) { + enum dp_fo_svc_type svc_type = DP_FO_SVC_LDAP; + struct sss_domain_info *domain; struct be_ctx *be_ctx; struct be_svc_data *svc; const char **services; int num_services; + errno_t ret; be_ctx = dp_client_be(dp_cli); + if (SBUS_IS_STRING_EMPTY(domname)) { + domain = be_ctx->domain; + } else { + domain = find_domain_by_name(be_ctx->domain, domname, false); + if (domain == NULL) { + sbus_request_reply_error(sbus_req, SBUS_ERROR_UNKNOWN_DOMAIN, + "Unknown domain %s", domname); + return EOK; + } + } + + /** + * Returning list of failover services is currently rather difficult + * since there is only one failover context for the whole backend. + * + * The list of services for the given domain depends on whether it is + * a master domain or a subdomain and whether we are using IPA, AD or + * LDAP backend. + * + * For LDAP we just return everything we have. + * For AD master domain we return AD, AD_GC. + * For AD subdomain we return subdomain.com, AD_GC. + * For IPA in client mode we return IPA. + * For IPA in server mode we return IPA for master domain and + * subdomain.com, gc_subdomain.com for subdomain. + * + * We also return everything else for all cases if any other service + * such as kerberos is configured separately. + */ + + /* Allocate enough space. */ num_services = 0; DLIST_FOR_EACH(svc, be_ctx->be_fo->svcs) { num_services++; + + if (strcasecmp(svc->name, "AD") == 0) { + svc_type |= DP_FO_SVC_AD; + } else if (strcasecmp(svc->name, "IPA") == 0) { + svc_type |= DP_FO_SVC_IPA; + } } services = talloc_zero_array(sbus_req, const char *, num_services); @@ -50,17 +238,108 @@ errno_t dp_failover_list_services(struct sbus_request *sbus_req, return ENOMEM; } - num_services = 0; - DLIST_FOR_EACH(svc, be_ctx->be_fo->svcs) { - services[num_services] = talloc_strdup(services, svc->name); - if (services[num_services] == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, "talloc_strdup() failed\n"); - talloc_free(services); - return ENOMEM; - } - num_services++; + /* Fill the list. */ + switch (svc_type) { + case DP_FO_SVC_LDAP: + case DP_FO_SVC_MIXED: + ret = dp_failover_list_services_ldap(be_ctx, services, &num_services); + break; + case DP_FO_SVC_AD: + ret = dp_failover_list_services_ad(be_ctx, domain, + services, &num_services); + break; + case DP_FO_SVC_IPA: + ret = dp_failover_list_services_ipa(be_ctx, domain, + services, &num_services); + break; + default: + ret = ERR_INTERNAL; + break; + } + + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create service list [%d]: %s\n", + ret, sss_strerror(ret)); + talloc_free(services); + return ret; } iface_dp_failover_ListServices_finish(sbus_req, services, num_services); return EOK; } + +errno_t dp_failover_active_server(struct sbus_request *sbus_req, + void *dp_cli, + const char *service_name) +{ + struct be_ctx *be_ctx; + struct be_svc_data *svc; + const char *server; + bool found = false; + + be_ctx = dp_client_be(dp_cli); + + DLIST_FOR_EACH(svc, be_ctx->be_fo->svcs) { + if (strcmp(svc->name, service_name) == 0) { + found = true; + break; + } + } + + if (!found) { + DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get server name\n"); + sbus_request_reply_error(sbus_req, SBUS_ERROR_NOT_FOUND, + "Unknown service name"); + return EOK; + } + + if (svc->last_good_srv == NULL) { + server = ""; + } else { + server = fo_get_server_name(svc->last_good_srv); + if (server == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get server name\n"); + sbus_request_reply_error(sbus_req, SBUS_ERROR_INTERNAL, + "Unable to get server name"); + return EOK; + } + } + + iface_dp_failover_ActiveServer_finish(sbus_req, server); + return EOK; +} + +errno_t dp_failover_list_servers(struct sbus_request *sbus_req, + void *dp_cli, + const char *service_name) +{ + struct be_ctx *be_ctx; + struct be_svc_data *svc; + const char **servers; + bool found = false; + size_t count; + + be_ctx = dp_client_be(dp_cli); + + DLIST_FOR_EACH(svc, be_ctx->be_fo->svcs) { + if (strcmp(svc->name, service_name) == 0) { + found = true; + break; + } + } + + if (!found) { + DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get server list\n"); + sbus_request_reply_error(sbus_req, SBUS_ERROR_NOT_FOUND, + "Unknown service name"); + return EOK; + } + + servers = fo_svc_server_list(sbus_req, svc->fo_service, &count); + if (servers == NULL) { + return ENOMEM; + } + + iface_dp_failover_ListServers_finish(sbus_req, servers, (int)count); + return EOK; +} diff --git a/src/providers/data_provider/dp_iface_generated.c b/src/providers/data_provider/dp_iface_generated.c index 7b36fd8aaeebb976a511c5592b1dd0ae28e9bb8a..fd2acb4f4bd8cf1dcbe8842cccc6dc2077fc83a2 100644 --- a/src/providers/data_provider/dp_iface_generated.c +++ b/src/providers/data_provider/dp_iface_generated.c @@ -111,6 +111,44 @@ int iface_dp_failover_ListServices_finish(struct sbus_request *req, const char * DBUS_TYPE_INVALID); } +/* arguments for org.freedesktop.sssd.DataProvider.Failover.ActiveServer */ +const struct sbus_arg_meta iface_dp_failover_ActiveServer__in[] = { + { "service_name", "s" }, + { NULL, } +}; + +/* arguments for org.freedesktop.sssd.DataProvider.Failover.ActiveServer */ +const struct sbus_arg_meta iface_dp_failover_ActiveServer__out[] = { + { "server", "s" }, + { NULL, } +}; + +int iface_dp_failover_ActiveServer_finish(struct sbus_request *req, const char *arg_server) +{ + return sbus_request_return_and_finish(req, + DBUS_TYPE_STRING, &arg_server, + DBUS_TYPE_INVALID); +} + +/* arguments for org.freedesktop.sssd.DataProvider.Failover.ListServers */ +const struct sbus_arg_meta iface_dp_failover_ListServers__in[] = { + { "service_name", "s" }, + { NULL, } +}; + +/* arguments for org.freedesktop.sssd.DataProvider.Failover.ListServers */ +const struct sbus_arg_meta iface_dp_failover_ListServers__out[] = { + { "servers", "as" }, + { NULL, } +}; + +int iface_dp_failover_ListServers_finish(struct sbus_request *req, const char *arg_servers[], int len_servers) +{ + return sbus_request_return_and_finish(req, + DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &arg_servers, len_servers, + DBUS_TYPE_INVALID); +} + /* methods for org.freedesktop.sssd.DataProvider.Failover */ const struct sbus_method_meta iface_dp_failover__methods[] = { { @@ -120,6 +158,20 @@ const struct sbus_method_meta iface_dp_failover__methods[] = { offsetof(struct iface_dp_failover, ListServices), invoke_s_method, }, + { + "ActiveServer", /* name */ + iface_dp_failover_ActiveServer__in, + iface_dp_failover_ActiveServer__out, + offsetof(struct iface_dp_failover, ActiveServer), + invoke_s_method, + }, + { + "ListServers", /* name */ + iface_dp_failover_ListServers__in, + iface_dp_failover_ListServers__out, + offsetof(struct iface_dp_failover, ListServers), + invoke_s_method, + }, { NULL, } }; diff --git a/src/providers/data_provider/dp_iface_generated.h b/src/providers/data_provider/dp_iface_generated.h index 977ab3bae803ca002162b02d0c3d9677779983f4..7c2216aa27022769c707d80b59e9b436e72d1739 100644 --- a/src/providers/data_provider/dp_iface_generated.h +++ b/src/providers/data_provider/dp_iface_generated.h @@ -22,6 +22,8 @@ /* constants for org.freedesktop.sssd.DataProvider.Failover */ #define IFACE_DP_FAILOVER "org.freedesktop.sssd.DataProvider.Failover" #define IFACE_DP_FAILOVER_LISTSERVICES "ListServices" +#define IFACE_DP_FAILOVER_ACTIVESERVER "ActiveServer" +#define IFACE_DP_FAILOVER_LISTSERVERS "ListServers" /* constants for org.freedesktop.sssd.dataprovider */ #define IFACE_DP "org.freedesktop.sssd.dataprovider" @@ -72,11 +74,19 @@ int iface_dp_backend_IsOnline_finish(struct sbus_request *req, bool arg_status); struct iface_dp_failover { struct sbus_vtable vtable; /* derive from sbus_vtable */ int (*ListServices)(struct sbus_request *req, void *data, const char *arg_domain_name); + int (*ActiveServer)(struct sbus_request *req, void *data, const char *arg_service_name); + int (*ListServers)(struct sbus_request *req, void *data, const char *arg_service_name); }; /* finish function for ListServices */ int iface_dp_failover_ListServices_finish(struct sbus_request *req, const char *arg_services[], int len_services); +/* finish function for ActiveServer */ +int iface_dp_failover_ActiveServer_finish(struct sbus_request *req, const char *arg_server); + +/* finish function for ListServers */ +int iface_dp_failover_ListServers_finish(struct sbus_request *req, const char *arg_servers[], int len_servers); + /* vtable for org.freedesktop.sssd.dataprovider */ struct iface_dp { struct sbus_vtable vtable; /* derive from sbus_vtable */ diff --git a/src/providers/fail_over.c b/src/providers/fail_over.c index 1d88d2aa54bfdebd4b648e2b13fa8d03e2be3973..8ab39f27f77e19e601855632196006a8dbbdf136 100644 --- a/src/providers/fail_over.c +++ b/src/providers/fail_over.c @@ -1660,6 +1660,48 @@ bool fo_svc_has_server(struct fo_service *service, struct fo_server *server) return false; } +const char **fo_svc_server_list(TALLOC_CTX *mem_ctx, + struct fo_service *service, + size_t *_count) +{ + const char **list; + const char *server; + struct fo_server *srv; + size_t count; + + count = 0; + DLIST_FOR_EACH(srv, service->server_list) { + count++; + } + + list = talloc_zero_array(mem_ctx, const char *, count + 1); + if (list == NULL) { + return NULL; + } + + count = 0; + DLIST_FOR_EACH(srv, service->server_list) { + server = fo_get_server_name(srv); + if (server == NULL) { + /* _srv_ */ + continue; + } + + list[count] = talloc_strdup(list, server); + if (list[count] == NULL) { + talloc_free(list); + return NULL; + } + count++; + } + + if (_count != NULL) { + *_count = count; + } + + return list; +} + bool fo_set_srv_lookup_plugin(struct fo_ctx *ctx, fo_srv_lookup_plugin_send_t send_fn, fo_srv_lookup_plugin_recv_t recv_fn, diff --git a/src/providers/fail_over.h b/src/providers/fail_over.h index f24b5715f13931965400c20562a1578aaf756908..d70212fb7ea569b9c47bba36704aa8ae18754cbb 100644 --- a/src/providers/fail_over.h +++ b/src/providers/fail_over.h @@ -212,6 +212,10 @@ struct fo_server *fo_get_active_server(struct fo_service *service); bool fo_svc_has_server(struct fo_service *service, struct fo_server *server); +const char **fo_svc_server_list(TALLOC_CTX *mem_ctx, + struct fo_service *service, + size_t *_count); + /* * pvt will be talloc_stealed to ctx */ diff --git a/src/responder/ifp/ifp_domains.c b/src/responder/ifp/ifp_domains.c index ff690ed6a7d5519979d242a4d5dadd08aff50347..977bbfcbe818f08873ce072d34fdcf900cabf52f 100644 --- a/src/responder/ifp/ifp_domains.c +++ b/src/responder/ifp/ifp_domains.c @@ -582,3 +582,51 @@ int ifp_domains_domain_list_services(struct sbus_request *sbus_req, return EOK; } + +int ifp_domains_domain_active_server(struct sbus_request *sbus_req, + void *data, + const char *service) +{ + struct ifp_ctx *ifp_ctx; + struct sss_domain_info *dom; + + ifp_ctx = talloc_get_type(data, struct ifp_ctx); + + dom = get_domain_info_from_req(sbus_req, data); + if (dom == NULL) { + sbus_request_reply_error(sbus_req, SBUS_ERROR_UNKNOWN_DOMAIN, + "Unknown domain"); + return EOK; + } + + rdp_message_send_and_reply(sbus_req, ifp_ctx->rctx, dom, DP_PATH, + IFACE_DP_FAILOVER, + IFACE_DP_FAILOVER_ACTIVESERVER, + DBUS_TYPE_STRING, &service); + + return EOK; +} + +int ifp_domains_domain_list_servers(struct sbus_request *sbus_req, + void *data, + const char *service) +{ + struct ifp_ctx *ifp_ctx; + struct sss_domain_info *dom; + + ifp_ctx = talloc_get_type(data, struct ifp_ctx); + + dom = get_domain_info_from_req(sbus_req, data); + if (dom == NULL) { + sbus_request_reply_error(sbus_req, SBUS_ERROR_UNKNOWN_DOMAIN, + "Unknown domain"); + return EOK; + } + + rdp_message_send_and_reply(sbus_req, ifp_ctx->rctx, dom, DP_PATH, + IFACE_DP_FAILOVER, + IFACE_DP_FAILOVER_LISTSERVERS, + DBUS_TYPE_STRING, &service); + + return EOK; +} diff --git a/src/responder/ifp/ifp_domains.h b/src/responder/ifp/ifp_domains.h index 91645e60701f8f75e89a42e93e2c066def67b018..621ba6158e285911cb8298cef212219dfd3afec8 100644 --- a/src/responder/ifp/ifp_domains.h +++ b/src/responder/ifp/ifp_domains.h @@ -100,4 +100,12 @@ int ifp_domains_domain_is_online(struct sbus_request *sbus_req, int ifp_domains_domain_list_services(struct sbus_request *sbus_req, void *data); +int ifp_domains_domain_active_server(struct sbus_request *sbus_req, + void *data, + const char *service); + +int ifp_domains_domain_list_servers(struct sbus_request *sbus_req, + void *data, + const char *service); + #endif /* IFP_DOMAINS_H_ */ diff --git a/src/responder/ifp/ifp_iface.c b/src/responder/ifp/ifp_iface.c index 90bb52b2ccf5207034abbe12bddbfa1eeaf875f7..e6ddc687ba9db878ee39fee5868d1f924d58482d 100644 --- a/src/responder/ifp/ifp_iface.c +++ b/src/responder/ifp/ifp_iface.c @@ -81,7 +81,9 @@ struct iface_ifp_domains iface_ifp_domains = { struct iface_ifp_domains_domain iface_ifp_domains_domain = { { &iface_ifp_domains_domain_meta, 0 }, .IsOnline = ifp_domains_domain_is_online, - .ListServices = ifp_domains_domain_list_services + .ListServices = ifp_domains_domain_list_services, + .ActiveServer = ifp_domains_domain_active_server, + .ListServers = ifp_domains_domain_list_servers }; struct iface_ifp_users iface_ifp_users = { diff --git a/src/responder/ifp/ifp_iface.xml b/src/responder/ifp/ifp_iface.xml index 7f6f47299deeba4b1baa23d1e63ee7bb17304a59..25b104ad70c0fd84b6c0fe9dbb0dc6e6439c1376 100644 --- a/src/responder/ifp/ifp_iface.xml +++ b/src/responder/ifp/ifp_iface.xml @@ -112,6 +112,16 @@ + + + + + + + + + + diff --git a/src/responder/ifp/ifp_iface_generated.c b/src/responder/ifp/ifp_iface_generated.c index 4d3bb5727b03ae64adad14fcdbb3eb5366edb406..6156ca2947434f301d206232f83cfc0647007707 100644 --- a/src/responder/ifp/ifp_iface_generated.c +++ b/src/responder/ifp/ifp_iface_generated.c @@ -558,6 +558,44 @@ int iface_ifp_domains_domain_ListServices_finish(struct sbus_request *req, const DBUS_TYPE_INVALID); } +/* arguments for org.freedesktop.sssd.infopipe.Domains.Domain.ActiveServer */ +const struct sbus_arg_meta iface_ifp_domains_domain_ActiveServer__in[] = { + { "service", "s" }, + { NULL, } +}; + +/* arguments for org.freedesktop.sssd.infopipe.Domains.Domain.ActiveServer */ +const struct sbus_arg_meta iface_ifp_domains_domain_ActiveServer__out[] = { + { "server", "s" }, + { NULL, } +}; + +int iface_ifp_domains_domain_ActiveServer_finish(struct sbus_request *req, const char *arg_server) +{ + return sbus_request_return_and_finish(req, + DBUS_TYPE_STRING, &arg_server, + DBUS_TYPE_INVALID); +} + +/* arguments for org.freedesktop.sssd.infopipe.Domains.Domain.ListServers */ +const struct sbus_arg_meta iface_ifp_domains_domain_ListServers__in[] = { + { "service_name", "s" }, + { NULL, } +}; + +/* arguments for org.freedesktop.sssd.infopipe.Domains.Domain.ListServers */ +const struct sbus_arg_meta iface_ifp_domains_domain_ListServers__out[] = { + { "servers", "as" }, + { NULL, } +}; + +int iface_ifp_domains_domain_ListServers_finish(struct sbus_request *req, const char *arg_servers[], int len_servers) +{ + return sbus_request_return_and_finish(req, + DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &arg_servers, len_servers, + DBUS_TYPE_INVALID); +} + /* methods for org.freedesktop.sssd.infopipe.Domains.Domain */ const struct sbus_method_meta iface_ifp_domains_domain__methods[] = { { @@ -574,6 +612,20 @@ const struct sbus_method_meta iface_ifp_domains_domain__methods[] = { offsetof(struct iface_ifp_domains_domain, ListServices), NULL, /* no invoker */ }, + { + "ActiveServer", /* name */ + iface_ifp_domains_domain_ActiveServer__in, + iface_ifp_domains_domain_ActiveServer__out, + offsetof(struct iface_ifp_domains_domain, ActiveServer), + invoke_s_method, + }, + { + "ListServers", /* name */ + iface_ifp_domains_domain_ListServers__in, + iface_ifp_domains_domain_ListServers__out, + offsetof(struct iface_ifp_domains_domain, ListServers), + invoke_s_method, + }, { NULL, } }; diff --git a/src/responder/ifp/ifp_iface_generated.h b/src/responder/ifp/ifp_iface_generated.h index 2eff57410e5292a05818050b96eb85aa3a4f2e16..141348249d2da5447fa04495564a8c6a55d67a1b 100644 --- a/src/responder/ifp/ifp_iface_generated.h +++ b/src/responder/ifp/ifp_iface_generated.h @@ -58,6 +58,8 @@ #define IFACE_IFP_DOMAINS_DOMAIN "org.freedesktop.sssd.infopipe.Domains.Domain" #define IFACE_IFP_DOMAINS_DOMAIN_ISONLINE "IsOnline" #define IFACE_IFP_DOMAINS_DOMAIN_LISTSERVICES "ListServices" +#define IFACE_IFP_DOMAINS_DOMAIN_ACTIVESERVER "ActiveServer" +#define IFACE_IFP_DOMAINS_DOMAIN_LISTSERVERS "ListServers" /* constants for org.freedesktop.sssd.infopipe.Cache */ #define IFACE_IFP_CACHE "org.freedesktop.sssd.infopipe.Cache" @@ -215,6 +217,8 @@ struct iface_ifp_domains_domain { struct sbus_vtable vtable; /* derive from sbus_vtable */ int (*IsOnline)(struct sbus_request *req, void *data); int (*ListServices)(struct sbus_request *req, void *data); + int (*ActiveServer)(struct sbus_request *req, void *data, const char *arg_service); + int (*ListServers)(struct sbus_request *req, void *data, const char *arg_service_name); }; /* finish function for IsOnline */ @@ -223,6 +227,12 @@ int iface_ifp_domains_domain_IsOnline_finish(struct sbus_request *req, bool arg_ /* finish function for ListServices */ int iface_ifp_domains_domain_ListServices_finish(struct sbus_request *req, const char *arg_services[], int len_services); +/* finish function for ActiveServer */ +int iface_ifp_domains_domain_ActiveServer_finish(struct sbus_request *req, const char *arg_server); + +/* finish function for ListServers */ +int iface_ifp_domains_domain_ListServers_finish(struct sbus_request *req, const char *arg_servers[], int len_servers); + /* vtable for org.freedesktop.sssd.infopipe.Cache */ struct iface_ifp_cache { struct sbus_vtable vtable; /* derive from sbus_vtable */ diff --git a/src/tools/sssctl/sssctl_domains.c b/src/tools/sssctl/sssctl_domains.c index 40962792b84eabeb2c142f158184b17180a01669..545ed95f4415da597b191146409ea6ba028f36f8 100644 --- a/src/tools/sssctl/sssctl_domains.c +++ b/src/tools/sssctl/sssctl_domains.c @@ -112,6 +112,155 @@ done: return ret; } +static const char *proper_service_name(const char *service) +{ + if (strcasecmp(service, "AD_GC") == 0) { + return "AD Global Catalog"; + } else if (strcasecmp(service, "AD") == 0) { + return "AD Domain Controller"; + } else if (strncasecmp(service, "sd_gc_", strlen("sd_gc_")) == 0) { + return "AD Global Catalog"; + } else if (strncasecmp(service, "sd_", strlen("sd_")) == 0) { + return "AD Domain Controller"; + } + + return service; +} + +static errno_t sssctl_domain_status_active_server(struct sss_tool_ctx *tool_ctx, + sss_sifp_ctx *sifp, + const char *domain_path) +{ + TALLOC_CTX *tmp_ctx; + sss_sifp_error error; + DBusMessage *reply; + const char *server; + const char **services; + int num_services; + errno_t ret; + int i; + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n"); + return ENOMEM; + } + + error = sssctl_sifp_send(tmp_ctx, sifp, &reply, domain_path, + IFACE_IFP_DOMAINS_DOMAIN, + IFACE_IFP_DOMAINS_DOMAIN_LISTSERVICES); + if (error != SSS_SIFP_OK) { + sssctl_sifp_error(sifp, error, "Unable to list services"); + ret = EIO; + goto done; + } + + ret = sbus_parse_reply(reply, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, + &services, &num_services); + if (ret != EOK) { + goto done; + } + + printf(_("Active servers:\n")); + for (i = 0; i < num_services; i++) { + error = sssctl_sifp_send(tmp_ctx, sifp, &reply, domain_path, + IFACE_IFP_DOMAINS_DOMAIN, + IFACE_IFP_DOMAINS_DOMAIN_ACTIVESERVER, + DBUS_TYPE_STRING, &services[i]); + if (error != SSS_SIFP_OK) { + sssctl_sifp_error(sifp, error, "Unable to get active server"); + ret = EIO; + goto done; + } + + ret = sbus_parse_reply(reply, DBUS_TYPE_STRING, &server); + if (ret != EOK) { + goto done; + } + + server = SBUS_IS_STRING_EMPTY(server) ? _("not connected") : server; + printf("%s: %s\n", proper_service_name(services[i]), server); + } + + ret = EOK; + +done: + talloc_free(tmp_ctx); + return ret; +} + +static errno_t sssctl_domain_status_server_list(struct sss_tool_ctx *tool_ctx, + sss_sifp_ctx *sifp, + const char *domain_path) +{ + TALLOC_CTX *tmp_ctx; + sss_sifp_error error; + DBusMessage *reply; + const char **servers; + int num_servers; + const char **services; + int num_services; + errno_t ret; + int i, j; + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n"); + return ENOMEM; + } + + error = sssctl_sifp_send(tmp_ctx, sifp, &reply, domain_path, + IFACE_IFP_DOMAINS_DOMAIN, + IFACE_IFP_DOMAINS_DOMAIN_LISTSERVICES); + if (error != SSS_SIFP_OK) { + sssctl_sifp_error(sifp, error, "Unable to list services"); + ret = EIO; + goto done; + } + + ret = sbus_parse_reply(reply, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, + &services, &num_services); + if (ret != EOK) { + goto done; + } + + for (i = 0; i < num_services; i++) { + printf(_("Discovered %s servers:\n"), proper_service_name(services[i])); + error = sssctl_sifp_send(tmp_ctx, sifp, &reply, domain_path, + IFACE_IFP_DOMAINS_DOMAIN, + IFACE_IFP_DOMAINS_DOMAIN_LISTSERVERS, + DBUS_TYPE_STRING, &services[i]); + if (error != SSS_SIFP_OK) { + sssctl_sifp_error(sifp, error, "Unable to get active server"); + ret = EIO; + goto done; + } + + ret = sbus_parse_reply(reply, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, + &servers, &num_servers); + if (ret != EOK) { + goto done; + } + + if (num_servers == 0) { + puts(_("None so far.\n")); + continue; + } + + for (j = 0; j < num_servers; j++) { + printf("- %s\n", servers[j]); + } + + printf("\n"); + } + + ret = EOK; + +done: + talloc_free(tmp_ctx); + return ret; +} + struct sssctl_domain_status_opts { const char *domain; int online; @@ -135,11 +284,8 @@ errno_t sssctl_domain_status(struct sss_cmdline *cmdline, /* Parse command line. */ struct poptOption options[] = { {"online", 'o', POPT_ARG_NONE , &opts.online, 0, _("Show online status"), NULL }, - /* - {"last-requests", 'l', POPT_ARG_NONE, &opts.last, 0, _("Show last requests that went to data provider"), NULL }, {"active-server", 'a', POPT_ARG_NONE, &opts.active, 0, _("Show information about active server"), NULL }, {"servers", 'r', POPT_ARG_NONE, &opts.servers, 0, _("Show list of discovered servers"), NULL }, - */ {"start", 's', POPT_ARG_NONE, &opts.force_start, 0, _("Start SSSD if it is not running"), NULL }, POPT_TABLEEND }; @@ -175,10 +321,32 @@ errno_t sssctl_domain_status(struct sss_cmdline *cmdline, return EFAULT; } - ret = sssctl_domain_status_online(tool_ctx, sifp, path); - if (ret != EOK) { - fprintf(stderr, _("Unable to get online status\n")); - return ret; + if (opts.online) { + ret = sssctl_domain_status_online(tool_ctx, sifp, path); + if (ret != EOK) { + fprintf(stderr, _("Unable to get online status\n")); + return ret; + } + + printf("\n"); + } + + if (opts.active) { + ret = sssctl_domain_status_active_server(tool_ctx, sifp, path); + if (ret != EOK) { + fprintf(stderr, _("Unable to get online status\n")); + return ret; + } + + printf("\n"); + } + + if (opts.servers) { + ret = sssctl_domain_status_server_list(tool_ctx, sifp, path); + if (ret != EOK) { + fprintf(stderr, _("Unable to get server list\n")); + return ret; + } } return EOK; -- 2.4.11