|
Packit |
c22fc9 |
/*
|
|
Packit |
c22fc9 |
* Soft: Keepalived is a failover program for the LVS project
|
|
Packit |
c22fc9 |
* <www.linuxvirtualserver.org>. It monitor & manipulate
|
|
Packit |
c22fc9 |
* a loadbalanced server pool using multi-layer checks.
|
|
Packit |
c22fc9 |
*
|
|
Packit |
c22fc9 |
* Part: DBus server thread for VRRP
|
|
Packit |
c22fc9 |
*
|
|
Packit |
c22fc9 |
* Author: Alexandre Cassen, <acassen@linux-vs.org>
|
|
Packit |
c22fc9 |
*
|
|
Packit |
c22fc9 |
* This program is distributed in the hope that it will be useful,
|
|
Packit |
c22fc9 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
c22fc9 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
Packit |
c22fc9 |
* See the GNU General Public License for more details.
|
|
Packit |
c22fc9 |
*
|
|
Packit |
c22fc9 |
* This program is free software; you can redistribute it and/or
|
|
Packit |
c22fc9 |
* modify it under the terms of the GNU General Public License
|
|
Packit |
c22fc9 |
* as published by the Free Software Foundation; either version
|
|
Packit |
c22fc9 |
* 2 of the License, or (at your option) any later version.
|
|
Packit |
c22fc9 |
*
|
|
Packit |
c22fc9 |
* Copyright (C) 2016-2017 Alexandre Cassen, <acassen@gmail.com>
|
|
Packit |
c22fc9 |
*/
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
/* See https://git.gnome.org/browse/glib/tree/gio/tests/fdbus-example-server.c
|
|
Packit |
c22fc9 |
* and https://developer.gnome.org/gio/stable/GDBusConnection.html#gdbus-server
|
|
Packit |
c22fc9 |
* for examples of coding.
|
|
Packit |
c22fc9 |
*
|
|
Packit |
c22fc9 |
* Create a general /org/keepalived/Vrrp1/Vrrp DBus
|
|
Packit |
c22fc9 |
* object and a /org/keepalived/Vrrp1/Instance/#interface#/#group# object for
|
|
Packit |
c22fc9 |
* each VRRP instance.
|
|
Packit |
c22fc9 |
* Interface org.keepalived.Vrrp1.Vrrp implements methods PrintData,
|
|
Packit |
c22fc9 |
* PrintStats and signal VrrpStopped.
|
|
Packit |
c22fc9 |
* Interface com.keepalived.Vrrp1.Instance implements method SendGarp
|
|
Packit |
c22fc9 |
* (sends a single Gratuitous ARP from the given Instance),
|
|
Packit |
c22fc9 |
* signal VrrpStatusChange, and properties Name and State (retrievable
|
|
Packit |
c22fc9 |
* through calls to org.freedesktop.DBus.Properties.Get)
|
|
Packit |
c22fc9 |
*
|
|
Packit |
c22fc9 |
* Interface files need to be installed in /usr/share/dbus-1/interfaces/
|
|
Packit |
c22fc9 |
* A policy file, which determines who has access to the service, is
|
|
Packit |
c22fc9 |
* installed in /etc/dbus-1/system.d/. Sources for the policy and interface
|
|
Packit |
c22fc9 |
* files are in keepalived/dbus.
|
|
Packit |
c22fc9 |
*
|
|
Packit |
c22fc9 |
* To test the DBus service run a command like: dbus-send --system --dest=org.keepalived.Vrrp1 --print-reply object interface.method type:argument
|
|
Packit |
c22fc9 |
* e.g.
|
|
Packit |
c22fc9 |
* dbus-send --system --dest=org.keepalived.Vrrp1 --print-reply /org/keepalived/Vrrp1/Vrrp org.keepalived.Vrrp1.Vrrp.PrintData
|
|
Packit |
c22fc9 |
* or
|
|
Packit |
c22fc9 |
* dbus-send --system --dest=org.keepalived.Vrrp1 --print-reply /org/keepalived/Vrrp1/Instance/eth0/1/IPv4 org.freedesktop.DBus.Properties.Get string:'org.keepalived.Vrrp1.Instance' string:'State'
|
|
Packit |
c22fc9 |
*
|
|
Packit |
c22fc9 |
* To monitor signals, run:
|
|
Packit |
c22fc9 |
* dbus-monitor --system type='signal'
|
|
Packit |
c22fc9 |
*
|
|
Packit |
c22fc9 |
* d-feet is a useful program for interfacing with DBus
|
|
Packit |
c22fc9 |
*/
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
#include "config.h"
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
#include <errno.h>
|
|
Packit |
c22fc9 |
#include <pthread.h>
|
|
Packit |
c22fc9 |
#include <semaphore.h>
|
|
Packit |
c22fc9 |
#include <gio/gio.h>
|
|
Packit |
c22fc9 |
#include <ctype.h>
|
|
Packit |
c22fc9 |
#include <fcntl.h>
|
|
Packit |
c22fc9 |
#include <sys/types.h>
|
|
Packit |
c22fc9 |
#include <stdlib.h>
|
|
Packit |
c22fc9 |
#include <stdint.h>
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
#include "vrrp_dbus.h"
|
|
Packit |
c22fc9 |
#include "vrrp_data.h"
|
|
Packit |
c22fc9 |
#include "vrrp_print.h"
|
|
Packit |
c22fc9 |
#include "global_data.h"
|
|
Packit |
c22fc9 |
#include "main.h"
|
|
Packit |
c22fc9 |
#include "logger.h"
|
|
Packit |
c22fc9 |
#include "utils.h"
|
|
Packit |
c22fc9 |
#ifdef THREAD_DUMP
|
|
Packit |
c22fc9 |
#include "scheduler.h"
|
|
Packit |
c22fc9 |
#endif
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
typedef enum dbus_action {
|
|
Packit |
c22fc9 |
DBUS_ACTION_NONE,
|
|
Packit |
c22fc9 |
DBUS_PRINT_DATA,
|
|
Packit |
c22fc9 |
DBUS_PRINT_STATS,
|
|
Packit Service |
dfccb1 |
DBUS_PRINT_STATS_CLEAR,
|
|
Packit |
c22fc9 |
DBUS_RELOAD,
|
|
Packit |
c22fc9 |
#ifdef _WITH_DBUS_CREATE_INSTANCE_
|
|
Packit |
c22fc9 |
DBUS_CREATE_INSTANCE,
|
|
Packit |
c22fc9 |
DBUS_DESTROY_INSTANCE,
|
|
Packit |
c22fc9 |
#endif
|
|
Packit |
c22fc9 |
DBUS_SEND_GARP,
|
|
Packit |
c22fc9 |
DBUS_GET_NAME,
|
|
Packit |
c22fc9 |
DBUS_GET_STATUS,
|
|
Packit |
c22fc9 |
} dbus_action_t;
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
typedef enum dbus_error {
|
|
Packit |
c22fc9 |
DBUS_SUCCESS,
|
|
Packit |
c22fc9 |
DBUS_INTERFACE_NOT_FOUND,
|
|
Packit |
c22fc9 |
DBUS_OBJECT_ALREADY_EXISTS,
|
|
Packit |
c22fc9 |
DBUS_INTERFACE_TOO_LONG,
|
|
Packit |
c22fc9 |
DBUS_INSTANCE_NOT_FOUND,
|
|
Packit |
c22fc9 |
} dbus_error_t;
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
typedef struct dbus_queue_ent {
|
|
Packit |
c22fc9 |
dbus_action_t action;
|
|
Packit |
c22fc9 |
dbus_error_t reply;
|
|
Packit |
c22fc9 |
char *ifname;
|
|
Packit |
c22fc9 |
uint8_t vrid;
|
|
Packit |
c22fc9 |
uint8_t family;
|
|
Packit |
c22fc9 |
GVariant *args;
|
|
Packit |
c22fc9 |
} dbus_queue_ent_t;
|
|
Packit |
c22fc9 |
|
|
Packit Service |
dfccb1 |
#define DBUS_SERVICE_NAME "org.keepalived.Vrrp1"
|
|
Packit Service |
dfccb1 |
#define DBUS_VRRP_INTERFACE "org.keepalived.Vrrp1.Vrrp"
|
|
Packit Service |
dfccb1 |
#define DBUS_VRRP_OBJECT_ROOT "/org/keepalived/Vrrp1"
|
|
Packit Service |
dfccb1 |
#define DBUS_VRRP_INSTANCE_PATH_DEFAULT_LENGTH 8
|
|
Packit Service |
dfccb1 |
#define DBUS_VRRP_INSTANCE_INTERFACE "org.keepalived.Vrrp1.Instance"
|
|
Packit Service |
dfccb1 |
#define DBUS_VRRP_INTERFACE_FILE_PATH "/usr/share/dbus-1/interfaces/org.keepalived.Vrrp1.Vrrp.xml"
|
|
Packit Service |
dfccb1 |
#define DBUS_VRRP_INSTANCE_INTERFACE_FILE_PATH "/usr/share/dbus-1/interfaces/org.keepalived.Vrrp1.Instance.xml"
|
|
Packit Service |
dfccb1 |
|
|
Packit Service |
dfccb1 |
static bool dbus_running;
|
|
Packit Service |
dfccb1 |
|
|
Packit |
c22fc9 |
/* Global file variables */
|
|
Packit Service |
dfccb1 |
static const char * const no_interface = "none";
|
|
Packit |
c22fc9 |
static GDBusNodeInfo *vrrp_introspection_data = NULL;
|
|
Packit |
c22fc9 |
static GDBusNodeInfo *vrrp_instance_introspection_data = NULL;
|
|
Packit |
c22fc9 |
static GDBusConnection *global_connection;
|
|
Packit |
c22fc9 |
static GHashTable *objects;
|
|
Packit |
c22fc9 |
static GMainLoop *loop;
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
/* Data passing between main vrrp thread and dbus thread */
|
|
Packit |
c22fc9 |
dbus_queue_ent_t *ent_ptr;
|
|
Packit Service |
dfccb1 |
static int dbus_in_pipe[2] = {-1, -1};
|
|
Packit Service |
dfccb1 |
static int dbus_out_pipe[2] = {-1, -1};
|
|
Packit |
c22fc9 |
static sem_t thread_end;
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
/* The only characters that are valid in a dbus path are A-Z, a-z, 0-9, _ */
|
|
Packit |
c22fc9 |
static char *
|
|
Packit |
c22fc9 |
set_valid_path(char *valid_path, const char *path)
|
|
Packit |
c22fc9 |
{
|
|
Packit |
c22fc9 |
const char *str_in;
|
|
Packit |
c22fc9 |
char *str_out;
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
for (str_in = path, str_out = valid_path; *str_in; str_in++, str_out++) {
|
|
Packit |
c22fc9 |
if (!isalnum(*str_in))
|
|
Packit |
c22fc9 |
*str_out = '_';
|
|
Packit |
c22fc9 |
else
|
|
Packit |
c22fc9 |
*str_out = *str_in;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
*str_out = '\0';
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
return valid_path;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit Service |
dfccb1 |
static bool __attribute__ ((pure))
|
|
Packit |
c22fc9 |
valid_path_cmp(const char *path, const char *valid_path)
|
|
Packit |
c22fc9 |
{
|
|
Packit |
c22fc9 |
for ( ; *path && *valid_path; path++, valid_path++) {
|
|
Packit |
c22fc9 |
if (!isalnum(*path)) {
|
|
Packit |
c22fc9 |
if (*valid_path != '_')
|
|
Packit |
c22fc9 |
return true;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
else if (*path != *valid_path)
|
|
Packit |
c22fc9 |
return true;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
return *path != *valid_path;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
static const char *
|
|
Packit |
c22fc9 |
family_str(int family)
|
|
Packit |
c22fc9 |
{
|
|
Packit |
c22fc9 |
if (family == AF_INET)
|
|
Packit |
c22fc9 |
return "IPv4";
|
|
Packit |
c22fc9 |
if (family == AF_INET6)
|
|
Packit |
c22fc9 |
return "IPv6";
|
|
Packit |
c22fc9 |
return "None";
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
static const char *
|
|
Packit |
c22fc9 |
state_str(int state)
|
|
Packit |
c22fc9 |
{
|
|
Packit |
c22fc9 |
switch (state) {
|
|
Packit |
c22fc9 |
case VRRP_STATE_INIT:
|
|
Packit |
c22fc9 |
return "Init";
|
|
Packit |
c22fc9 |
case VRRP_STATE_BACK:
|
|
Packit |
c22fc9 |
return "Backup";
|
|
Packit |
c22fc9 |
case VRRP_STATE_MAST:
|
|
Packit |
c22fc9 |
return "Master";
|
|
Packit |
c22fc9 |
case VRRP_STATE_FAULT:
|
|
Packit |
c22fc9 |
return "Fault";
|
|
Packit Service |
dfccb1 |
case VRRP_STATE_STOP:
|
|
Packit Service |
dfccb1 |
return "Stop";
|
|
Packit Service |
dfccb1 |
case VRRP_STATE_DELETED:
|
|
Packit Service |
dfccb1 |
return "Deleted";
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
return "Unknown";
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit Service |
dfccb1 |
static vrrp_t * __attribute__ ((pure))
|
|
Packit |
c22fc9 |
get_vrrp_instance(const char *ifname, int vrid, int family)
|
|
Packit |
c22fc9 |
{
|
|
Packit |
c22fc9 |
vrrp_t *vrrp;
|
|
Packit |
c22fc9 |
|
|
Packit Service |
dfccb1 |
list_for_each_entry(vrrp, &vrrp_data->vrrp, e_list) {
|
|
Packit Service |
dfccb1 |
if (vrrp->ifp &&
|
|
Packit Service |
dfccb1 |
vrrp->vrid == vrid &&
|
|
Packit |
c22fc9 |
vrrp->family == family &&
|
|
Packit Service |
dfccb1 |
!valid_path_cmp(VRRP_CONFIGURED_IFP(vrrp)->ifname, ifname))
|
|
Packit Service |
dfccb1 |
return vrrp;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
return NULL;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
static gboolean
|
|
Packit Service |
dfccb1 |
unregister_object(const void * const key, gpointer value, __attribute__((unused)) gpointer user_data)
|
|
Packit |
c22fc9 |
{
|
|
Packit |
c22fc9 |
if (g_hash_table_remove(objects, key))
|
|
Packit |
c22fc9 |
return g_dbus_connection_unregister_object(global_connection, GPOINTER_TO_UINT(value));
|
|
Packit |
c22fc9 |
return false;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit Service |
dfccb1 |
static gboolean
|
|
Packit Service |
dfccb1 |
remove_object(__attribute__((unused)) gpointer key, gpointer value, __attribute__((unused)) gpointer user_data)
|
|
Packit Service |
dfccb1 |
{
|
|
Packit Service |
dfccb1 |
return g_dbus_connection_unregister_object(global_connection, GPOINTER_TO_UINT(value));
|
|
Packit Service |
dfccb1 |
}
|
|
Packit Service |
dfccb1 |
|
|
Packit Service |
dfccb1 |
static gchar * __attribute__ ((malloc))
|
|
Packit |
c22fc9 |
dbus_object_create_path_vrrp(void)
|
|
Packit |
c22fc9 |
{
|
|
Packit |
c22fc9 |
return g_strconcat(DBUS_VRRP_OBJECT_ROOT,
|
|
Packit |
c22fc9 |
#if HAVE_DECL_CLONE_NEWNET
|
|
Packit |
c22fc9 |
global_data->network_namespace ? "/" : "", global_data->network_namespace ? global_data->network_namespace : "",
|
|
Packit |
c22fc9 |
#endif
|
|
Packit |
c22fc9 |
global_data->instance_name ? "/" : "", global_data->instance_name ? global_data->instance_name : "",
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
"/Vrrp", NULL);
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit Service |
dfccb1 |
static gchar * __attribute__ ((malloc))
|
|
Packit |
c22fc9 |
dbus_object_create_path_instance(const gchar *interface, int vrid, sa_family_t family)
|
|
Packit |
c22fc9 |
{
|
|
Packit |
c22fc9 |
gchar *object_path;
|
|
Packit |
c22fc9 |
char standardized_name[sizeof ((vrrp_t*)NULL)->ifp->ifname];
|
|
Packit |
c22fc9 |
gchar *vrid_str = g_strdup_printf("%d", vrid);
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
set_valid_path(standardized_name, interface);
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
object_path = g_strconcat(DBUS_VRRP_OBJECT_ROOT,
|
|
Packit |
c22fc9 |
#if HAVE_DECL_CLONE_NEWNET
|
|
Packit |
c22fc9 |
global_data->network_namespace ? "/" : "", global_data->network_namespace ? global_data->network_namespace : "",
|
|
Packit |
c22fc9 |
#endif
|
|
Packit |
c22fc9 |
global_data->instance_name ? "/" : "", global_data->instance_name ? global_data->instance_name : "",
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
"/Instance/",
|
|
Packit |
c22fc9 |
standardized_name, "/", vrid_str,
|
|
Packit |
c22fc9 |
"/", family_str(family),
|
|
Packit |
c22fc9 |
NULL);
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
g_free(vrid_str);
|
|
Packit |
c22fc9 |
return object_path;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
static dbus_queue_ent_t *
|
|
Packit |
c22fc9 |
process_method_call(dbus_queue_ent_t *ent)
|
|
Packit |
c22fc9 |
{
|
|
Packit |
c22fc9 |
ssize_t ret;
|
|
Packit Service |
dfccb1 |
char buf = 0;
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
if (!ent)
|
|
Packit |
c22fc9 |
return NULL;
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
/* Tell the main thread that a queue entry is waiting. Any data works */
|
|
Packit |
c22fc9 |
ent_ptr = ent;
|
|
Packit Service |
dfccb1 |
if (write(dbus_in_pipe[1], &buf, 1) != 1)
|
|
Packit |
c22fc9 |
log_message(LOG_INFO, "Write from DBus thread to main thread failed");
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
/* Wait for a response */
|
|
Packit Service |
dfccb1 |
while ((ret = read(dbus_out_pipe[0], &buf, 1)) == -1 && check_EINTR(errno))
|
|
Packit |
c22fc9 |
log_message(LOG_INFO, "dbus_out_pipe read returned EINTR");
|
|
Packit |
c22fc9 |
if (ret == -1)
|
|
Packit |
c22fc9 |
log_message(LOG_INFO, "DBus response read error - errno = %d", errno);
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
#ifdef DBUS_DEBUG
|
|
Packit |
c22fc9 |
if (ent->reply != DBUS_SUCCESS) {
|
|
Packit |
c22fc9 |
char *iname;
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
if (ent->reply == DBUS_INTERFACE_NOT_FOUND)
|
|
Packit |
c22fc9 |
log_message(LOG_INFO, "Unable to find DBus requested instance %s/%d/%s", ent->ifname, ent->vrid, family_str(ent->family));
|
|
Packit |
c22fc9 |
else if (ent->reply == DBUS_OBJECT_ALREADY_EXISTS)
|
|
Packit |
c22fc9 |
log_message(LOG_INFO, "Unable to create DBus requested object with instance %s/%d/%s", ent->ifname, ent->vrid, family_str(ent->family));
|
|
Packit |
c22fc9 |
else if (ent->reply == DBUS_INSTANCE_NOT_FOUND) {
|
|
Packit |
c22fc9 |
g_variant_get(ent->args, "(s)", &iname);
|
|
Packit |
c22fc9 |
log_message(LOG_INFO, "Unable to find DBus requested instance %s", iname);
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
else
|
|
Packit |
c22fc9 |
log_message(LOG_INFO, "Unknown DBus reply %d", ent->reply);
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
#endif
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
return ent;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
static void
|
|
Packit |
c22fc9 |
get_interface_ids(const gchar *object_path, gchar *interface, uint8_t *vrid, uint8_t *family)
|
|
Packit |
c22fc9 |
{
|
|
Packit |
c22fc9 |
int path_length = DBUS_VRRP_INSTANCE_PATH_DEFAULT_LENGTH;
|
|
Packit |
c22fc9 |
gchar **dirs;
|
|
Packit |
c22fc9 |
char *endptr;
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
#if HAVE_DECL_CLONE_NEWNET
|
|
Packit |
c22fc9 |
if(global_data->network_namespace)
|
|
Packit |
c22fc9 |
path_length++;
|
|
Packit |
c22fc9 |
#endif
|
|
Packit |
c22fc9 |
if(global_data->instance_name)
|
|
Packit |
c22fc9 |
path_length++;
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
/* object_path will have interface, vrid and family as
|
|
Packit |
c22fc9 |
* the third to last, second to last and last levels */
|
|
Packit |
c22fc9 |
dirs = g_strsplit(object_path, "/", path_length);
|
|
Packit |
c22fc9 |
strcpy(interface, dirs[path_length-3]);
|
|
Packit |
c22fc9 |
*vrid = (uint8_t)strtoul(dirs[path_length-2], &endptr, 10);
|
|
Packit |
c22fc9 |
if (*endptr)
|
|
Packit |
c22fc9 |
log_message(LOG_INFO, "Dbus unexpected characters '%s' at end of number '%s'", endptr, dirs[path_length-2]);
|
|
Packit |
c22fc9 |
*family = !g_strcmp0(dirs[path_length-1], "IPv4") ? AF_INET : !g_strcmp0(dirs[path_length-1], "IPv6") ? AF_INET6 : AF_UNSPEC;
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
/* We are finished with all the object_path strings now */
|
|
Packit |
c22fc9 |
g_strfreev(dirs);
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
/* handles reply to org.freedesktop.DBus.Properties.Get method on any object*/
|
|
Packit |
c22fc9 |
static GVariant *
|
|
Packit |
c22fc9 |
handle_get_property(__attribute__((unused)) GDBusConnection *connection,
|
|
Packit |
c22fc9 |
__attribute__((unused)) const gchar *sender,
|
|
Packit |
c22fc9 |
const gchar *object_path,
|
|
Packit |
c22fc9 |
const gchar *interface_name,
|
|
Packit |
c22fc9 |
const gchar *property_name,
|
|
Packit |
c22fc9 |
GError **error,
|
|
Packit |
c22fc9 |
__attribute__((unused)) gpointer user_data)
|
|
Packit |
c22fc9 |
{
|
|
Packit |
c22fc9 |
GVariant *ret = NULL;
|
|
Packit |
c22fc9 |
dbus_queue_ent_t ent;
|
|
Packit |
c22fc9 |
char ifname_str[sizeof ((vrrp_t*)NULL)->ifp->ifname];
|
|
Packit |
c22fc9 |
int action;
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
if (g_strcmp0(interface_name, DBUS_VRRP_INSTANCE_INTERFACE)) {
|
|
Packit |
c22fc9 |
log_message(LOG_INFO, "Interface %s has not been implemented yet", interface_name);
|
|
Packit |
c22fc9 |
return NULL;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
if (!g_strcmp0(property_name, "Name"))
|
|
Packit |
c22fc9 |
action = DBUS_GET_NAME;
|
|
Packit |
c22fc9 |
else if (!g_strcmp0(property_name, "State"))
|
|
Packit |
c22fc9 |
action = DBUS_GET_STATUS;
|
|
Packit |
c22fc9 |
else {
|
|
Packit |
c22fc9 |
log_message(LOG_INFO, "Property %s does not exist", property_name);
|
|
Packit |
c22fc9 |
return NULL;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
get_interface_ids(object_path, ifname_str, &ent.vrid, &ent.family);
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
ent.action = action;
|
|
Packit |
c22fc9 |
ent.ifname = ifname_str;
|
|
Packit |
c22fc9 |
ent.args = NULL;
|
|
Packit |
c22fc9 |
process_method_call(&ent;;
|
|
Packit |
c22fc9 |
if (ent.reply == DBUS_SUCCESS)
|
|
Packit |
c22fc9 |
ret = ent.args;
|
|
Packit |
c22fc9 |
else
|
|
Packit |
c22fc9 |
g_set_error(error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "Instance '%s/%d/%s' not found", ifname_str, ent.vrid, family_str(ent.family));
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
return ret;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
/* handles method_calls on any object */
|
|
Packit |
c22fc9 |
static void
|
|
Packit |
c22fc9 |
handle_method_call(__attribute__((unused)) GDBusConnection *connection,
|
|
Packit |
c22fc9 |
__attribute__((unused)) const gchar *sender,
|
|
Packit |
c22fc9 |
const gchar *object_path,
|
|
Packit |
c22fc9 |
const gchar *interface_name,
|
|
Packit |
c22fc9 |
const gchar *method_name,
|
|
Packit |
c22fc9 |
#ifndef _WITH_DBUS_CREATE_INSTANCE_
|
|
Packit |
c22fc9 |
__attribute__((unused))
|
|
Packit |
c22fc9 |
#endif
|
|
Packit |
c22fc9 |
GVariant *parameters,
|
|
Packit |
c22fc9 |
GDBusMethodInvocation *invocation,
|
|
Packit |
c22fc9 |
__attribute__((unused)) gpointer user_data)
|
|
Packit |
c22fc9 |
{
|
|
Packit |
c22fc9 |
#ifdef _WITH_DBUS_CREATE_INSTANCE_
|
|
Packit |
c22fc9 |
char *iname;
|
|
Packit |
c22fc9 |
char *ifname;
|
|
Packit |
c22fc9 |
size_t len;
|
|
Packit |
c22fc9 |
unsigned family;
|
|
Packit |
c22fc9 |
#endif
|
|
Packit |
c22fc9 |
dbus_queue_ent_t ent;
|
|
Packit |
c22fc9 |
char ifname_str[sizeof ((vrrp_t*)NULL)->ifp->ifname];
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
if (!g_strcmp0(interface_name, DBUS_VRRP_INTERFACE)) {
|
|
Packit |
c22fc9 |
if (!g_strcmp0(method_name, "PrintData")) {
|
|
Packit |
c22fc9 |
ent.action = DBUS_PRINT_DATA;
|
|
Packit |
c22fc9 |
process_method_call(&ent;;
|
|
Packit |
c22fc9 |
g_dbus_method_invocation_return_value(invocation, NULL);
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
else if (g_strcmp0(method_name, "PrintStats") == 0) {
|
|
Packit |
c22fc9 |
ent.action = DBUS_PRINT_STATS;
|
|
Packit |
c22fc9 |
process_method_call(&ent;;
|
|
Packit |
c22fc9 |
g_dbus_method_invocation_return_value(invocation, NULL);
|
|
Packit |
c22fc9 |
}
|
|
Packit Service |
dfccb1 |
else if (g_strcmp0(method_name, "PrintStatsClear") == 0) {
|
|
Packit Service |
dfccb1 |
ent.action = DBUS_PRINT_STATS_CLEAR;
|
|
Packit Service |
dfccb1 |
process_method_call(&ent;;
|
|
Packit Service |
dfccb1 |
g_dbus_method_invocation_return_value(invocation, NULL);
|
|
Packit Service |
dfccb1 |
}
|
|
Packit |
c22fc9 |
else if (g_strcmp0(method_name, "ReloadConfig") == 0) {
|
|
Packit |
c22fc9 |
g_dbus_method_invocation_return_value(invocation, NULL);
|
|
Packit |
c22fc9 |
kill(getppid(), SIGHUP);
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
#ifdef _WITH_DBUS_CREATE_INSTANCE_
|
|
Packit |
c22fc9 |
else if (g_strcmp0(method_name, "CreateInstance") == 0) {
|
|
Packit |
c22fc9 |
g_variant_get(parameters, "(ssuu)", &iname, &ifname, &ent.vrid, &family);
|
|
Packit |
c22fc9 |
len = strlen(ifname);
|
|
Packit |
c22fc9 |
if (len == 0 || len >= IFNAMSIZ) {
|
|
Packit |
c22fc9 |
log_message(LOG_INFO, "Interface name '%s' too long for CreateInstance", ifname);
|
|
Packit |
c22fc9 |
g_dbus_method_invocation_return_error(invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "Interface name empty or too long");
|
|
Packit |
c22fc9 |
return;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
ent.action = DBUS_CREATE_INSTANCE;
|
|
Packit |
c22fc9 |
ent.ifname = ifname;
|
|
Packit |
c22fc9 |
ent.family = family == 4 ? AF_INET : family == 6 ? AF_INET6 : AF_UNSPEC;
|
|
Packit |
c22fc9 |
ent.args = g_variant_new("(s)", iname);
|
|
Packit |
c22fc9 |
process_method_call(&ent;;
|
|
Packit |
c22fc9 |
g_variant_unref(ent.args);
|
|
Packit |
c22fc9 |
g_dbus_method_invocation_return_value(invocation, NULL);
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
else if (g_strcmp0(method_name, "DestroyInstance") == 0) {
|
|
Packit |
c22fc9 |
// TODO - this should be on the instance
|
|
Packit |
c22fc9 |
ent.action = DBUS_DESTROY_INSTANCE;
|
|
Packit |
c22fc9 |
ent.args = parameters;
|
|
Packit |
c22fc9 |
process_method_call(&ent;;
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
if (ent.reply == DBUS_INSTANCE_NOT_FOUND) {
|
|
Packit |
c22fc9 |
g_variant_get(parameters, "(s)", &iname);
|
|
Packit |
c22fc9 |
g_dbus_method_invocation_return_error(invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "Instance '%s' not found", iname);
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
else
|
|
Packit |
c22fc9 |
g_dbus_method_invocation_return_value(invocation, NULL);
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
#endif
|
|
Packit |
c22fc9 |
else {
|
|
Packit |
c22fc9 |
log_message(LOG_INFO, "Method %s has not been implemented yet", method_name);
|
|
Packit |
c22fc9 |
g_dbus_method_invocation_return_error(invocation, G_DBUS_ERROR, G_DBUS_ERROR_MATCH_RULE_NOT_FOUND, "Method not implemented");
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
return;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
if (!g_strcmp0(interface_name, DBUS_VRRP_INSTANCE_INTERFACE)) {
|
|
Packit |
c22fc9 |
if (!g_strcmp0(method_name, "SendGarp")) {
|
|
Packit |
c22fc9 |
get_interface_ids(object_path, ifname_str, &ent.vrid, &ent.family);
|
|
Packit |
c22fc9 |
ent.action = DBUS_SEND_GARP;
|
|
Packit |
c22fc9 |
ent.ifname = ifname_str;
|
|
Packit |
c22fc9 |
process_method_call(&ent;;
|
|
Packit |
c22fc9 |
if (ent.reply == DBUS_INTERFACE_NOT_FOUND)
|
|
Packit |
c22fc9 |
g_dbus_method_invocation_return_error(invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "Instance '%s/%d/%s' not found", ifname_str, ent.vrid, family_str(ent.family));
|
|
Packit |
c22fc9 |
else
|
|
Packit |
c22fc9 |
g_dbus_method_invocation_return_value(invocation, NULL);
|
|
Packit |
c22fc9 |
} else {
|
|
Packit |
c22fc9 |
log_message(LOG_INFO, "Method %s has not been implemented yet", method_name);
|
|
Packit |
c22fc9 |
g_dbus_method_invocation_return_error(invocation, G_DBUS_ERROR, G_DBUS_ERROR_MATCH_RULE_NOT_FOUND, "Method not implemented");
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
return;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
log_message(LOG_INFO, "Interface %s has not been implemented yet", interface_name);
|
|
Packit |
c22fc9 |
g_dbus_method_invocation_return_error(invocation, G_DBUS_ERROR, G_DBUS_ERROR_MATCH_RULE_NOT_FOUND, "Interface not implemented");
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
static const GDBusInterfaceVTable interface_vtable =
|
|
Packit |
c22fc9 |
{
|
|
Packit |
c22fc9 |
handle_method_call,
|
|
Packit |
c22fc9 |
handle_get_property,
|
|
Packit |
c22fc9 |
NULL, /* handle_set_property is null because we have no writeable property */
|
|
Packit |
c22fc9 |
{}
|
|
Packit |
c22fc9 |
};
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
static int
|
|
Packit Service |
dfccb1 |
dbus_create_object_params(const char *instance_name, const char *interface_name, int vrid, sa_family_t family, bool log_success)
|
|
Packit |
c22fc9 |
{
|
|
Packit |
c22fc9 |
gchar *object_path;
|
|
Packit |
c22fc9 |
GError *local_error = NULL;
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
if (g_hash_table_lookup(objects, instance_name)) {
|
|
Packit |
c22fc9 |
log_message(LOG_INFO, "An object for instance %s already exists", instance_name);
|
|
Packit |
c22fc9 |
return DBUS_OBJECT_ALREADY_EXISTS;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
object_path = dbus_object_create_path_instance(interface_name, vrid, family);
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
guint instance = g_dbus_connection_register_object(global_connection, object_path,
|
|
Packit |
c22fc9 |
vrrp_instance_introspection_data->interfaces[0],
|
|
Packit |
c22fc9 |
&interface_vtable, NULL, NULL, &local_error);
|
|
Packit |
c22fc9 |
if (local_error != NULL) {
|
|
Packit |
c22fc9 |
log_message(LOG_INFO, "Registering DBus object on %s failed: %s",
|
|
Packit |
c22fc9 |
object_path, local_error->message);
|
|
Packit |
c22fc9 |
g_clear_error(&local_error);
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
if (instance) {
|
|
Packit Service |
dfccb1 |
g_hash_table_insert(objects, no_const_char_p(instance_name), GUINT_TO_POINTER(instance));
|
|
Packit |
c22fc9 |
if (log_success)
|
|
Packit |
c22fc9 |
log_message(LOG_INFO, "Added DBus object for instance %s on path %s", instance_name, object_path);
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
g_free(object_path);
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
return DBUS_SUCCESS;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
static void
|
|
Packit |
c22fc9 |
dbus_create_object(vrrp_t *vrrp)
|
|
Packit |
c22fc9 |
{
|
|
Packit Service |
dfccb1 |
dbus_create_object_params(vrrp->iname, vrrp->ifp ? IF_NAME(VRRP_CONFIGURED_IFP(vrrp)) : no_interface, vrrp->vrid, vrrp->family, false);
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
static bool
|
|
Packit |
c22fc9 |
dbus_emit_signal(GDBusConnection *connection,
|
|
Packit |
c22fc9 |
const gchar *object_path,
|
|
Packit |
c22fc9 |
const gchar *interface_name,
|
|
Packit |
c22fc9 |
const gchar *signal_name,
|
|
Packit |
c22fc9 |
GVariant *parameters)
|
|
Packit |
c22fc9 |
{
|
|
Packit |
c22fc9 |
GError *local_error = NULL;
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
g_dbus_connection_emit_signal(connection, NULL, object_path, interface_name, signal_name, parameters,
|
|
Packit |
c22fc9 |
&local_error);
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
if (local_error != NULL) {
|
|
Packit |
c22fc9 |
log_message(LOG_INFO, "Emitting DBus signal %s.%s on %s failed: %s",
|
|
Packit |
c22fc9 |
interface_name, signal_name, object_path, local_error->message);
|
|
Packit |
c22fc9 |
g_clear_error(&local_error);
|
|
Packit |
c22fc9 |
return false;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
return true;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
/* first function to be run when trying to own bus,
|
|
Packit |
c22fc9 |
* exports objects to the bus */
|
|
Packit |
c22fc9 |
static void
|
|
Packit |
c22fc9 |
on_bus_acquired(GDBusConnection *connection,
|
|
Packit |
c22fc9 |
const gchar *name,
|
|
Packit |
c22fc9 |
__attribute__((unused)) gpointer user_data)
|
|
Packit |
c22fc9 |
{
|
|
Packit |
c22fc9 |
global_connection = connection;
|
|
Packit |
c22fc9 |
gchar *path;
|
|
Packit Service |
dfccb1 |
vrrp_t *vrrp;
|
|
Packit |
c22fc9 |
GError *local_error = NULL;
|
|
Packit Service |
dfccb1 |
guint vrrp_guint;
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
log_message(LOG_INFO, "Acquired DBus bus %s", name);
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
/* register VRRP object */
|
|
Packit |
c22fc9 |
path = dbus_object_create_path_vrrp();
|
|
Packit Service |
dfccb1 |
vrrp_guint = g_dbus_connection_register_object(connection, path,
|
|
Packit |
c22fc9 |
vrrp_introspection_data->interfaces[0],
|
|
Packit |
c22fc9 |
&interface_vtable, NULL, NULL, &local_error);
|
|
Packit Service |
dfccb1 |
g_hash_table_insert(objects, no_const_char_p("__Vrrp__"), GUINT_TO_POINTER(vrrp_guint));
|
|
Packit |
c22fc9 |
if (local_error != NULL) {
|
|
Packit |
c22fc9 |
log_message(LOG_INFO, "Registering VRRP object on %s failed: %s",
|
|
Packit |
c22fc9 |
path, local_error->message);
|
|
Packit |
c22fc9 |
g_clear_error(&local_error);
|
|
Packit |
c22fc9 |
}
|
|
Packit Service |
dfccb1 |
g_free(path);
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
/* for each available VRRP instance, register an object */
|
|
Packit Service |
dfccb1 |
if (list_empty(&vrrp_data->vrrp))
|
|
Packit |
c22fc9 |
return;
|
|
Packit |
c22fc9 |
|
|
Packit Service |
dfccb1 |
list_for_each_entry(vrrp, &vrrp_data->vrrp, e_list)
|
|
Packit |
c22fc9 |
dbus_create_object(vrrp);
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
/* Send a signal to say we have started */
|
|
Packit |
c22fc9 |
path = dbus_object_create_path_vrrp();
|
|
Packit |
c22fc9 |
dbus_emit_signal(global_connection, path, DBUS_VRRP_INTERFACE, "VrrpStarted", NULL);
|
|
Packit |
c22fc9 |
g_free(path);
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
/* Notify DBus of the state of our instances */
|
|
Packit Service |
dfccb1 |
list_for_each_entry(vrrp, &vrrp_data->vrrp, e_list)
|
|
Packit |
c22fc9 |
dbus_send_state_signal(vrrp);
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
/* run if bus name is acquired successfully */
|
|
Packit |
c22fc9 |
static void
|
|
Packit |
c22fc9 |
on_name_acquired(__attribute__((unused)) GDBusConnection *connection,
|
|
Packit |
c22fc9 |
const gchar *name,
|
|
Packit |
c22fc9 |
__attribute__((unused)) gpointer user_data)
|
|
Packit |
c22fc9 |
{
|
|
Packit |
c22fc9 |
log_message(LOG_INFO, "Acquired the name %s on the session bus", name);
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
/* run if bus name or connection are lost */
|
|
Packit |
c22fc9 |
static void
|
|
Packit |
c22fc9 |
on_name_lost(GDBusConnection *connection,
|
|
Packit |
c22fc9 |
const gchar *name,
|
|
Packit |
c22fc9 |
__attribute__((unused)) gpointer user_data)
|
|
Packit |
c22fc9 |
{
|
|
Packit |
c22fc9 |
log_message(LOG_INFO, "Lost the name %s on the session bus", name);
|
|
Packit |
c22fc9 |
global_connection = connection;
|
|
Packit Service |
dfccb1 |
g_hash_table_foreach_remove(objects, remove_object, NULL);
|
|
Packit |
c22fc9 |
objects = NULL;
|
|
Packit |
c22fc9 |
global_connection = NULL;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit Service |
dfccb1 |
static const gchar*
|
|
Packit Service |
dfccb1 |
read_file(const gchar* filepath)
|
|
Packit |
c22fc9 |
{
|
|
Packit |
c22fc9 |
FILE * f;
|
|
Packit Service |
dfccb1 |
long length;
|
|
Packit |
c22fc9 |
gchar *ret = NULL;
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
f = fopen(filepath, "r");
|
|
Packit |
c22fc9 |
if (f) {
|
|
Packit |
c22fc9 |
fseek(f, 0, SEEK_END);
|
|
Packit Service |
dfccb1 |
length = ftell(f);
|
|
Packit Service |
dfccb1 |
if (length < 0) {
|
|
Packit Service |
dfccb1 |
fclose(f);
|
|
Packit Service |
dfccb1 |
return NULL;
|
|
Packit Service |
dfccb1 |
}
|
|
Packit |
c22fc9 |
fseek(f, 0, SEEK_SET);
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
/* We can't use MALLOC since it isn't thread safe */
|
|
Packit |
c22fc9 |
ret = MALLOC(length + 1);
|
|
Packit |
c22fc9 |
if (ret) {
|
|
Packit |
c22fc9 |
if (fread(ret, length, 1, f) != 1) {
|
|
Packit |
c22fc9 |
log_message(LOG_INFO, "Failed to read all of %s", filepath);
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
ret[length] = '\0';
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
else
|
|
Packit |
c22fc9 |
log_message(LOG_INFO, "Unable to read Dbus file %s", filepath);
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
fclose(f);
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
return ret;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
static void *
|
|
Packit |
c22fc9 |
dbus_main(__attribute__ ((unused)) void *unused)
|
|
Packit |
c22fc9 |
{
|
|
Packit Service |
dfccb1 |
const gchar *introspection_xml;
|
|
Packit |
c22fc9 |
guint owner_id;
|
|
Packit |
c22fc9 |
const char *service_name;
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
objects = g_hash_table_new(g_str_hash, g_str_equal);
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
/* DBus service org.keepalived.Vrrp1 exposes two interfaces, Vrrp and Instance.
|
|
Packit |
c22fc9 |
* Vrrp is implemented by a single VRRP object for general purposes, such as printing
|
|
Packit |
c22fc9 |
* data or signaling that the VRRP process has been stopped.
|
|
Packit |
c22fc9 |
* Instance is implemented by an Instance object for every VRRP Instance in vrrp_data.
|
|
Packit |
c22fc9 |
* It exposes instance specific methods and properties.
|
|
Packit |
c22fc9 |
*/
|
|
Packit |
c22fc9 |
#ifdef DBUS_NEED_G_TYPE_INIT
|
|
Packit |
c22fc9 |
g_type_init();
|
|
Packit |
c22fc9 |
#endif
|
|
Packit |
c22fc9 |
GError *error = NULL;
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
/* read service interface data from xml files */
|
|
Packit |
c22fc9 |
introspection_xml = read_file(DBUS_VRRP_INTERFACE_FILE_PATH);
|
|
Packit |
c22fc9 |
if (!introspection_xml)
|
|
Packit |
c22fc9 |
return NULL;
|
|
Packit |
c22fc9 |
vrrp_introspection_data = g_dbus_node_info_new_for_xml(introspection_xml, &error);
|
|
Packit Service |
dfccb1 |
FREE_CONST(introspection_xml);
|
|
Packit |
c22fc9 |
if (error != NULL) {
|
|
Packit |
c22fc9 |
log_message(LOG_INFO, "Parsing DBus interface %s from file %s failed: %s",
|
|
Packit |
c22fc9 |
DBUS_VRRP_INTERFACE, DBUS_VRRP_INTERFACE_FILE_PATH, error->message);
|
|
Packit |
c22fc9 |
g_clear_error(&error);
|
|
Packit |
c22fc9 |
return NULL;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
introspection_xml = read_file(DBUS_VRRP_INSTANCE_INTERFACE_FILE_PATH);
|
|
Packit |
c22fc9 |
if (!introspection_xml)
|
|
Packit |
c22fc9 |
return NULL;
|
|
Packit |
c22fc9 |
vrrp_instance_introspection_data = g_dbus_node_info_new_for_xml(introspection_xml, &error);
|
|
Packit Service |
dfccb1 |
FREE_CONST(introspection_xml);
|
|
Packit |
c22fc9 |
if (error != NULL) {
|
|
Packit |
c22fc9 |
log_message(LOG_INFO, "Parsing DBus interface %s from file %s failed: %s",
|
|
Packit |
c22fc9 |
DBUS_VRRP_INSTANCE_INTERFACE, DBUS_VRRP_INSTANCE_INTERFACE_FILE_PATH, error->message);
|
|
Packit |
c22fc9 |
g_clear_error(&error);
|
|
Packit |
c22fc9 |
return NULL;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
service_name = global_data->dbus_service_name ? global_data->dbus_service_name : DBUS_SERVICE_NAME;
|
|
Packit |
c22fc9 |
owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
|
|
Packit |
c22fc9 |
service_name,
|
|
Packit |
c22fc9 |
G_BUS_NAME_OWNER_FLAGS_NONE,
|
|
Packit |
c22fc9 |
on_bus_acquired,
|
|
Packit |
c22fc9 |
on_name_acquired,
|
|
Packit |
c22fc9 |
on_name_lost,
|
|
Packit |
c22fc9 |
NULL, /* user_data */
|
|
Packit |
c22fc9 |
NULL); /* user_data_free_func */
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
loop = g_main_loop_new(NULL, FALSE);
|
|
Packit |
c22fc9 |
g_main_loop_run(loop);
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
/* cleanup after loop terminates */
|
|
Packit |
c22fc9 |
g_main_loop_unref(loop);
|
|
Packit |
c22fc9 |
g_bus_unown_name(owner_id);
|
|
Packit |
c22fc9 |
global_connection = NULL;
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
sem_post(&thread_end);
|
|
Packit |
c22fc9 |
pthread_exit(0);
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
/* The following functions are run in the context of the main vrrp thread */
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
/* send signal VrrpStatusChange
|
|
Packit |
c22fc9 |
* containing the new state of vrrp */
|
|
Packit |
c22fc9 |
void
|
|
Packit |
c22fc9 |
dbus_send_state_signal(vrrp_t *vrrp)
|
|
Packit |
c22fc9 |
{
|
|
Packit |
c22fc9 |
gchar *object_path;
|
|
Packit |
c22fc9 |
GVariant *args;
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
/* the interface will go through the initial state changes before
|
|
Packit |
c22fc9 |
* the main loop can be started and global_connection initialised */
|
|
Packit |
c22fc9 |
if (global_connection == NULL)
|
|
Packit |
c22fc9 |
return;
|
|
Packit |
c22fc9 |
|
|
Packit Service |
dfccb1 |
object_path = dbus_object_create_path_instance(vrrp->ifp ? IF_NAME(VRRP_CONFIGURED_IFP(vrrp)) : no_interface, vrrp->vrid, vrrp->family);
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
args = g_variant_new("(u)", vrrp->state);
|
|
Packit |
c22fc9 |
dbus_emit_signal(global_connection, object_path, DBUS_VRRP_INSTANCE_INTERFACE, "VrrpStatusChange", args);
|
|
Packit |
c22fc9 |
g_free(object_path);
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
/* send signal VrrpRestarted */
|
|
Packit |
c22fc9 |
static void
|
|
Packit |
c22fc9 |
dbus_send_reload_signal(void)
|
|
Packit |
c22fc9 |
{
|
|
Packit |
c22fc9 |
gchar *path;
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
if (global_connection == NULL)
|
|
Packit |
c22fc9 |
return;
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
path = dbus_object_create_path_vrrp();
|
|
Packit |
c22fc9 |
dbus_emit_signal(global_connection, path, DBUS_VRRP_INTERFACE, "VrrpReloaded", NULL);
|
|
Packit |
c22fc9 |
g_free(path);
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
static gboolean
|
|
Packit Service |
dfccb1 |
dbus_unregister_object(const char *str)
|
|
Packit |
c22fc9 |
{
|
|
Packit |
c22fc9 |
gboolean ret = false;
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
gpointer value = g_hash_table_lookup(objects, str);
|
|
Packit |
c22fc9 |
if (value) {
|
|
Packit |
c22fc9 |
ret = unregister_object(str, value, NULL);
|
|
Packit |
c22fc9 |
log_message(LOG_INFO, "Deleted DBus object for instance %s", str);
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
#ifdef DBUS_DEBUG
|
|
Packit |
c22fc9 |
else
|
|
Packit |
c22fc9 |
log_message(LOG_INFO, "DBus object not found for instance %s", str);
|
|
Packit |
c22fc9 |
#endif
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
return ret;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
void
|
|
Packit Service |
dfccb1 |
dbus_remove_object(const vrrp_t *vrrp)
|
|
Packit |
c22fc9 |
{
|
|
Packit |
c22fc9 |
dbus_unregister_object(vrrp->iname);
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit Service |
dfccb1 |
static void
|
|
Packit Service |
dfccb1 |
handle_dbus_msg(__attribute__((unused)) thread_ref_t thread)
|
|
Packit |
c22fc9 |
{
|
|
Packit |
c22fc9 |
dbus_queue_ent_t *ent;
|
|
Packit |
c22fc9 |
char recv_buf;
|
|
Packit |
c22fc9 |
vrrp_t *vrrp;
|
|
Packit |
c22fc9 |
#ifdef _WITH_DBUS_CREATE_INSTANCE_
|
|
Packit |
c22fc9 |
gchar *name;
|
|
Packit |
c22fc9 |
#endif
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
if (read(dbus_in_pipe[0], &recv_buf, 1) != 1)
|
|
Packit |
c22fc9 |
log_message(LOG_INFO, "Read from DBus thread to vrrp thread failed");
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
if ((ent = ent_ptr) != NULL) {
|
|
Packit |
c22fc9 |
ent->reply = DBUS_SUCCESS;
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
if (ent->action == DBUS_PRINT_DATA) {
|
|
Packit |
c22fc9 |
log_message(LOG_INFO, "Printing VRRP data on DBus request");
|
|
Packit |
c22fc9 |
vrrp_print_data();
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
else if (ent->action == DBUS_PRINT_STATS) {
|
|
Packit |
c22fc9 |
log_message(LOG_INFO, "Printing VRRP stats on DBus request");
|
|
Packit Service |
dfccb1 |
vrrp_print_stats(false);
|
|
Packit Service |
dfccb1 |
}
|
|
Packit Service |
dfccb1 |
else if (ent->action == DBUS_PRINT_STATS_CLEAR) {
|
|
Packit Service |
dfccb1 |
log_message(LOG_INFO, "Printing and clearing VRRP stats on DBus request");
|
|
Packit Service |
dfccb1 |
vrrp_print_stats(true);
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
#ifdef _WITH_DBUS_CREATE_INSTANCE_
|
|
Packit |
c22fc9 |
else if (ent->action == DBUS_CREATE_INSTANCE) {
|
|
Packit |
c22fc9 |
g_variant_get(ent->args, "(s)", &name);
|
|
Packit |
c22fc9 |
ent->reply = dbus_create_object_params(name, ent->ifname, ent->vrid, ent->family, true);
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
else if (ent->action == DBUS_DESTROY_INSTANCE) {
|
|
Packit |
c22fc9 |
g_variant_get(ent->args, "(s)", &name);
|
|
Packit |
c22fc9 |
if (!dbus_unregister_object(name))
|
|
Packit |
c22fc9 |
ent->reply = DBUS_INSTANCE_NOT_FOUND;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
#endif
|
|
Packit |
c22fc9 |
else if (ent->action == DBUS_SEND_GARP) {
|
|
Packit |
c22fc9 |
ent->reply = DBUS_INTERFACE_NOT_FOUND;
|
|
Packit |
c22fc9 |
vrrp = get_vrrp_instance(ent->ifname, ent->vrid, ent->family);
|
|
Packit |
c22fc9 |
if (vrrp) {
|
|
Packit |
c22fc9 |
log_message(LOG_INFO, "Sending garps on %s on DBus request", vrrp->iname);
|
|
Packit |
c22fc9 |
vrrp_send_link_update(vrrp, 1);
|
|
Packit |
c22fc9 |
ent->reply = DBUS_SUCCESS;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
else if (ent->action == DBUS_GET_NAME ||
|
|
Packit |
c22fc9 |
ent->action == DBUS_GET_STATUS) {
|
|
Packit |
c22fc9 |
/* we look for the vrrp instance object that corresponds to our interface and group */
|
|
Packit |
c22fc9 |
ent->reply = DBUS_INTERFACE_NOT_FOUND;
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
vrrp = get_vrrp_instance(ent->ifname, ent->vrid, ent->family);
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
if (vrrp) {
|
|
Packit |
c22fc9 |
/* the property_name argument is the property we want to Get */
|
|
Packit |
c22fc9 |
if (ent->action == DBUS_GET_NAME)
|
|
Packit |
c22fc9 |
ent->args = g_variant_new("(s)", vrrp->iname);
|
|
Packit |
c22fc9 |
else if (ent->action == DBUS_GET_STATUS)
|
|
Packit |
c22fc9 |
ent->args = g_variant_new("(us)", vrrp->state, state_str(vrrp->state));
|
|
Packit |
c22fc9 |
else
|
|
Packit |
c22fc9 |
ent->args = NULL; /* How did we get here? */
|
|
Packit |
c22fc9 |
ent->reply = DBUS_SUCCESS;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
}
|
|
Packit Service |
dfccb1 |
if (write(dbus_out_pipe[1], &recv_buf, 1) != 1)
|
|
Packit |
c22fc9 |
log_message(LOG_INFO, "Write from main thread to DBus thread failed");
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit Service |
dfccb1 |
thread_add_read(master, handle_dbus_msg, NULL, dbus_in_pipe[0], TIMER_NEVER, false);
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
void
|
|
Packit Service |
dfccb1 |
dbus_reload(const list_head_t *o, const list_head_t *n)
|
|
Packit |
c22fc9 |
{
|
|
Packit Service |
dfccb1 |
vrrp_t *vrrp_n, *vrrp_o;
|
|
Packit |
c22fc9 |
|
|
Packit Service |
dfccb1 |
if (!dbus_running)
|
|
Packit Service |
dfccb1 |
return;
|
|
Packit |
c22fc9 |
|
|
Packit Service |
dfccb1 |
list_for_each_entry(vrrp_n, n, e_list) {
|
|
Packit Service |
dfccb1 |
const char *n_name;
|
|
Packit Service |
dfccb1 |
bool match_found;
|
|
Packit Service |
dfccb1 |
|
|
Packit Service |
dfccb1 |
n_name = vrrp_n->ifp ? VRRP_CONFIGURED_IFP(vrrp_n)->ifname : no_interface;
|
|
Packit Service |
dfccb1 |
|
|
Packit Service |
dfccb1 |
/* Try and find an instance with same vrid/family/interface that existed before and now */
|
|
Packit Service |
dfccb1 |
match_found = false;
|
|
Packit Service |
dfccb1 |
list_for_each_entry(vrrp_o, o, e_list) {
|
|
Packit Service |
dfccb1 |
if (vrrp_n->vrid == vrrp_o->vrid &&
|
|
Packit Service |
dfccb1 |
vrrp_n->family == vrrp_o->family &&
|
|
Packit Service |
dfccb1 |
// TODO - need to match on unicast_src if no interface
|
|
Packit Service |
dfccb1 |
!strcmp(n_name, VRRP_CONFIGURED_IFP(vrrp_o)->ifname)) {
|
|
Packit Service |
dfccb1 |
/* If the old instance exists in the new config,
|
|
Packit Service |
dfccb1 |
* then the dbus object will exist */
|
|
Packit Service |
dfccb1 |
if (!strcmp(vrrp_n->iname, vrrp_o->iname)) {
|
|
Packit Service |
dfccb1 |
match_found = true;
|
|
Packit Service |
dfccb1 |
g_hash_table_replace(objects, no_const_char_p(vrrp_n->iname), g_hash_table_lookup(objects, vrrp_o->iname));
|
|
Packit Service |
dfccb1 |
break;
|
|
Packit Service |
dfccb1 |
} else {
|
|
Packit Service |
dfccb1 |
gpointer instance;
|
|
Packit Service |
dfccb1 |
if ((instance = g_hash_table_lookup(objects, vrrp_o->iname))) {
|
|
Packit Service |
dfccb1 |
g_hash_table_remove(objects, vrrp_o->iname);
|
|
Packit Service |
dfccb1 |
g_hash_table_insert(objects, no_const_char_p(vrrp_n->iname), instance);
|
|
Packit Service |
dfccb1 |
}
|
|
Packit Service |
dfccb1 |
match_found = true;
|
|
Packit Service |
dfccb1 |
break;
|
|
Packit Service |
dfccb1 |
}
|
|
Packit |
c22fc9 |
|
|
Packit Service |
dfccb1 |
#if 0
|
|
Packit Service |
dfccb1 |
/* The following was in the original code, but I can't work out
|
|
Packit Service |
dfccb1 |
* its purpose. Leaving it here for now in case it is really needed. */
|
|
Packit |
c22fc9 |
|
|
Packit Service |
dfccb1 |
/* Check if the old instance name we found still exists
|
|
Packit Service |
dfccb1 |
* (but has a different vrid/family/interface) */
|
|
Packit Service |
dfccb1 |
list_for_each_entry(vrrp_n3, n, e_list) {
|
|
Packit Service |
dfccb1 |
if (!strcmp(vrrp_o->iname, vrrp_n3->iname)) {
|
|
Packit |
c22fc9 |
match_found = true;
|
|
Packit |
c22fc9 |
break;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
}
|
|
Packit Service |
dfccb1 |
#endif
|
|
Packit |
c22fc9 |
}
|
|
Packit Service |
dfccb1 |
}
|
|
Packit |
c22fc9 |
|
|
Packit Service |
dfccb1 |
if (match_found)
|
|
Packit Service |
dfccb1 |
continue;
|
|
Packit |
c22fc9 |
|
|
Packit Service |
dfccb1 |
dbus_create_object(vrrp_n);
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
/* Signal we have reloaded */
|
|
Packit |
c22fc9 |
dbus_send_reload_signal();
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
/* We need to reinstate the read thread */
|
|
Packit Service |
dfccb1 |
thread_add_read(master, handle_dbus_msg, NULL, dbus_in_pipe[0], TIMER_NEVER, false);
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
bool
|
|
Packit |
c22fc9 |
dbus_start(void)
|
|
Packit |
c22fc9 |
{
|
|
Packit |
c22fc9 |
pthread_t dbus_thread;
|
|
Packit |
c22fc9 |
sigset_t sigset, cursigset;
|
|
Packit Service |
dfccb1 |
int flags;
|
|
Packit Service |
dfccb1 |
|
|
Packit Service |
dfccb1 |
if (dbus_running)
|
|
Packit Service |
dfccb1 |
return false;
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
if (open_pipe(dbus_in_pipe)) {
|
|
Packit |
c22fc9 |
log_message(LOG_INFO, "Unable to create inbound dbus pipe - disabling DBus");
|
|
Packit |
c22fc9 |
return false;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
if (open_pipe(dbus_out_pipe)) {
|
|
Packit |
c22fc9 |
log_message(LOG_INFO, "Unable to create outbound dbus pipe - disabling DBus");
|
|
Packit |
c22fc9 |
close(dbus_in_pipe[0]);
|
|
Packit |
c22fc9 |
close(dbus_in_pipe[1]);
|
|
Packit Service |
dfccb1 |
dbus_in_pipe[0] = -1;
|
|
Packit Service |
dfccb1 |
dbus_out_pipe[0] = -1;
|
|
Packit |
c22fc9 |
return false;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
/* We don't want the main thread to block when using the pipes,
|
|
Packit |
c22fc9 |
* but the other side of the pipes should block. */
|
|
Packit Service |
dfccb1 |
flags = fcntl(dbus_in_pipe[1], F_GETFL);
|
|
Packit Service |
dfccb1 |
if (flags == -1 ||
|
|
Packit Service |
dfccb1 |
fcntl(dbus_in_pipe[1], F_SETFL, flags & ~O_NONBLOCK) == -1)
|
|
Packit Service |
dfccb1 |
log_message(LOG_INFO, "Unable to set dbus thread in_pipe blocking - (%d - %m)", errno);
|
|
Packit Service |
dfccb1 |
flags = fcntl(dbus_out_pipe[0], F_GETFL);
|
|
Packit Service |
dfccb1 |
if (flags == -1 ||
|
|
Packit Service |
dfccb1 |
fcntl(dbus_out_pipe[0], F_SETFL, flags & ~O_NONBLOCK) == -1)
|
|
Packit Service |
dfccb1 |
log_message(LOG_INFO, "Unable to set dbus thread out_pipe blocking - (%d - %m)", errno);
|
|
Packit |
c22fc9 |
|
|
Packit Service |
dfccb1 |
thread_add_read(master, handle_dbus_msg, NULL, dbus_in_pipe[0], TIMER_NEVER, false);
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
/* Initialise the thread termination semaphore */
|
|
Packit |
c22fc9 |
sem_init(&thread_end, 0, 0);
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
/* Block signals (all) we don't want the new thread to process */
|
|
Packit |
c22fc9 |
sigfillset(&sigset);
|
|
Packit |
c22fc9 |
pthread_sigmask(SIG_SETMASK, &sigset, &cursigset);
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
/* Now create the dbus thread */
|
|
Packit |
c22fc9 |
pthread_create(&dbus_thread, NULL, &dbus_main, NULL);
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
/* Reenable our signals */
|
|
Packit |
c22fc9 |
pthread_sigmask(SIG_SETMASK, &cursigset, NULL);
|
|
Packit |
c22fc9 |
|
|
Packit Service |
dfccb1 |
dbus_running = true;
|
|
Packit Service |
dfccb1 |
|
|
Packit |
c22fc9 |
return true;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
void
|
|
Packit |
c22fc9 |
dbus_stop(void)
|
|
Packit |
c22fc9 |
{
|
|
Packit |
c22fc9 |
struct timespec thread_end_wait;
|
|
Packit |
c22fc9 |
int ret;
|
|
Packit |
c22fc9 |
gchar *path;
|
|
Packit |
c22fc9 |
|
|
Packit Service |
dfccb1 |
if (!dbus_running)
|
|
Packit Service |
dfccb1 |
return;
|
|
Packit Service |
dfccb1 |
|
|
Packit Service |
dfccb1 |
g_hash_table_foreach_remove(objects, remove_object, NULL);
|
|
Packit Service |
dfccb1 |
objects = NULL;
|
|
Packit Service |
dfccb1 |
|
|
Packit |
c22fc9 |
if (global_connection != NULL) {
|
|
Packit |
c22fc9 |
path = dbus_object_create_path_vrrp();
|
|
Packit |
c22fc9 |
dbus_emit_signal(global_connection, path, DBUS_VRRP_INTERFACE, "VrrpStopped", NULL);
|
|
Packit |
c22fc9 |
g_free(path);
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
g_main_loop_quit(loop);
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
g_dbus_node_info_unref(vrrp_introspection_data);
|
|
Packit |
c22fc9 |
g_dbus_node_info_unref(vrrp_instance_introspection_data);
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
clock_gettime(CLOCK_REALTIME, &thread_end_wait);
|
|
Packit |
c22fc9 |
thread_end_wait.tv_sec += 1;
|
|
Packit Service |
dfccb1 |
while ((ret = sem_timedwait(&thread_end, &thread_end_wait)) == -1 && check_EINTR(errno));
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
if (ret == -1 ) {
|
|
Packit |
c22fc9 |
if (errno == ETIMEDOUT)
|
|
Packit |
c22fc9 |
log_message(LOG_INFO, "DBus thread termination timed out");
|
|
Packit |
c22fc9 |
else
|
|
Packit |
c22fc9 |
log_message(LOG_INFO, "sem_timewait error %d", errno);
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
else {
|
|
Packit |
c22fc9 |
log_message(LOG_INFO, "Released DBus");
|
|
Packit |
c22fc9 |
sem_destroy(&thread_end);
|
|
Packit |
c22fc9 |
}
|
|
Packit Service |
dfccb1 |
|
|
Packit Service |
dfccb1 |
dbus_running = false;
|
|
Packit Service |
dfccb1 |
|
|
Packit Service |
dfccb1 |
close(dbus_in_pipe[0]);
|
|
Packit Service |
dfccb1 |
close(dbus_in_pipe[1]);
|
|
Packit Service |
dfccb1 |
dbus_in_pipe[0] = -1;
|
|
Packit Service |
dfccb1 |
dbus_in_pipe[0] = -1;
|
|
Packit Service |
dfccb1 |
close(dbus_out_pipe[0]);
|
|
Packit Service |
dfccb1 |
close(dbus_out_pipe[1]);
|
|
Packit Service |
dfccb1 |
dbus_out_pipe[0] = -1;
|
|
Packit Service |
dfccb1 |
dbus_out_pipe[0] = -1;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
#ifdef THREAD_DUMP
|
|
Packit |
c22fc9 |
void
|
|
Packit |
c22fc9 |
register_vrrp_dbus_addresses(void)
|
|
Packit |
c22fc9 |
{
|
|
Packit |
c22fc9 |
register_thread_address("handle_dbus_msg", handle_dbus_msg);
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
#endif
|