Blame keepalived/vrrp/vrrp_json.c

Packit c22fc9
/*
Packit c22fc9
 * Soft:        Vrrpd is an implementation of VRRPv2 as specified in rfc2338.
Packit c22fc9
 *              VRRP is a protocol which elect a master server on a LAN. If the
Packit c22fc9
 *              master fails, a backup server takes over.
Packit c22fc9
 *              The original implementation has been made by jerome etienne.
Packit c22fc9
 *
Packit c22fc9
 * Part:        Output running VRRP state information in JSON format
Packit c22fc9
 *
Packit c22fc9
 * Author:      Damien Clabaut, <Damien.Clabaut@corp.ovh.com>
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) 2017 Damien Clabaut, <Damien.Clabaut@corp.ovh.com>
Packit c22fc9
 * Copyright (C) 2017-2017 Alexandre Cassen, <acassen@gmail.com>
Packit c22fc9
 */
Packit c22fc9
Packit c22fc9
#include "config.h"
Packit c22fc9
#include "vrrp_json.h"
Packit c22fc9
Packit c22fc9
#include <errno.h>
Packit c22fc9
#include <stdio.h>
Packit c22fc9
#include <json.h>
Packit c22fc9
Packit c22fc9
#include "vrrp.h"
Packit c22fc9
#include "vrrp_track.h"
Packit c22fc9
#include "list.h"
Packit c22fc9
#include "vrrp_data.h"
Packit c22fc9
#include "vrrp_iproute.h"
Packit c22fc9
#include "vrrp_iprule.h"
Packit c22fc9
#include "logger.h"
Packit c22fc9
#include "timer.h"
Packit c22fc9
#include "utils.h"
Packit c22fc9
Packit c22fc9
static inline double
Packit c22fc9
timeval_to_double(const timeval_t *t)
Packit c22fc9
{
Packit c22fc9
	/* The casts are necessary to avoid conversion warnings */
Packit c22fc9
	return (double)t->tv_sec + (double)t->tv_usec / TIMER_HZ_FLOAT;
Packit c22fc9
}
Packit c22fc9
Packit c22fc9
void
Packit c22fc9
vrrp_print_json(void)
Packit c22fc9
{
Packit c22fc9
	FILE *file;
Packit c22fc9
	element e;
Packit c22fc9
	struct json_object *array;
Packit c22fc9
Packit c22fc9
	if (LIST_ISEMPTY(vrrp_data->vrrp))
Packit c22fc9
		return;
Packit c22fc9
Packit c22fc9
	file = fopen_safe("/tmp/keepalived.json", "w");
Packit c22fc9
	if (!file) {
Packit c22fc9
		log_message(LOG_INFO, "Can't open /tmp/keepalived.json (%d: %s)",
Packit c22fc9
			errno, strerror(errno));
Packit c22fc9
		return;
Packit c22fc9
	}
Packit c22fc9
Packit c22fc9
	array = json_object_new_array();
Packit c22fc9
Packit c22fc9
	for (e = LIST_HEAD(vrrp_data->vrrp); e; ELEMENT_NEXT(e)) {
Packit c22fc9
		struct json_object *instance_json, *json_stats, *json_data,
Packit c22fc9
			*vips, *evips, *track_ifp, *track_script;
Packit c22fc9
#ifdef _HAVE_FIB_ROUTING_
Packit c22fc9
		struct json_object *vroutes, *vrules;
Packit c22fc9
#endif
Packit c22fc9
		element f;
Packit c22fc9
Packit c22fc9
		vrrp_t *vrrp = ELEMENT_DATA(e);
Packit c22fc9
		instance_json = json_object_new_object();
Packit c22fc9
		json_stats = json_object_new_object();
Packit c22fc9
		json_data = json_object_new_object();
Packit c22fc9
		vips = json_object_new_array();
Packit c22fc9
		evips = json_object_new_array();
Packit c22fc9
		track_ifp = json_object_new_array();
Packit c22fc9
		track_script = json_object_new_array();
Packit c22fc9
#ifdef _HAVE_FIB_ROUTING_
Packit c22fc9
		vroutes = json_object_new_array();
Packit c22fc9
		vrules = json_object_new_array();
Packit c22fc9
#endif
Packit c22fc9
Packit c22fc9
		// Dump data to json
Packit c22fc9
		json_object_object_add(json_data, "iname",
Packit c22fc9
			json_object_new_string(vrrp->iname));
Packit c22fc9
		json_object_object_add(json_data, "dont_track_primary",
Packit c22fc9
			json_object_new_int(vrrp->dont_track_primary));
Packit c22fc9
		json_object_object_add(json_data, "skip_check_adv_addr",
Packit c22fc9
			json_object_new_int(vrrp->skip_check_adv_addr));
Packit c22fc9
		json_object_object_add(json_data, "strict_mode",
Packit c22fc9
			json_object_new_int((int)vrrp->strict_mode));
Packit c22fc9
#ifdef _HAVE_VRRP_VMAC_
Packit c22fc9
		json_object_object_add(json_data, "vmac_ifname",
Packit c22fc9
			json_object_new_string(vrrp->vmac_ifname));
Packit c22fc9
#endif
Packit c22fc9
		// Tracked interfaces are stored in a list
Packit c22fc9
		if (!LIST_ISEMPTY(vrrp->track_ifp)) {
Packit c22fc9
			for (f = LIST_HEAD(vrrp->track_ifp); f; ELEMENT_NEXT(f)) {
Packit c22fc9
				interface_t *ifp = ELEMENT_DATA(f);
Packit c22fc9
				json_object_array_add(track_ifp,
Packit c22fc9
					json_object_new_string(ifp->ifname));
Packit c22fc9
			}
Packit c22fc9
		}
Packit c22fc9
		json_object_object_add(json_data, "track_ifp", track_ifp);
Packit c22fc9
Packit c22fc9
		// Tracked scripts also
Packit c22fc9
		if (!LIST_ISEMPTY(vrrp->track_script)) {
Packit c22fc9
			for (f = LIST_HEAD(vrrp->track_script); f; ELEMENT_NEXT(f)) {
Packit c22fc9
				tracked_sc_t *tsc = ELEMENT_DATA(f);
Packit c22fc9
				vrrp_script_t *vscript = tsc->scr;
Packit c22fc9
				json_object_array_add(track_script,
Packit c22fc9
					json_object_new_string(cmd_str(&vscript->script)));
Packit c22fc9
			}
Packit c22fc9
		}
Packit c22fc9
		json_object_object_add(json_data, "track_script", track_script);
Packit c22fc9
Packit c22fc9
		json_object_object_add(json_data, "ifp_ifname",
Packit c22fc9
			json_object_new_string(vrrp->ifp->ifname));
Packit c22fc9
		json_object_object_add(json_data, "master_priority",
Packit c22fc9
			json_object_new_int(vrrp->master_priority));
Packit c22fc9
		json_object_object_add(json_data, "last_transition",
Packit c22fc9
			json_object_new_double(timeval_to_double(&vrrp->last_transition)));
Packit c22fc9
		json_object_object_add(json_data, "garp_delay",
Packit c22fc9
			json_object_new_double(vrrp->garp_delay / TIMER_HZ_FLOAT));
Packit c22fc9
		json_object_object_add(json_data, "garp_refresh",
Packit c22fc9
			json_object_new_int((int)vrrp->garp_refresh.tv_sec));
Packit c22fc9
		json_object_object_add(json_data, "garp_rep",
Packit c22fc9
			json_object_new_int((int)vrrp->garp_rep));
Packit c22fc9
		json_object_object_add(json_data, "garp_refresh_rep",
Packit c22fc9
			json_object_new_int((int)vrrp->garp_refresh_rep));
Packit c22fc9
		json_object_object_add(json_data, "garp_lower_prio_delay",
Packit c22fc9
			json_object_new_int((int)(vrrp->garp_lower_prio_delay / TIMER_HZ)));
Packit c22fc9
		json_object_object_add(json_data, "garp_lower_prio_rep",
Packit c22fc9
			json_object_new_int((int)vrrp->garp_lower_prio_rep));
Packit c22fc9
		json_object_object_add(json_data, "lower_prio_no_advert",
Packit c22fc9
			json_object_new_int((int)vrrp->lower_prio_no_advert));
Packit c22fc9
		json_object_object_add(json_data, "higher_prio_send_advert",
Packit c22fc9
			json_object_new_int((int)vrrp->higher_prio_send_advert));
Packit c22fc9
		json_object_object_add(json_data, "vrid",
Packit c22fc9
			json_object_new_int(vrrp->vrid));
Packit c22fc9
		json_object_object_add(json_data, "base_priority",
Packit c22fc9
			json_object_new_int(vrrp->base_priority));
Packit c22fc9
		json_object_object_add(json_data, "effective_priority",
Packit c22fc9
			json_object_new_int(vrrp->effective_priority));
Packit c22fc9
		json_object_object_add(json_data, "vipset",
Packit c22fc9
			json_object_new_boolean(vrrp->vipset));
Packit c22fc9
Packit c22fc9
		//Virtual IPs are stored in a list
Packit c22fc9
		if (!LIST_ISEMPTY(vrrp->vip)) {
Packit c22fc9
			for (f = LIST_HEAD(vrrp->vip); f; ELEMENT_NEXT(f)) {
Packit c22fc9
				ip_address_t *vip = ELEMENT_DATA(f);
Packit c22fc9
				char ipaddr[INET6_ADDRSTRLEN];
Packit c22fc9
				inet_ntop(vrrp->family, &(vip->u.sin.sin_addr.s_addr),
Packit c22fc9
					ipaddr, INET6_ADDRSTRLEN);
Packit c22fc9
				json_object_array_add(vips,
Packit c22fc9
					json_object_new_string(ipaddr));
Packit c22fc9
			}
Packit c22fc9
		}
Packit c22fc9
		json_object_object_add(json_data, "vips", vips);
Packit c22fc9
Packit c22fc9
		//External VIPs are also stored in a list
Packit c22fc9
		if (!LIST_ISEMPTY(vrrp->evip)) {
Packit c22fc9
			for (f = LIST_HEAD(vrrp->evip); f; ELEMENT_NEXT(f)) {
Packit c22fc9
				ip_address_t *evip = ELEMENT_DATA(f);
Packit c22fc9
				char ipaddr[INET6_ADDRSTRLEN];
Packit c22fc9
				inet_ntop(vrrp->family, &(evip->u.sin.sin_addr.s_addr),
Packit c22fc9
					ipaddr, INET6_ADDRSTRLEN);
Packit c22fc9
				json_object_array_add(evips,
Packit c22fc9
					json_object_new_string(ipaddr));
Packit c22fc9
			}
Packit c22fc9
		}
Packit c22fc9
		json_object_object_add(json_data, "evips", evips);
Packit c22fc9
Packit c22fc9
		json_object_object_add(json_data, "promote_secondaries",
Packit c22fc9
			json_object_new_boolean(vrrp->promote_secondaries));
Packit c22fc9
Packit c22fc9
#ifdef _HAVE_FIB_ROUTING_
Packit c22fc9
		// Dump vroutes
Packit c22fc9
		if (!LIST_ISEMPTY(vrrp->vroutes)) {
Packit c22fc9
			for (f = LIST_HEAD(vrrp->vroutes); f; ELEMENT_NEXT(f)) {
Packit c22fc9
				ip_route_t *route = ELEMENT_DATA(f);
Packit c22fc9
				char *buf = MALLOC(ROUTE_BUF_SIZE);
Packit c22fc9
				format_iproute(route, buf, ROUTE_BUF_SIZE);
Packit c22fc9
				json_object_array_add(vroutes,
Packit c22fc9
					json_object_new_string(buf));
Packit c22fc9
			}
Packit c22fc9
		}
Packit c22fc9
		json_object_object_add(json_data, "vroutes", vroutes);
Packit c22fc9
Packit c22fc9
		// Dump vrules
Packit c22fc9
		if (!LIST_ISEMPTY(vrrp->vrules)) {
Packit c22fc9
			for (f = LIST_HEAD(vrrp->vrules); f; ELEMENT_NEXT(f)) {
Packit c22fc9
				ip_rule_t *rule = ELEMENT_DATA(f);
Packit c22fc9
				char *buf = MALLOC(RULE_BUF_SIZE);
Packit c22fc9
				format_iprule(rule, buf, RULE_BUF_SIZE);
Packit c22fc9
				json_object_array_add(vrules,
Packit c22fc9
					json_object_new_string(buf));
Packit c22fc9
			}
Packit c22fc9
		}
Packit c22fc9
		json_object_object_add(json_data, "vrules", vrules);
Packit c22fc9
#endif
Packit c22fc9
Packit c22fc9
		json_object_object_add(json_data, "adver_int",
Packit c22fc9
			json_object_new_double(vrrp->adver_int / TIMER_HZ_FLOAT));
Packit c22fc9
		json_object_object_add(json_data, "master_adver_int",
Packit c22fc9
			json_object_new_double(vrrp->master_adver_int / TIMER_HZ_FLOAT));
Packit c22fc9
		json_object_object_add(json_data, "accept",
Packit c22fc9
			json_object_new_int((int)vrrp->accept));
Packit c22fc9
		json_object_object_add(json_data, "nopreempt",
Packit c22fc9
			json_object_new_boolean(vrrp->nopreempt));
Packit c22fc9
		json_object_object_add(json_data, "preempt_delay",
Packit c22fc9
			json_object_new_int((int)(vrrp->preempt_delay / TIMER_HZ)));
Packit c22fc9
		json_object_object_add(json_data, "state",
Packit c22fc9
			json_object_new_int(vrrp->state));
Packit c22fc9
		json_object_object_add(json_data, "wantstate",
Packit c22fc9
			json_object_new_int(vrrp->wantstate));
Packit c22fc9
		json_object_object_add(json_data, "version",
Packit c22fc9
			json_object_new_int(vrrp->version));
Packit c22fc9
		if (vrrp->script_backup)
Packit c22fc9
			json_object_object_add(json_data, "script_backup",
Packit c22fc9
				json_object_new_string(cmd_str(vrrp->script_backup)));
Packit c22fc9
		if (vrrp->script_master)
Packit c22fc9
			json_object_object_add(json_data, "script_master",
Packit c22fc9
				json_object_new_string(cmd_str(vrrp->script_master)));
Packit c22fc9
		if (vrrp->script_fault)
Packit c22fc9
			json_object_object_add(json_data, "script_fault",
Packit c22fc9
				json_object_new_string(cmd_str(vrrp->script_fault)));
Packit c22fc9
		if (vrrp->script_stop)
Packit c22fc9
			json_object_object_add(json_data, "script_stop",
Packit c22fc9
				json_object_new_string(cmd_str(vrrp->script_stop)));
Packit c22fc9
		if (vrrp->script)
Packit c22fc9
			json_object_object_add(json_data, "script",
Packit c22fc9
				json_object_new_string(cmd_str(vrrp->script)));
Packit c22fc9
		if (vrrp->script_master_rx_lower_pri)
Packit c22fc9
			json_object_object_add(json_data, "script_master_rx_lower_pri",
Packit c22fc9
				json_object_new_string(cmd_str(vrrp->script_master_rx_lower_pri)));
Packit c22fc9
		json_object_object_add(json_data, "smtp_alert",
Packit c22fc9
			json_object_new_boolean(vrrp->smtp_alert));
Packit c22fc9
#ifdef _WITH_VRRP_AUTH_
Packit c22fc9
		if (vrrp->auth_type) {
Packit c22fc9
			json_object_object_add(json_data, "auth_type",
Packit c22fc9
				json_object_new_int(vrrp->auth_type));
Packit c22fc9
Packit c22fc9
			if (vrrp->auth_type != VRRP_AUTH_AH) {
Packit c22fc9
				char auth_data[sizeof(vrrp->auth_data) + 1];
Packit c22fc9
				memcpy(auth_data, vrrp->auth_data, sizeof(vrrp->auth_data));
Packit c22fc9
				auth_data[sizeof(vrrp->auth_data)] = '\0';
Packit c22fc9
				json_object_object_add(json_data, "auth_data",
Packit c22fc9
					json_object_new_string(auth_data));
Packit c22fc9
			}
Packit c22fc9
		}
Packit c22fc9
		else
Packit c22fc9
			json_object_object_add(json_data, "auth_type",
Packit c22fc9
				json_object_new_int(0));
Packit c22fc9
#endif
Packit c22fc9
Packit c22fc9
		// Dump stats to json
Packit c22fc9
		json_object_object_add(json_stats, "advert_rcvd",
Packit c22fc9
			json_object_new_int64((int64_t)vrrp->stats->advert_rcvd));
Packit c22fc9
		json_object_object_add(json_stats, "advert_sent",
Packit c22fc9
			json_object_new_int64(vrrp->stats->advert_sent));
Packit c22fc9
		json_object_object_add(json_stats, "become_master",
Packit c22fc9
			json_object_new_int64(vrrp->stats->become_master));
Packit c22fc9
		json_object_object_add(json_stats, "release_master",
Packit c22fc9
			json_object_new_int64(vrrp->stats->release_master));
Packit c22fc9
		json_object_object_add(json_stats, "packet_len_err",
Packit c22fc9
			json_object_new_int64((int64_t)vrrp->stats->packet_len_err));
Packit c22fc9
		json_object_object_add(json_stats, "advert_interval_err",
Packit c22fc9
			json_object_new_int64((int64_t)vrrp->stats->advert_interval_err));
Packit c22fc9
		json_object_object_add(json_stats, "ip_ttl_err",
Packit c22fc9
			json_object_new_int64((int64_t)vrrp->stats->ip_ttl_err));
Packit c22fc9
		json_object_object_add(json_stats, "invalid_type_rcvd",
Packit c22fc9
			json_object_new_int64((int64_t)vrrp->stats->invalid_type_rcvd));
Packit c22fc9
		json_object_object_add(json_stats, "addr_list_err",
Packit c22fc9
			json_object_new_int64((int64_t)vrrp->stats->addr_list_err));
Packit c22fc9
		json_object_object_add(json_stats, "invalid_authtype",
Packit c22fc9
			json_object_new_int64(vrrp->stats->invalid_authtype));
Packit c22fc9
#ifdef _WITH_VRRP_AUTH_
Packit c22fc9
		json_object_object_add(json_stats, "authtype_mismatch",
Packit c22fc9
			json_object_new_int64(vrrp->stats->authtype_mismatch));
Packit c22fc9
		json_object_object_add(json_stats, "auth_failure",
Packit c22fc9
			json_object_new_int64(vrrp->stats->auth_failure));
Packit c22fc9
#endif
Packit c22fc9
		json_object_object_add(json_stats, "pri_zero_rcvd",
Packit c22fc9
			json_object_new_int64((int64_t)vrrp->stats->pri_zero_rcvd));
Packit c22fc9
		json_object_object_add(json_stats, "pri_zero_sent",
Packit c22fc9
			json_object_new_int64((int64_t)vrrp->stats->pri_zero_sent));
Packit c22fc9
Packit c22fc9
		// Add both json_data and json_stats to main instance_json
Packit c22fc9
		json_object_object_add(instance_json, "data", json_data);
Packit c22fc9
		json_object_object_add(instance_json, "stats", json_stats);
Packit c22fc9
Packit c22fc9
		// Add instance_json to main array
Packit c22fc9
		json_object_array_add(array, instance_json);
Packit c22fc9
Packit c22fc9
	}
Packit c22fc9
	fprintf(file, "%s", json_object_to_json_string(array));
Packit c22fc9
	fclose(file);
Packit c22fc9
}