From 7f4199c2d4dc9147be436005d75e03fc468f5349 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
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 <lslebodn@redhat.com>
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
(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 @@
<arg name="domain_name" type="s" direction="in" />
<arg name="services" type="as" direction="out" />
</method>
+ <method name="ActiveServer">
+ <arg name="service_name" type="s" direction="in" />
+ <arg name="server" type="s" direction="out" />
+ </method>
+ <method name="ListServers">
+ <arg name="service_name" type="s" direction="in" />
+ <arg name="servers" type="as" direction="out" />
+ </method>
</interface>
<interface name="org.freedesktop.sssd.dataprovider">
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 @@
<method name="ListServices">
<arg name="services" type="as" direction="out" />
</method>
+
+ <method name="ActiveServer">
+ <arg name="service" type="s" direction="in" />
+ <arg name="server" type="s" direction="out" />
+ </method>
+
+ <method name="ListServers">
+ <arg name="service_name" type="s" direction="in" />
+ <arg name="servers" type="as" direction="out" />
+ </method>
</interface>
<interface name="org.freedesktop.sssd.infopipe.Cache">
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