mirror of
https://gitlab.com/openconnect/ocserv.git
synced 2026-02-10 16:57:00 +08:00
1366 lines
32 KiB
C
1366 lines
32 KiB
C
/*
|
|
* Copyright (C) 2014 Red Hat
|
|
*
|
|
* 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 2 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 <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include <config.h>
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <sys/types.h>
|
|
#include <sys/socket.h>
|
|
#include <sys/un.h>
|
|
#include <main.h>
|
|
#include <vpn.h>
|
|
#include <ip-lease.h>
|
|
|
|
#include <errno.h>
|
|
#include <main-ctl.h>
|
|
#include <main-ban.h>
|
|
#include <dbus/dbus.h>
|
|
#include <str.h>
|
|
|
|
#define OCSERV_DBUS_NAME "org.infradead.ocserv"
|
|
|
|
struct ctl_list_st {
|
|
struct list_head head;
|
|
};
|
|
|
|
struct dbus_ctx {
|
|
struct ctl_list_st ctl_list;
|
|
DBusConnection *conn;
|
|
};
|
|
|
|
static void method_status(main_server_st * s, struct dbus_ctx *ctx,
|
|
DBusMessage * msg);
|
|
static void method_list_users(main_server_st * s, struct dbus_ctx *ctx,
|
|
DBusMessage * msg);
|
|
static void method_unban_ip(main_server_st * s,
|
|
struct dbus_ctx *ctx,
|
|
DBusMessage * msg);
|
|
static void method_disconnect_user_name(main_server_st * s,
|
|
struct dbus_ctx *ctx,
|
|
DBusMessage * msg);
|
|
static void method_disconnect_user_id(main_server_st * s, struct dbus_ctx *ctx,
|
|
DBusMessage * msg);
|
|
static void method_introspect(main_server_st * s, struct dbus_ctx *ctx,
|
|
DBusMessage * msg);
|
|
static void method_stop(main_server_st * s, struct dbus_ctx *ctx,
|
|
DBusMessage * msg);
|
|
static void method_reload(main_server_st * s, struct dbus_ctx *ctx,
|
|
DBusMessage * msg);
|
|
static void method_user_info(main_server_st * s, struct dbus_ctx *ctx,
|
|
DBusMessage * msg);
|
|
static void method_id_info(main_server_st * s, struct dbus_ctx *ctx,
|
|
DBusMessage * msg);
|
|
static void method_list_banned(main_server_st * s, struct dbus_ctx *ctx,
|
|
DBusMessage * msg);
|
|
|
|
typedef void (*method_func) (main_server_st * s, struct dbus_ctx *ctx,
|
|
DBusMessage * msg);
|
|
#define CTL_READ 1
|
|
#define CTL_WRITE 2
|
|
|
|
struct ctl_handler_st {
|
|
struct list_node list;
|
|
int fd;
|
|
unsigned type; /* CTL_READ/WRITE */
|
|
unsigned enabled;
|
|
void *watch;
|
|
};
|
|
|
|
typedef struct {
|
|
char *name;
|
|
unsigned name_size;
|
|
char *iface;
|
|
unsigned iface_size;
|
|
char *desc;
|
|
unsigned desc_size;
|
|
method_func func;
|
|
} ctl_method_st;
|
|
|
|
#define ENTRY(name, iface, desc, func) \
|
|
{name, sizeof(name)-1, iface, sizeof(iface)-1, desc, sizeof(desc)-1, func}
|
|
|
|
#define LIST_USERS_SIG "(issssssssusssss)"
|
|
#define LIST_SINGLE_USER_SIG "(issssssssusssssuuasasasas)"
|
|
#define LIST_BANNED_SIG "(usu)"
|
|
|
|
#define DESC_LIST \
|
|
" <method name=\"list\">\n" \
|
|
" <arg name=\"user-info\" direction=\"out\" type=\"a"LIST_USERS_SIG"\"/>\n" \
|
|
" </method>\n"
|
|
|
|
#define DESC_LIST_BANNED \
|
|
" <method name=\"list\">\n" \
|
|
" <arg name=\"banned-info\" direction=\"out\" type=\"a"LIST_BANNED_SIG"\"/>\n" \
|
|
" </method>\n"
|
|
|
|
#define DESC_USER_INFO \
|
|
" <method name=\"user_info\">\n" \
|
|
" <arg name=\"user-info\" direction=\"out\" type=\"a"LIST_SINGLE_USER_SIG"\"/>\n" \
|
|
" </method>\n"
|
|
|
|
/* ID-INFO returns an array of 0 or 1 elements */
|
|
#define DESC_ID_INFO \
|
|
" <method name=\"id_info\">\n" \
|
|
" <arg name=\"id-info\" direction=\"out\" type=\"a"LIST_SINGLE_USER_SIG"\"/>\n" \
|
|
" </method>\n"
|
|
|
|
#define DESC_DISC_NAME \
|
|
" <method name=\"disconnect_name\">\n" \
|
|
" <arg name=\"user-name\" direction=\"in\" type=\"s\"/>\n" \
|
|
" <arg name=\"status\" direction=\"out\" type=\"b\"/>\n" \
|
|
" </method>\n"
|
|
|
|
#define DESC_RELOAD \
|
|
" <method name=\"reload\">\n" \
|
|
" <arg name=\"status\" direction=\"out\" type=\"b\"/>\n" \
|
|
" </method>\n"
|
|
|
|
#define DESC_STOP \
|
|
" <method name=\"stop\">\n" \
|
|
" <arg name=\"status\" direction=\"out\" type=\"b\"/>\n" \
|
|
" </method>\n"
|
|
|
|
#define DESC_DISC_ID \
|
|
" <method name=\"disconnect_id\">\n" \
|
|
" <arg name=\"user-id\" direction=\"in\" type=\"u\"/>\n" \
|
|
" <arg name=\"status\" direction=\"out\" type=\"b\"/>\n" \
|
|
" </method>\n"
|
|
|
|
#define DESC_UNBAN_IP \
|
|
" <method name=\"unban_ip\">\n" \
|
|
" <arg name=\"user-ip\" direction=\"in\" type=\"s\"/>\n" \
|
|
" <arg name=\"status\" direction=\"out\" type=\"b\"/>\n" \
|
|
" </method>\n"
|
|
|
|
#define DESC_STATUS \
|
|
" <method name=\"status\">\n" \
|
|
" <arg name=\"status\" direction=\"out\" type=\"b\"/>\n" \
|
|
" <arg name=\"pid\" direction=\"out\" type=\"u\"/>\n" \
|
|
" <arg name=\"sec-mod-pid\" direction=\"out\" type=\"u\"/>\n" \
|
|
" <arg name=\"clients\" direction=\"out\" type=\"u\"/>\n" \
|
|
" <arg name=\"tls-sessions\" direction=\"out\" type=\"u\"/>\n" \
|
|
" <arg name=\"banned-ips\" direction=\"out\" type=\"u\"/>\n" \
|
|
" </method>\n"
|
|
|
|
static const ctl_method_st methods[] = {
|
|
ENTRY("Introspect", "org.freedesktop.DBus.Introspectable", NULL,
|
|
method_introspect),
|
|
ENTRY("status", "org.infradead.ocserv", DESC_STATUS, method_status),
|
|
ENTRY("reload", "org.infradead.ocserv", DESC_RELOAD, method_reload),
|
|
ENTRY("stop", "org.infradead.ocserv", DESC_RELOAD, method_stop),
|
|
ENTRY("list", "org.infradead.ocserv", DESC_LIST, method_list_users),
|
|
ENTRY("list_banned", "org.infradead.ocserv", DESC_LIST_BANNED, method_list_banned),
|
|
ENTRY("user_info2", "org.infradead.ocserv", DESC_USER_INFO,
|
|
method_user_info),
|
|
ENTRY("id_info2", "org.infradead.ocserv", DESC_ID_INFO, method_id_info),
|
|
ENTRY("disconnect_name", "org.infradead.ocserv", DESC_DISC_NAME,
|
|
method_disconnect_user_name),
|
|
ENTRY("unban_ip", "org.infradead.ocserv", DESC_UNBAN_IP,
|
|
method_unban_ip),
|
|
ENTRY("disconnect_id", "org.infradead.ocserv", DESC_DISC_ID,
|
|
method_disconnect_user_id),
|
|
{NULL, 0, NULL, 0, NULL}
|
|
};
|
|
|
|
static void add_ctl_fd(struct dbus_ctx *ctx, int fd, void *watch, unsigned type)
|
|
{
|
|
struct ctl_handler_st *tmp;
|
|
|
|
tmp = talloc_zero(ctx, struct ctl_handler_st);
|
|
if (tmp == NULL)
|
|
return;
|
|
|
|
tmp->fd = fd;
|
|
if (dbus_watch_get_enabled(watch))
|
|
tmp->enabled = 1;
|
|
else
|
|
tmp->enabled = 0;
|
|
tmp->watch = watch;
|
|
tmp->type = type;
|
|
|
|
syslog(LOG_DEBUG, "dbus: adding %s %swatch for fd: %d",
|
|
(type == CTL_READ) ? "read" : "write",
|
|
(tmp->enabled) ? "" : "(disabled) ", fd);
|
|
|
|
list_add(&ctx->ctl_list.head, &(tmp->list));
|
|
}
|
|
|
|
static dbus_bool_t add_watch(DBusWatch * watch, void *data)
|
|
{
|
|
int fd = dbus_watch_get_unix_fd(watch);
|
|
struct dbus_ctx *ctx = data;
|
|
unsigned flags;
|
|
|
|
flags = dbus_watch_get_flags(watch);
|
|
|
|
if (flags & DBUS_WATCH_READABLE) {
|
|
add_ctl_fd(ctx, fd, watch, CTL_READ);
|
|
} else {
|
|
add_ctl_fd(ctx, fd, watch, CTL_WRITE);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
static void remove_watch(DBusWatch * watch, void *data)
|
|
{
|
|
struct dbus_ctx *ctx = data;
|
|
struct ctl_handler_st *btmp = NULL, *bpos;
|
|
|
|
list_for_each_safe(&ctx->ctl_list.head, btmp, bpos, list) {
|
|
if (btmp->watch == watch) {
|
|
syslog(LOG_DEBUG,
|
|
"dbus: removing %s watch for fd: %d",
|
|
(btmp->type == CTL_READ) ? "read" : "write",
|
|
btmp->fd);
|
|
|
|
list_del(&btmp->list);
|
|
talloc_free(btmp);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void toggle_watch(DBusWatch * watch, void *data)
|
|
{
|
|
struct dbus_ctx *ctx = data;
|
|
struct ctl_handler_st *btmp = NULL;
|
|
|
|
list_for_each(&ctx->ctl_list.head, btmp, list) {
|
|
if (btmp->watch == watch) {
|
|
if (dbus_watch_get_enabled(watch)) {
|
|
btmp->enabled = 1;
|
|
} else
|
|
btmp->enabled = 0;
|
|
|
|
syslog(LOG_DEBUG,
|
|
"dbus: %s %s watch for fd: %d",
|
|
(btmp->enabled) ? "enabling" : "disabling",
|
|
(btmp->type == CTL_READ) ? "read" : "write",
|
|
btmp->fd);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
static void method_status(main_server_st * s, struct dbus_ctx *ctx,
|
|
DBusMessage * msg)
|
|
{
|
|
DBusMessage *reply;
|
|
DBusMessageIter args;
|
|
dbus_bool_t status = true;
|
|
dbus_uint32_t tmp;
|
|
|
|
mslog(s, NULL, LOG_DEBUG, "ctl: status");
|
|
|
|
/* no arguments needed */
|
|
reply = dbus_message_new_method_return(msg);
|
|
if (reply == NULL) {
|
|
mslog(s, NULL, LOG_ERR, "error generating dbus reply");
|
|
return;
|
|
}
|
|
|
|
dbus_message_iter_init_append(reply, &args);
|
|
|
|
if (dbus_message_iter_append_basic(&args, DBUS_TYPE_BOOLEAN, &status) ==
|
|
0) {
|
|
mslog(s, NULL, LOG_ERR, "error appending to dbus reply");
|
|
goto error;
|
|
}
|
|
|
|
tmp = getpid();
|
|
if (dbus_message_iter_append_basic(&args, DBUS_TYPE_UINT32, &tmp) == 0) {
|
|
mslog(s, NULL, LOG_ERR, "error appending to dbus reply");
|
|
goto error;
|
|
}
|
|
|
|
tmp = s->sec_mod_pid;
|
|
if (dbus_message_iter_append_basic(&args, DBUS_TYPE_UINT32, &tmp) == 0) {
|
|
mslog(s, NULL, LOG_ERR, "error appending to dbus reply");
|
|
goto error;
|
|
}
|
|
|
|
tmp = s->active_clients;
|
|
if (dbus_message_iter_append_basic(&args, DBUS_TYPE_UINT32, &tmp) == 0) {
|
|
mslog(s, NULL, LOG_ERR, "error appending to dbus reply");
|
|
goto error;
|
|
}
|
|
|
|
tmp = s->tls_db.entries;
|
|
if (dbus_message_iter_append_basic(&args, DBUS_TYPE_UINT32, &tmp) == 0) {
|
|
mslog(s, NULL, LOG_ERR, "error appending to dbus reply");
|
|
goto error;
|
|
}
|
|
|
|
if (dbus_message_iter_append_basic(&args, DBUS_TYPE_UINT32, &tmp) == 0) {
|
|
mslog(s, NULL, LOG_ERR, "error appending to dbus reply");
|
|
goto error;
|
|
}
|
|
|
|
if (!dbus_connection_send(ctx->conn, reply, NULL)) {
|
|
mslog(s, NULL, LOG_ERR, "error sending dbus reply");
|
|
goto error;
|
|
}
|
|
|
|
error:
|
|
dbus_message_unref(reply);
|
|
|
|
return;
|
|
}
|
|
|
|
static void method_reload(main_server_st * s, struct dbus_ctx *ctx,
|
|
DBusMessage * msg)
|
|
{
|
|
DBusMessage *reply;
|
|
DBusMessageIter args;
|
|
dbus_bool_t status = true;
|
|
|
|
mslog(s, NULL, LOG_DEBUG, "ctl: reload");
|
|
|
|
/* no arguments needed */
|
|
reply = dbus_message_new_method_return(msg);
|
|
if (reply == NULL) {
|
|
mslog(s, NULL, LOG_ERR, "error generating dbus reply");
|
|
return;
|
|
}
|
|
|
|
dbus_message_iter_init_append(reply, &args);
|
|
|
|
if (dbus_message_iter_append_basic(&args, DBUS_TYPE_BOOLEAN, &status) ==
|
|
0) {
|
|
mslog(s, NULL, LOG_ERR, "error appending to dbus reply");
|
|
goto error;
|
|
}
|
|
|
|
request_reload(0);
|
|
|
|
if (!dbus_connection_send(ctx->conn, reply, NULL)) {
|
|
mslog(s, NULL, LOG_ERR, "error sending dbus reply");
|
|
goto error;
|
|
}
|
|
|
|
error:
|
|
dbus_message_unref(reply);
|
|
|
|
return;
|
|
}
|
|
|
|
static void method_stop(main_server_st * s, struct dbus_ctx *ctx,
|
|
DBusMessage * msg)
|
|
{
|
|
DBusMessage *reply;
|
|
DBusMessageIter args;
|
|
dbus_bool_t status = true;
|
|
|
|
mslog(s, NULL, LOG_DEBUG, "ctl: stop");
|
|
|
|
/* no arguments needed */
|
|
reply = dbus_message_new_method_return(msg);
|
|
if (reply == NULL) {
|
|
mslog(s, NULL, LOG_ERR, "error generating dbus reply");
|
|
return;
|
|
}
|
|
|
|
dbus_message_iter_init_append(reply, &args);
|
|
|
|
if (dbus_message_iter_append_basic(&args, DBUS_TYPE_BOOLEAN, &status) ==
|
|
0) {
|
|
mslog(s, NULL, LOG_ERR, "error appending to dbus reply");
|
|
goto error;
|
|
}
|
|
|
|
request_stop(0);
|
|
|
|
if (!dbus_connection_send(ctx->conn, reply, NULL)) {
|
|
mslog(s, NULL, LOG_ERR, "error sending dbus reply");
|
|
goto error;
|
|
}
|
|
|
|
error:
|
|
dbus_message_unref(reply);
|
|
|
|
return;
|
|
}
|
|
|
|
static int append_list(DBusMessageIter * subs, char **list, unsigned list_size)
|
|
{
|
|
DBusMessageIter suba;
|
|
unsigned i;
|
|
|
|
if (dbus_message_iter_open_container
|
|
(subs, DBUS_TYPE_ARRAY, "s", &suba) == 0) {
|
|
return -1;
|
|
}
|
|
|
|
for (i = 0; i < list_size; i++) {
|
|
if (dbus_message_iter_append_basic
|
|
(&suba, DBUS_TYPE_STRING, &list[i]) == 0) {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
if (dbus_message_iter_close_container(subs, &suba) == 0) {
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int append_user_info(main_server_st * s, DBusMessageIter * subs,
|
|
struct proc_st *ctmp, unsigned single)
|
|
{
|
|
dbus_uint32_t tmp;
|
|
dbus_int32_t stmp;
|
|
char ipbuf[128];
|
|
const char *strtmp;
|
|
char **list;
|
|
unsigned list_size;
|
|
int ret;
|
|
|
|
/* ID: pid */
|
|
stmp = ctmp->pid;
|
|
if (dbus_message_iter_append_basic(subs, DBUS_TYPE_INT32, &stmp) == 0) {
|
|
return -1;
|
|
}
|
|
|
|
strtmp = ctmp->username;
|
|
if (dbus_message_iter_append_basic
|
|
(subs, DBUS_TYPE_STRING, &strtmp) == 0) {
|
|
return -1;
|
|
}
|
|
|
|
strtmp = ctmp->groupname;
|
|
if (dbus_message_iter_append_basic
|
|
(subs, DBUS_TYPE_STRING, &strtmp) == 0) {
|
|
return -1;
|
|
}
|
|
|
|
strtmp =
|
|
human_addr2((struct sockaddr *)&ctmp->remote_addr,
|
|
ctmp->remote_addr_len, ipbuf, sizeof(ipbuf), 0);
|
|
if (strtmp == NULL)
|
|
strtmp = "";
|
|
if (dbus_message_iter_append_basic
|
|
(subs, DBUS_TYPE_STRING, &strtmp) == 0) {
|
|
return -1;
|
|
}
|
|
strtmp = ctmp->tun_lease.name;
|
|
if (dbus_message_iter_append_basic
|
|
(subs, DBUS_TYPE_STRING, &strtmp) == 0) {
|
|
return -1;
|
|
}
|
|
|
|
strtmp = NULL;
|
|
if (ctmp->ipv4 != NULL)
|
|
strtmp =
|
|
human_addr2((struct sockaddr *)&ctmp->ipv4->rip,
|
|
ctmp->ipv4->rip_len, ipbuf, sizeof(ipbuf), 0);
|
|
if (strtmp == NULL)
|
|
strtmp = "";
|
|
if (dbus_message_iter_append_basic
|
|
(subs, DBUS_TYPE_STRING, &strtmp) == 0) {
|
|
return -1;
|
|
}
|
|
|
|
strtmp = NULL;
|
|
if (ctmp->ipv4 != NULL)
|
|
strtmp =
|
|
human_addr2((struct sockaddr *)&ctmp->ipv4->lip,
|
|
ctmp->ipv4->lip_len, ipbuf, sizeof(ipbuf), 0);
|
|
if (strtmp == NULL)
|
|
strtmp = "";
|
|
if (dbus_message_iter_append_basic
|
|
(subs, DBUS_TYPE_STRING, &strtmp) == 0) {
|
|
return -1;
|
|
}
|
|
|
|
strtmp = NULL;
|
|
if (ctmp->ipv6 != NULL)
|
|
strtmp =
|
|
human_addr2((struct sockaddr *)&ctmp->ipv6->rip,
|
|
ctmp->ipv6->rip_len, ipbuf, sizeof(ipbuf), 0);
|
|
if (strtmp == NULL)
|
|
strtmp = "";
|
|
if (dbus_message_iter_append_basic
|
|
(subs, DBUS_TYPE_STRING, &strtmp) == 0) {
|
|
return -1;
|
|
}
|
|
|
|
strtmp = NULL;
|
|
if (ctmp->ipv6 != NULL)
|
|
strtmp =
|
|
human_addr2((struct sockaddr *)&ctmp->ipv6->lip,
|
|
ctmp->ipv6->lip_len, ipbuf, sizeof(ipbuf), 0);
|
|
if (strtmp == NULL)
|
|
strtmp = "";
|
|
if (dbus_message_iter_append_basic
|
|
(subs, DBUS_TYPE_STRING, &strtmp) == 0) {
|
|
return -1;
|
|
}
|
|
tmp = ctmp->conn_time;
|
|
if (dbus_message_iter_append_basic(subs, DBUS_TYPE_UINT32, &tmp) == 0) {
|
|
return -1;
|
|
}
|
|
|
|
strtmp = ctmp->hostname;
|
|
if (dbus_message_iter_append_basic
|
|
(subs, DBUS_TYPE_STRING, &strtmp) == 0) {
|
|
return -1;
|
|
}
|
|
|
|
strtmp = ctmp->user_agent;
|
|
if (dbus_message_iter_append_basic
|
|
(subs, DBUS_TYPE_STRING, &strtmp) == 0) {
|
|
return -1;
|
|
}
|
|
|
|
if (ctmp->status == PS_AUTH_COMPLETED)
|
|
strtmp = "connected";
|
|
else if (ctmp->status == PS_AUTH_INIT)
|
|
strtmp = "auth";
|
|
else if (ctmp->status == PS_AUTH_INACTIVE)
|
|
strtmp = "pre-auth";
|
|
else if (ctmp->status == PS_AUTH_FAILED)
|
|
strtmp = "auth failed";
|
|
else
|
|
strtmp = "unknown";
|
|
if (dbus_message_iter_append_basic
|
|
(subs, DBUS_TYPE_STRING, &strtmp) == 0) {
|
|
return -1;
|
|
}
|
|
|
|
strtmp = ctmp->tls_ciphersuite;
|
|
if (dbus_message_iter_append_basic
|
|
(subs, DBUS_TYPE_STRING, &strtmp) == 0) {
|
|
return -1;
|
|
}
|
|
|
|
strtmp = ctmp->dtls_ciphersuite;
|
|
if (dbus_message_iter_append_basic
|
|
(subs, DBUS_TYPE_STRING, &strtmp) == 0) {
|
|
return -1;
|
|
}
|
|
|
|
if (single > 0) {
|
|
if (ctmp->config.rx_per_sec > 0)
|
|
tmp = ctmp->config.rx_per_sec;
|
|
else
|
|
tmp = s->config->rx_per_sec;
|
|
tmp *= 1000;
|
|
if (dbus_message_iter_append_basic(subs, DBUS_TYPE_UINT32, &tmp)
|
|
== 0) {
|
|
return -1;
|
|
}
|
|
|
|
if (ctmp->config.tx_per_sec > 0)
|
|
tmp = ctmp->config.tx_per_sec;
|
|
else
|
|
tmp = s->config->tx_per_sec;
|
|
tmp *= 1000;
|
|
if (dbus_message_iter_append_basic(subs, DBUS_TYPE_UINT32, &tmp)
|
|
== 0) {
|
|
return -1;
|
|
}
|
|
|
|
if (ctmp->config.dns_size > 0) {
|
|
list = ctmp->config.dns;
|
|
list_size = ctmp->config.dns_size;
|
|
} else {
|
|
list = s->config->network.dns;
|
|
list_size = s->config->network.dns_size;
|
|
}
|
|
ret = append_list(subs, list, list_size);
|
|
if (ret < 0)
|
|
return ret;
|
|
|
|
if (ctmp->config.nbns_size > 0) {
|
|
list = ctmp->config.nbns;
|
|
list_size = ctmp->config.nbns_size;
|
|
} else {
|
|
list = s->config->network.nbns;
|
|
list_size = s->config->network.nbns_size;
|
|
}
|
|
ret = append_list(subs, list, list_size);
|
|
if (ret < 0)
|
|
return ret;
|
|
|
|
if (ctmp->config.routes_size > 0) {
|
|
list = ctmp->config.routes;
|
|
list_size = ctmp->config.routes_size;
|
|
} else {
|
|
list = s->config->network.routes;
|
|
list_size = s->config->network.routes_size;
|
|
}
|
|
ret = append_list(subs, list, list_size);
|
|
if (ret < 0)
|
|
return ret;
|
|
|
|
if (ctmp->config.iroutes_size > 0) {
|
|
list = ctmp->config.iroutes;
|
|
list_size = ctmp->config.iroutes_size;
|
|
} else {
|
|
list = NULL;
|
|
list_size = 0;
|
|
}
|
|
ret = append_list(subs, list, list_size);
|
|
if (ret < 0)
|
|
return ret;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void method_list_users(main_server_st * s, struct dbus_ctx *ctx,
|
|
DBusMessage * msg)
|
|
{
|
|
DBusMessage *reply;
|
|
DBusMessageIter args;
|
|
DBusMessageIter suba;
|
|
DBusMessageIter subs;
|
|
struct proc_st *ctmp = NULL;
|
|
int ret;
|
|
|
|
mslog(s, NULL, LOG_DEBUG, "ctl: list-users");
|
|
|
|
/* no arguments needed */
|
|
reply = dbus_message_new_method_return(msg);
|
|
if (reply == NULL) {
|
|
mslog(s, NULL, LOG_ERR, "error generating dbus reply");
|
|
return;
|
|
}
|
|
|
|
dbus_message_iter_init_append(reply, &args);
|
|
if (dbus_message_iter_open_container
|
|
(&args, DBUS_TYPE_ARRAY, LIST_USERS_SIG, &suba) == 0) {
|
|
mslog(s, NULL, LOG_ERR,
|
|
"error appending container to dbus reply");
|
|
goto error;
|
|
}
|
|
|
|
list_for_each(&s->proc_list.head, ctmp, list) {
|
|
|
|
if (dbus_message_iter_open_container
|
|
(&suba, DBUS_TYPE_STRUCT, NULL, &subs) == 0) {
|
|
mslog(s, NULL, LOG_ERR,
|
|
"error appending container to dbus reply");
|
|
goto error;
|
|
}
|
|
|
|
ret = append_user_info(s, &subs, ctmp, 0);
|
|
if (ret < 0) {
|
|
mslog(s, NULL, LOG_ERR,
|
|
"error appending container to dbus reply");
|
|
goto error;
|
|
}
|
|
|
|
if (dbus_message_iter_close_container(&suba, &subs) == 0) {
|
|
mslog(s, NULL, LOG_ERR,
|
|
"error closing container in dbus reply");
|
|
goto error;
|
|
}
|
|
}
|
|
|
|
if (dbus_message_iter_close_container(&args, &suba) == 0) {
|
|
mslog(s, NULL, LOG_ERR,
|
|
"error closing container in dbus reply");
|
|
goto error;
|
|
}
|
|
|
|
if (!dbus_connection_send(ctx->conn, reply, NULL)) {
|
|
mslog(s, NULL, LOG_ERR, "error sending dbus reply");
|
|
goto error;
|
|
}
|
|
|
|
error:
|
|
dbus_message_unref(reply);
|
|
|
|
return;
|
|
}
|
|
|
|
static int append_ban_info(main_server_st *s,
|
|
DBusMessageIter *suba,
|
|
struct ban_entry_st *e)
|
|
{
|
|
DBusMessageIter subs;
|
|
dbus_uint32_t t;
|
|
char *ip;
|
|
|
|
if (dbus_message_iter_open_container
|
|
(suba, DBUS_TYPE_STRUCT, NULL, &subs) == 0) {
|
|
mslog(s, NULL, LOG_ERR,
|
|
"error appending container to dbus reply");
|
|
return -1;
|
|
}
|
|
|
|
t = e->score;
|
|
if (dbus_message_iter_append_basic(&subs, DBUS_TYPE_UINT32, &t) == 0) {
|
|
mslog(s, NULL, LOG_ERR, "error appending to dbus reply");
|
|
return -1;
|
|
}
|
|
|
|
ip = e->ip;
|
|
if (dbus_message_iter_append_basic(&subs, DBUS_TYPE_STRING, &ip) == 0) {
|
|
mslog(s, NULL, LOG_ERR, "error appending to dbus reply");
|
|
return -1;
|
|
}
|
|
|
|
if (s->config->max_ban_score > 0 && e->score >= s->config->max_ban_score) {
|
|
t = e->expires;
|
|
} else {
|
|
t = 0;
|
|
}
|
|
|
|
if (dbus_message_iter_append_basic(&subs, DBUS_TYPE_UINT32, &t) == 0) {
|
|
mslog(s, NULL, LOG_ERR, "error appending to dbus reply");
|
|
return -1;
|
|
}
|
|
|
|
if (dbus_message_iter_close_container(suba, &subs) == 0) {
|
|
mslog(s, NULL, LOG_ERR,
|
|
"error closing container in dbus reply");
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void method_list_banned(main_server_st * s, struct dbus_ctx *ctx,
|
|
DBusMessage * msg)
|
|
{
|
|
DBusMessage *reply;
|
|
DBusMessageIter args;
|
|
DBusMessageIter suba;
|
|
int ret;
|
|
struct ban_entry_st *e = NULL;
|
|
struct htable *db = s->ban_db;
|
|
struct htable_iter iter;
|
|
|
|
mslog(s, NULL, LOG_DEBUG, "ctl: list-banned");
|
|
|
|
/* no arguments needed */
|
|
reply = dbus_message_new_method_return(msg);
|
|
if (reply == NULL) {
|
|
mslog(s, NULL, LOG_ERR, "error generating dbus reply");
|
|
return;
|
|
}
|
|
|
|
dbus_message_iter_init_append(reply, &args);
|
|
if (dbus_message_iter_open_container
|
|
(&args, DBUS_TYPE_ARRAY, LIST_BANNED_SIG, &suba) == 0) {
|
|
mslog(s, NULL, LOG_ERR,
|
|
"error appending container to dbus reply");
|
|
goto error;
|
|
}
|
|
|
|
e = htable_first(db, &iter);
|
|
while (e != NULL) {
|
|
ret = append_ban_info(s, &suba, e);
|
|
if (ret < 0) {
|
|
mslog(s, NULL, LOG_ERR,
|
|
"error appending ban info to reply");
|
|
goto error;
|
|
}
|
|
e = htable_next(db, &iter);
|
|
}
|
|
|
|
if (dbus_message_iter_close_container(&args, &suba) == 0) {
|
|
mslog(s, NULL, LOG_ERR,
|
|
"error closing container in dbus reply");
|
|
goto error;
|
|
}
|
|
|
|
if (!dbus_connection_send(ctx->conn, reply, NULL)) {
|
|
mslog(s, NULL, LOG_ERR, "error sending dbus reply");
|
|
goto error;
|
|
}
|
|
|
|
error:
|
|
dbus_message_unref(reply);
|
|
|
|
return;
|
|
}
|
|
|
|
static void single_info_common(main_server_st * s, struct dbus_ctx *ctx,
|
|
DBusMessage * msg, const char *user, unsigned id)
|
|
{
|
|
DBusMessage *reply;
|
|
DBusMessageIter args;
|
|
DBusMessageIter suba;
|
|
DBusMessageIter subs;
|
|
int ret;
|
|
unsigned found_user = 0;
|
|
struct proc_st *ctmp = NULL;
|
|
|
|
if (user != NULL)
|
|
mslog(s, NULL, LOG_INFO, "providing info for user '%s'", user);
|
|
else
|
|
mslog(s, NULL, LOG_INFO, "providing info for ID '%u'", id);
|
|
|
|
/* no arguments needed */
|
|
reply = dbus_message_new_method_return(msg);
|
|
if (reply == NULL) {
|
|
mslog(s, NULL, LOG_ERR, "error generating dbus reply");
|
|
return;
|
|
}
|
|
|
|
dbus_message_iter_init_append(reply, &args);
|
|
if (dbus_message_iter_open_container
|
|
(&args, DBUS_TYPE_ARRAY, LIST_SINGLE_USER_SIG, &suba) == 0) {
|
|
mslog(s, NULL, LOG_ERR,
|
|
"error appending container to dbus reply");
|
|
goto error;
|
|
}
|
|
|
|
list_for_each(&s->proc_list.head, ctmp, list) {
|
|
if (user == NULL) { /* id */
|
|
if (id == 0 || id == -1 || id != ctmp->pid) {
|
|
continue;
|
|
}
|
|
} else { /* username */
|
|
if (strcmp(ctmp->username, user) != 0) {
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if (dbus_message_iter_open_container
|
|
(&suba, DBUS_TYPE_STRUCT, NULL, &subs) == 0) {
|
|
mslog(s, NULL, LOG_ERR,
|
|
"error appending container to dbus reply");
|
|
goto error;
|
|
}
|
|
|
|
ret = append_user_info(s, &subs, ctmp, 1);
|
|
if (ret < 0) {
|
|
mslog(s, NULL, LOG_ERR,
|
|
"error appending to dbus reply");
|
|
goto error;
|
|
}
|
|
|
|
if (dbus_message_iter_close_container(&suba, &subs) == 0) {
|
|
mslog(s, NULL, LOG_ERR,
|
|
"error closing container in dbus reply");
|
|
goto error;
|
|
}
|
|
|
|
found_user = 1;
|
|
|
|
if (id != 0) /* id -> one a single element */
|
|
break;
|
|
}
|
|
|
|
if (dbus_message_iter_close_container(&args, &suba) == 0) {
|
|
mslog(s, NULL, LOG_ERR,
|
|
"error closing container in dbus reply");
|
|
goto error;
|
|
}
|
|
|
|
if (found_user == 0) {
|
|
if (user != NULL)
|
|
mslog(s, NULL, LOG_INFO, "could not find user '%s'",
|
|
user);
|
|
else
|
|
mslog(s, NULL, LOG_INFO, "could not find ID '%u'", id);
|
|
}
|
|
|
|
if (!dbus_connection_send(ctx->conn, reply, NULL)) {
|
|
mslog(s, NULL, LOG_ERR, "error sending dbus reply");
|
|
goto error;
|
|
}
|
|
|
|
error:
|
|
dbus_message_unref(reply);
|
|
|
|
return;
|
|
}
|
|
|
|
static void method_user_info(main_server_st * s, struct dbus_ctx *ctx,
|
|
DBusMessage * msg)
|
|
{
|
|
DBusMessageIter args;
|
|
const char *name;
|
|
|
|
mslog(s, NULL, LOG_DEBUG, "ctl: user_info (name)");
|
|
|
|
if (dbus_message_iter_init(msg, &args) == 0) {
|
|
mslog(s, NULL, LOG_ERR, "no arguments provided in user_info");
|
|
return;
|
|
}
|
|
|
|
if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_STRING) {
|
|
mslog(s, NULL, LOG_ERR, "wrong argument provided in user_info");
|
|
return;
|
|
}
|
|
|
|
dbus_message_iter_get_basic(&args, &name);
|
|
|
|
single_info_common(s, ctx, msg, name, 0);
|
|
|
|
return;
|
|
}
|
|
|
|
static void method_id_info(main_server_st * s, struct dbus_ctx *ctx,
|
|
DBusMessage * msg)
|
|
{
|
|
DBusMessageIter args;
|
|
dbus_uint32_t id;
|
|
|
|
mslog(s, NULL, LOG_DEBUG, "ctl: user_info (id)");
|
|
|
|
if (dbus_message_iter_init(msg, &args) == 0) {
|
|
mslog(s, NULL, LOG_ERR, "no arguments provided in user_info");
|
|
return;
|
|
}
|
|
|
|
if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_UINT32) {
|
|
mslog(s, NULL, LOG_ERR, "wrong argument provided in user_info");
|
|
return;
|
|
}
|
|
|
|
dbus_message_iter_get_basic(&args, &id);
|
|
|
|
single_info_common(s, ctx, msg, NULL, id);
|
|
|
|
return;
|
|
}
|
|
|
|
static void method_unban_ip(main_server_st * s,
|
|
struct dbus_ctx *ctx,
|
|
DBusMessage * msg)
|
|
{
|
|
DBusMessage *reply;
|
|
DBusMessageIter args;
|
|
dbus_bool_t status = 0;
|
|
char *ip = "";
|
|
|
|
mslog(s, NULL, LOG_DEBUG, "ctl: unban_ip");
|
|
|
|
if (dbus_message_iter_init(msg, &args) == 0) {
|
|
mslog(s, NULL, LOG_ERR,
|
|
"no arguments provided in unban_ip");
|
|
return;
|
|
}
|
|
|
|
if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_STRING) {
|
|
mslog(s, NULL, LOG_ERR,
|
|
"wrong argument provided in unban_ip");
|
|
return;
|
|
}
|
|
|
|
dbus_message_iter_get_basic(&args, &ip);
|
|
|
|
if (remove_ip_from_ban_list(s, ip) != 0) {
|
|
if (ip)
|
|
mslog(s, NULL, LOG_INFO,
|
|
"unbanning IP '%s' due to ctl request", ip);
|
|
status = 1;
|
|
}
|
|
|
|
/* reply */
|
|
reply = dbus_message_new_method_return(msg);
|
|
if (reply == NULL) {
|
|
mslog(s, NULL, LOG_ERR, "error generating dbus reply");
|
|
return;
|
|
}
|
|
|
|
dbus_message_iter_init_append(reply, &args);
|
|
|
|
if (dbus_message_iter_append_basic(&args, DBUS_TYPE_BOOLEAN, &status) ==
|
|
0) {
|
|
mslog(s, NULL, LOG_ERR, "error appending to dbus reply");
|
|
goto error;
|
|
}
|
|
|
|
if (!dbus_connection_send(ctx->conn, reply, NULL)) {
|
|
mslog(s, NULL, LOG_ERR, "error sending dbus reply");
|
|
goto error;
|
|
}
|
|
|
|
error:
|
|
dbus_message_unref(reply);
|
|
|
|
return;
|
|
}
|
|
|
|
static void method_disconnect_user_name(main_server_st * s,
|
|
struct dbus_ctx *ctx,
|
|
DBusMessage * msg)
|
|
{
|
|
DBusMessage *reply;
|
|
DBusMessageIter args;
|
|
dbus_bool_t status = 0;
|
|
struct proc_st *ctmp = NULL, *cpos;
|
|
char *name = "";
|
|
|
|
mslog(s, NULL, LOG_DEBUG, "ctl: disconnect_name");
|
|
|
|
if (dbus_message_iter_init(msg, &args) == 0) {
|
|
mslog(s, NULL, LOG_ERR,
|
|
"no arguments provided in disconnect_name");
|
|
return;
|
|
}
|
|
|
|
if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_STRING) {
|
|
mslog(s, NULL, LOG_ERR,
|
|
"wrong argument provided in disconnect_name");
|
|
return;
|
|
}
|
|
|
|
dbus_message_iter_get_basic(&args, &name);
|
|
|
|
/* got the name. Try to disconnect */
|
|
list_for_each_safe(&s->proc_list.head, ctmp, cpos, list) {
|
|
if (strcmp(ctmp->username, name) == 0) {
|
|
remove_proc(s, ctmp, 1);
|
|
status = 1;
|
|
}
|
|
}
|
|
|
|
/* reply */
|
|
reply = dbus_message_new_method_return(msg);
|
|
if (reply == NULL) {
|
|
mslog(s, NULL, LOG_ERR, "error generating dbus reply");
|
|
return;
|
|
}
|
|
|
|
dbus_message_iter_init_append(reply, &args);
|
|
|
|
if (dbus_message_iter_append_basic(&args, DBUS_TYPE_BOOLEAN, &status) ==
|
|
0) {
|
|
mslog(s, NULL, LOG_ERR, "error appending to dbus reply");
|
|
goto error;
|
|
}
|
|
|
|
if (!dbus_connection_send(ctx->conn, reply, NULL)) {
|
|
mslog(s, NULL, LOG_ERR, "error sending dbus reply");
|
|
goto error;
|
|
}
|
|
|
|
error:
|
|
dbus_message_unref(reply);
|
|
|
|
return;
|
|
}
|
|
|
|
static void method_disconnect_user_id(main_server_st * s, struct dbus_ctx *ctx,
|
|
DBusMessage * msg)
|
|
{
|
|
DBusMessage *reply;
|
|
DBusMessageIter args;
|
|
dbus_bool_t status = 0;
|
|
struct proc_st *ctmp = NULL, *cpos;
|
|
dbus_uint32_t id = 0;
|
|
|
|
mslog(s, NULL, LOG_DEBUG, "ctl: disconnect_id");
|
|
|
|
if (dbus_message_iter_init(msg, &args) == 0) {
|
|
mslog(s, NULL, LOG_ERR,
|
|
"no arguments provided in disconnect_id");
|
|
return;
|
|
}
|
|
|
|
if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_UINT32) {
|
|
mslog(s, NULL, LOG_ERR,
|
|
"wrong argument provided in disconnect_id");
|
|
return;
|
|
}
|
|
|
|
dbus_message_iter_get_basic(&args, &id);
|
|
|
|
/* got the ID. Try to disconnect */
|
|
list_for_each_safe(&s->proc_list.head, ctmp, cpos, list) {
|
|
if (ctmp->pid == id) {
|
|
remove_proc(s, ctmp, 1);
|
|
status = 1;
|
|
if (id != -1)
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* reply */
|
|
reply = dbus_message_new_method_return(msg);
|
|
if (reply == NULL) {
|
|
mslog(s, NULL, LOG_ERR, "error generating dbus reply");
|
|
return;
|
|
}
|
|
|
|
dbus_message_iter_init_append(reply, &args);
|
|
|
|
if (dbus_message_iter_append_basic(&args, DBUS_TYPE_BOOLEAN, &status) ==
|
|
0) {
|
|
mslog(s, NULL, LOG_ERR, "error appending to dbus reply");
|
|
goto error;
|
|
}
|
|
|
|
if (!dbus_connection_send(ctx->conn, reply, NULL)) {
|
|
mslog(s, NULL, LOG_ERR, "error sending dbus reply");
|
|
goto error;
|
|
}
|
|
|
|
error:
|
|
dbus_message_unref(reply);
|
|
|
|
return;
|
|
}
|
|
|
|
#define XML_HEAD \
|
|
"<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\"\n" \
|
|
"\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n" \
|
|
"<node name=\"/org/infradead/ocserv\">\n" \
|
|
"<interface name=\"org.infradead.ocserv\">\n"
|
|
|
|
#define XML_FOOT \
|
|
"</interface>" \
|
|
"</node>\n"
|
|
|
|
static void method_introspect(main_server_st * s, struct dbus_ctx *ctx,
|
|
DBusMessage * msg)
|
|
{
|
|
DBusMessage *reply = NULL;
|
|
const char *xml;
|
|
str_st buf;
|
|
int ret;
|
|
unsigned i;
|
|
|
|
mslog(s, NULL, LOG_DEBUG, "ctl: introspect");
|
|
|
|
str_init(&buf, ctx);
|
|
|
|
ret = str_append_data(&buf, XML_HEAD, sizeof(XML_HEAD) - 1);
|
|
if (ret < 0) {
|
|
mslog(s, NULL, LOG_ERR, "error generating dbus reply");
|
|
goto error;
|
|
}
|
|
|
|
for (i = 0; methods[i].name != NULL; i++) {
|
|
ret =
|
|
str_append_data(&buf, methods[i].desc,
|
|
methods[i].desc_size);
|
|
if (ret < 0) {
|
|
mslog(s, NULL, LOG_ERR, "error generating dbus reply");
|
|
goto error;
|
|
}
|
|
}
|
|
|
|
ret = str_append_data(&buf, XML_FOOT, sizeof(XML_FOOT) - 1);
|
|
if (ret < 0) {
|
|
mslog(s, NULL, LOG_ERR, "error generating dbus reply");
|
|
goto error;
|
|
}
|
|
|
|
/* no arguments needed */
|
|
reply = dbus_message_new_method_return(msg);
|
|
if (reply == NULL) {
|
|
mslog(s, NULL, LOG_ERR, "error generating dbus reply");
|
|
goto error;
|
|
}
|
|
|
|
xml = (char *)buf.data;
|
|
if (dbus_message_append_args
|
|
(reply, DBUS_TYPE_STRING, &xml, DBUS_TYPE_INVALID) == 0) {
|
|
mslog(s, NULL, LOG_ERR, "error in introspect to dbus reply");
|
|
goto error;
|
|
}
|
|
|
|
if (!dbus_connection_send(ctx->conn, reply, NULL)) {
|
|
mslog(s, NULL, LOG_ERR, "error sending dbus reply");
|
|
goto error;
|
|
}
|
|
|
|
error:
|
|
str_clear(&buf);
|
|
if (reply)
|
|
dbus_message_unref(reply);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
static void ctl_handle_commands(main_server_st * s, struct ctl_handler_st *ctl)
|
|
{
|
|
struct dbus_ctx *ctx = s->ctl_ctx;
|
|
DBusConnection *conn;
|
|
DBusMessage *msg;
|
|
int ret;
|
|
unsigned flags, i;
|
|
|
|
if (s->config->use_dbus == 0 || ctx == NULL) {
|
|
return;
|
|
}
|
|
|
|
conn = ctx->conn;
|
|
|
|
if (ctl->type == CTL_READ)
|
|
flags = DBUS_WATCH_READABLE;
|
|
else
|
|
flags = DBUS_WATCH_WRITABLE;
|
|
|
|
dbus_connection_ref(conn);
|
|
ret = dbus_watch_handle(ctl->watch, flags);
|
|
dbus_connection_unref(conn);
|
|
|
|
if (ret == 0) {
|
|
mslog(s, NULL, LOG_ERR, "error handling watch");
|
|
return;
|
|
}
|
|
|
|
do {
|
|
if (dbus_connection_read_write(conn, 0) == 0) {
|
|
mslog(s, NULL, LOG_ERR,
|
|
"error handling dbus_connection_read_write");
|
|
return;
|
|
}
|
|
|
|
msg = dbus_connection_pop_message(conn);
|
|
if (msg == NULL)
|
|
return;
|
|
|
|
for (i = 0;; i++) {
|
|
if (methods[i].name == NULL) {
|
|
mslog(s, NULL, LOG_INFO,
|
|
"unknown D-BUS message: %s.%s: %s",
|
|
dbus_message_get_interface(msg),
|
|
dbus_message_get_member(msg),
|
|
dbus_message_get_path(msg));
|
|
break;
|
|
}
|
|
if (dbus_message_is_method_call
|
|
(msg, methods[i].iface, methods[i].name)) {
|
|
methods[i].func(s, ctx, msg);
|
|
break;
|
|
}
|
|
}
|
|
|
|
dbus_message_unref(msg);
|
|
} while (msg != NULL);
|
|
}
|
|
|
|
int ctl_handler_set_fds(main_server_st * s, fd_set * rd_set, fd_set * wr_set)
|
|
{
|
|
struct ctl_handler_st *ctl_tmp = NULL;
|
|
struct dbus_ctx *ctx = s->ctl_ctx;
|
|
int n = -1;
|
|
|
|
if (ctx == NULL)
|
|
return -1;
|
|
|
|
list_for_each(&ctx->ctl_list.head, ctl_tmp, list) {
|
|
if (ctl_tmp->enabled) {
|
|
if (ctl_tmp->type == CTL_READ)
|
|
FD_SET(ctl_tmp->fd, rd_set);
|
|
else
|
|
FD_SET(ctl_tmp->fd, wr_set);
|
|
n = MAX(n, ctl_tmp->fd);
|
|
}
|
|
}
|
|
|
|
return n;
|
|
}
|
|
|
|
void ctl_handler_run_pending(main_server_st* s, fd_set *rd_set, fd_set *wr_set)
|
|
{
|
|
struct ctl_handler_st *ctl_tmp = NULL, *ctl_pos;
|
|
struct dbus_ctx *ctx = s->ctl_ctx;
|
|
|
|
if (ctx == NULL)
|
|
return;
|
|
|
|
list_for_each_safe(&ctx->ctl_list.head, ctl_tmp, ctl_pos, list) {
|
|
if (ctl_tmp->enabled == 0)
|
|
continue;
|
|
if (ctl_tmp->type == CTL_READ) {
|
|
if (FD_ISSET(ctl_tmp->fd, rd_set))
|
|
ctl_handle_commands(s, ctl_tmp);
|
|
} else {
|
|
if (FD_ISSET(ctl_tmp->fd, wr_set))
|
|
ctl_handle_commands(s, ctl_tmp);
|
|
}
|
|
}
|
|
}
|
|
|
|
void ctl_handler_deinit(main_server_st * s)
|
|
{
|
|
struct dbus_ctx *ctx = s->ctl_ctx;
|
|
|
|
if (s->config->use_dbus != 0 && ctx != NULL && ctx->conn != NULL) {
|
|
mslog(s, NULL, LOG_DEBUG, "closing DBUS connection");
|
|
dbus_connection_close(ctx->conn);
|
|
dbus_bus_release_name(ctx->conn, OCSERV_DBUS_NAME, NULL);
|
|
dbus_connection_unref(ctx->conn);
|
|
}
|
|
}
|
|
|
|
/* Initializes unix socket and stores the fd.
|
|
*/
|
|
int ctl_handler_init(main_server_st * s)
|
|
{
|
|
int ret;
|
|
DBusError err;
|
|
DBusConnection *conn;
|
|
struct dbus_ctx *ctx;
|
|
|
|
if (s->config->use_dbus == 0)
|
|
return 0;
|
|
|
|
ctx = talloc_zero(s, struct dbus_ctx);
|
|
if (ctx == NULL)
|
|
return ERR_CTL;
|
|
|
|
list_head_init(&ctx->ctl_list.head);
|
|
dbus_error_init(&err);
|
|
|
|
conn = dbus_bus_get_private(DBUS_BUS_SYSTEM, &err);
|
|
if (conn == NULL) {
|
|
mslog(s, NULL, LOG_DEBUG, "error initializing DBUS connection");
|
|
goto error;
|
|
}
|
|
|
|
ret = dbus_bus_request_name(conn, OCSERV_DBUS_NAME,
|
|
DBUS_NAME_FLAG_REPLACE_EXISTING, &err);
|
|
if (ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
|
|
mslog(s, NULL, LOG_DEBUG, "error requesting DBUS name");
|
|
goto error;
|
|
}
|
|
|
|
ctx->conn = conn;
|
|
s->ctl_ctx = ctx;
|
|
|
|
if (!dbus_connection_set_watch_functions(conn,
|
|
add_watch, remove_watch,
|
|
toggle_watch, ctx, NULL)) {
|
|
mslog(s, NULL, LOG_DEBUG, "error setting DBUS watchers");
|
|
goto error;
|
|
}
|
|
mslog(s, NULL, LOG_DEBUG, "initialized DBUS connection");
|
|
|
|
|
|
return 0;
|
|
|
|
error:
|
|
if (dbus_error_is_set(&err)) {
|
|
fprintf(stderr, "DBUS connection error (%s)", err.message);
|
|
dbus_error_free(&err);
|
|
}
|
|
ctl_handler_deinit(s);
|
|
|
|
return ERR_CTL;
|
|
}
|
|
|