/*
* Copyright (C) Sumit Bose 2009
*
* 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 the Free
* Software Foundation; either version 3 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see .
*
*/
#include
#include
#include "tevent.h"
#include "util/util.h"
#include "sbus/sssd_dbus.h"
#include "sbus_interfaces.h"
#include "util/service_helpers.h"
#include "providers/data_provider.h"
struct pp_context {
struct event_context *event_ctx;
struct service_sbus_ctx *sbus_dp_ctx;
};
static void task_check_for_new_policies(struct event_context *ev_ctx,
struct timed_event *te,
struct timeval tval, void *ptr);
static void process_dp_reply(DBusPendingCall *pending, void *ptr);
static void set_task_check_for_new_policies(struct pp_context *pp_ctx) {
struct timed_event *te = NULL;
struct timeval tv;
gettimeofday(&tv, NULL);
tv.tv_sec += 5;
tv.tv_usec = 0;
te = event_add_timed(pp_ctx->event_ctx, pp_ctx, tv, task_check_for_new_policies, pp_ctx);
if (te == NULL) exit(1);
}
static void task_check_for_new_policies(struct event_context *ev_ctx,
struct timed_event *te,
struct timeval tval, void *ptr) {
DBusMessage* msg;
DBusConnection *conn;
DBusPendingCall* pending;
struct pp_context *pp_ctx = talloc_get_type(ptr, struct pp_context);
DEBUG(0,("Hello, I'm task_check_for_new_policies.\n"));
conn = sbus_get_connection(pp_ctx->sbus_dp_ctx->scon_ctx);
msg = dbus_message_new_method_call(NULL,
DP_CLI_PATH,
DP_CLI_INTERFACE,
DP_PP_GET_POLICIES);
if (msg == NULL) {
DEBUG(0, ("dbus_message_new_method_call returned NULL, I do not know what to do, aborting ...\n"));
/* FIXME */
exit(1);
}
if (!dbus_connection_send_with_reply (conn, msg, &pending, -1)) {
DEBUG(0, ("Out Of Memory!\n"));
/* FIXME */
exit(1);
}
if ( pending == NULL ) {
DEBUG(0, ("pending is NULL\n"));
/* FIXME */
exit(1);
}
dbus_pending_call_set_notify(pending, process_dp_reply, pp_ctx, NULL);
dbus_message_unref(msg);
}
static void process_dp_reply(DBusPendingCall *pending, void *ptr) {
DBusError dbus_error;
DBusMessage* msg;
int ret;
int type;
dbus_uint32_t ans;
dbus_error_init(&dbus_error);
dbus_pending_call_block(pending);
msg = dbus_pending_call_steal_reply(pending);
if (msg == NULL) {
DEBUG(0, ("Reply Null\n"));
/* FIXME */
exit(1);
}
type = dbus_message_get_type(msg);
switch (type) {
case DBUS_MESSAGE_TYPE_METHOD_RETURN:
ret = dbus_message_get_args(msg, &dbus_error,
DBUS_TYPE_UINT32, &ans,
DBUS_TYPE_INVALID);
if (!ret) {
DEBUG(0, ("Failed to parse reply.\n"));
exit(1);
} else {
switch(ans) {
case POL_ANS_OFFLINE:
DEBUG(3, ("Got POL_ANS_OFFLINE\n"));
break;
case POL_ANS_NOTHING_TO_DO:
DEBUG(3, ("Got POL_ANS_NOTHING_TO_DO\n"));
break;
case POL_ANS_NEW_POL_AVAIL:
DEBUG(3, ("Got POL_ANS_NEW_POL_AVAIL\n"));
break;
case POL_ANS_ERROR:
DEBUG(3, ("Got POL_ANS_ERROR\n"));
break;
default:
DEBUG(3, ("Got unknow reply: %d\n", ans));
}
}
break;
case DBUS_MESSAGE_TYPE_ERROR:
DEBUG(0, ("Reply error.\n"));
break;
default:
DEBUG(0, ("Default... what now?.\n"));
}
dbus_pending_call_unref(pending);
dbus_message_unref(msg);
set_task_check_for_new_policies(ptr);
}
static int service_identity(DBusMessage *message, void *data, DBusMessage **r);
static int service_pong(DBusMessage *message, void *data, DBusMessage **r);
static int dp_cli_identity(DBusMessage *message, void *data, DBusMessage **r);
struct sbus_method sbus_monitor_methods[] = {
{SERVICE_METHOD_IDENTITY, service_identity},
{SERVICE_METHOD_PING, service_pong},
{NULL, NULL}
};
struct sbus_method sbus_dp_methods[] = {
{DP_CLI_METHOD_IDENTITY, dp_cli_identity},
{NULL, NULL}
};
static int dp_cli_identity(DBusMessage *message, void *data, DBusMessage **r) {
dbus_uint16_t version = 0x0001; /*FIXME */
dbus_uint16_t clitype = DP_CLI_FRONTEND;
DBusMessage *reply;
dbus_bool_t ret;
char *name="PolicyProcessor";
char *domain="IPA";
DEBUG(0, ("dp_cli_identity got called.\n"));
reply = dbus_message_new_method_return(message);
ret = dbus_message_append_args(reply,
DBUS_TYPE_UINT16, &clitype,
DBUS_TYPE_UINT16, &version,
DBUS_TYPE_STRING, &name,
DBUS_TYPE_STRING, &domain,
DBUS_TYPE_INVALID);
if (!ret) {
return EIO;
}
*r = reply;
return EOK;
}
static int service_identity(DBusMessage *message, void *data, DBusMessage **r)
{
dbus_uint16_t version = 0x0001;
const char *name = "PolicyProcessor";
DBusMessage *reply;
dbus_bool_t ret;
DEBUG(0, ("service_identity got called.\n"));
reply = dbus_message_new_method_return(message);
ret = dbus_message_append_args(reply,
DBUS_TYPE_STRING, &name,
DBUS_TYPE_UINT16, &version,
DBUS_TYPE_INVALID);
if (!ret) {
return EIO;
}
*r = reply;
return EOK;
}
static int service_pong(DBusMessage *message, void *data, DBusMessage **r)
{
DBusMessage *reply;
dbus_bool_t ret;
reply = dbus_message_new_method_return(message);
ret = dbus_message_append_args(reply, DBUS_TYPE_INVALID);
if (!ret) {
return EIO;
}
*r = reply;
return EOK;
}
static int sssd_dp_sbus_init(TALLOC_CTX *mem_ctx,
struct event_context *ev,
struct confdb_ctx *cdb,
struct sbus_method *methods,
struct service_sbus_ctx **srvs_ctx,
sbus_conn_destructor_fn destructor) {
struct service_sbus_ctx *ss_ctx;
struct sbus_method_ctx *sm_ctx;
TALLOC_CTX *ctx;
char *default_dp_address;
int ret;
ctx = talloc_new(mem_ctx);
if (ctx == NULL) {
ret = ENOMEM;
goto done;
}
ss_ctx = talloc_zero(ctx, struct service_sbus_ctx);
if (ss_ctx == NULL) {
ret = ENOMEM;
goto done;
}
ss_ctx->ev = ev;
default_dp_address = talloc_asprintf(ctx, "unix:path=%s/%s",
PIPE_PATH, DATA_PROVIDER_PIPE);
if (default_dp_address == NULL) {
ret = ENOMEM;
goto done;
}
ret = sbus_new_connection(ss_ctx, ss_ctx->ev,
default_dp_address, &ss_ctx->scon_ctx,
destructor);
if (ret != EOK) goto done;
sm_ctx = talloc_zero(ss_ctx, struct sbus_method_ctx);
if (sm_ctx == NULL) {
ret = ENOMEM;
goto done;
}
sm_ctx->interface = talloc_strdup(sm_ctx, DATA_PROVIDER_INTERFACE);
sm_ctx->path = talloc_strdup(sm_ctx, DATA_PROVIDER_PATH);
if (!sm_ctx->interface || !sm_ctx->path) {
ret = ENOMEM;
goto done;
}
sm_ctx->methods = methods;
sm_ctx->message_handler = sbus_message_handler;
sbus_conn_add_method_ctx(ss_ctx->scon_ctx, sm_ctx);
talloc_steal(mem_ctx,ss_ctx);
*srvs_ctx = ss_ctx;
ret = EOK;
done:
talloc_free(ctx);
return ret;
}
int setup_sbus_and_server_loop(void) {
int ret=0;
struct main_context *main_ctx = NULL;
struct service_sbus_ctx *sbus_ctx = NULL;
struct service_sbus_ctx *sbus_dp_ctx = NULL;
struct pp_context *pp_ctx;
ret = server_setup("PolicyProcessor", 0, &main_ctx);
if (ret != EOK ) {
DEBUG(0, ("sever_setup failed.\n"));
return ret;
}
sbus_ctx = sssd_service_sbus_init(main_ctx, main_ctx->event_ctx,
main_ctx->confdb_ctx, sbus_monitor_methods, NULL);
if (sbus_ctx == NULL) return -1;
ret = sssd_dp_sbus_init(main_ctx, main_ctx->event_ctx,
main_ctx->confdb_ctx, sbus_dp_methods,
&sbus_dp_ctx, NULL);
if (ret != EOK) goto done;
pp_ctx = talloc_zero(main_ctx, struct pp_context);
if (pp_ctx == NULL) {
ret = ENOMEM;
goto done;
}
pp_ctx->event_ctx = main_ctx->event_ctx;
pp_ctx->sbus_dp_ctx = sbus_dp_ctx;
set_task_check_for_new_policies(pp_ctx);
server_loop(main_ctx);
done:
talloc_free(main_ctx);
return ret;
}