Skip to content
Permalink
Branch: semtor
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
1676 lines (1232 sloc) 59.1 KB
/*
* Copyright (c) 2010 Axel Neumann
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
* License as published by the Free Software Foundation.
*
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA
*/
#define _GNU_SOURCE
#include <arpa/inet.h>
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "list.h"
#include "control.h"
#include "bmx.h"
#include "crypt.h"
#include "avl.h"
#include "node.h"
#include "key.h"
#include "sec.h"
#include "metrics.h"
#include "ogm.h"
#include "link.h"
#include "msg.h"
#include "desc.h"
#include "content.h"
#include "ip.h"
#include "hna.h"
#include "schedule.h"
#include "tools.h"
#include "iptools.h"
#include "plugin.h"
#include "allocate.h"
#include "prof.h"
#define CODE_CATEGORY_NAME "general"
int32_t my_compatibility = DEF_COMPATIBILITY;
int32_t my_conformance_tolerance = DEF_CONFORMANCE_TOLERANCE;
char my_Hostname[MAX_HOSTNAME_LEN] = "";
int32_t dad_to = DEF_DAD_TO;
uint16_t my_desc_capabilities = MY_DESC_CAPABILITIES;
const IPX_T ZERO_IP = { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } } };
const MAC_T ZERO_MAC = {{0}};
const ADDR_T ZERO_ADDR = {{0}};
const struct net_key ZERO_NET_KEY = ZERO_NET_KEY_INIT;
const struct net_key ZERO_NET4_KEY = ZERO_NET4_KEY_INIT;
const struct net_key ZERO_NET6_KEY = ZERO_NET6_KEY_INIT;
IDM_T terminating = 0;
IDM_T initializing = YES;
IDM_T cleaning_up = NO;
const IDM_T CONST_YES = YES;
const IDM_T CONST_NO = NO;
TIME_T bmx_time = 0;
TIME_SEC_T bmx_time_sec = 0;
uint32_t s_curr_avg_cpu_load = 0;
AVL_TREE(status_tree, struct status_handl, status_name);
IDM_T validate_param(int32_t probe, int32_t min, int32_t max, char *name)
{
if ( probe < min || probe > max ) {
dbgf_sys(DBGT_ERR, "Illegal %s parameter value %d ( min %d max %d )", name, probe, min, max);
return FAILURE;
}
return SUCCESS;
}
/***********************************************************
Runtime Infrastructure
************************************************************/
#ifndef NO_TRACE_FUNCTION_CALLS
static char* function_call_buffer_name_array[FUNCTION_CALL_BUFFER_SIZE] = {0};
static TIME_T function_call_buffer_time_array[FUNCTION_CALL_BUFFER_SIZE] = {0};
static uint8_t function_call_buffer_pos = 0;
static void debug_function_calls(void)
{
uint8_t i;
for (i = function_call_buffer_pos + 1; i != function_call_buffer_pos; i = ((i+1) % FUNCTION_CALL_BUFFER_SIZE)) {
if (!function_call_buffer_name_array[i])
continue;
dbgf_sys(DBGT_ERR, "%10d %s()", function_call_buffer_time_array[i], function_call_buffer_name_array[i]);
}
}
void trace_function_call(const char *func)
{
if (function_call_buffer_name_array[function_call_buffer_pos] != func) {
function_call_buffer_time_array[function_call_buffer_pos] = bmx_time;
function_call_buffer_name_array[function_call_buffer_pos] = (char*)func;
function_call_buffer_pos = ((function_call_buffer_pos+1) % FUNCTION_CALL_BUFFER_SIZE);
}
}
#endif
char *get_human_uptime(uint32_t reference)
{
// DD:HH:MM:SS
static char ut[32]="00:00:00:00";
sprintf( ut, "%i:%i%i:%i%i:%i%i",
(((bmx_time_sec-reference)/86400)),
(((bmx_time_sec-reference)%86400)/36000)%10,
(((bmx_time_sec-reference)%86400)/3600)%10,
(((bmx_time_sec-reference)%3600)/600)%10,
(((bmx_time_sec-reference)%3600)/60)%10,
(((bmx_time_sec-reference)%60)/10)%10,
(((bmx_time_sec-reference)%60))%10
);
return ut;
}
void wait_sec_msec(TIME_SEC_T sec, TIME_T msec)
{
TRACE_FUNCTION_CALL;
struct timeval time;
//no debugging here because this is called from debug_output() -> dbg_fprintf() which may case a loop!
time.tv_sec = sec + (msec/1000) ;
time.tv_usec = ( msec * 1000 ) % 1000000;
select( 0, NULL, NULL, NULL, &time );
return;
}
static void handler(int32_t sig)
{
TRACE_FUNCTION_CALL;
if ( !Client_mode ) {
dbgf_sys(DBGT_ERR, "called with signal %d", sig);
}
printf("\n");// to have a newline after ^C
terminating = YES;
}
static void segmentation_fault(int32_t sig)
{
TRACE_FUNCTION_CALL;
static int segfault = NO;
if (!segfault) {
segfault = YES;
dbg_sys(DBGT_ERR, "First SIGSEGV %d received, try cleaning up...", sig);
#ifndef NO_TRACE_FUNCTION_CALLS
debug_function_calls();
#endif
dbg(DBGL_SYS, DBGT_ERR, "Terminating with error code %d (%s-%s-rev%s)! Please notify a developer",
sig, BMX_BRANCH, BRANCH_VERSION, GIT_REV);
if (initializing) {
dbg_sys(DBGT_ERR,
"check up-to-dateness of bmx libs in default lib path %s or customized lib path defined by %s !",
BMX_DEF_LIB_PATH, BMX_ENV_LIB_PATH);
}
if (!cleaning_up)
cleanup_all(CLEANUP_RETURN);
dbg_sys(DBGT_ERR, "raising SIGSEGV again ...");
} else {
dbg(DBGL_SYS, DBGT_ERR, "Second SIGSEGV %d received, giving up! core contains second SIGSEV!", sig);
}
signal(SIGSEGV, SIG_DFL);
errno=0;
if ( raise( SIGSEGV ) ) {
dbg_sys(DBGT_ERR, "raising SIGSEGV failed: %s...", strerror(errno) );
}
}
void cleanup_all(int32_t status)
{
TRACE_FUNCTION_CALL;
if (status < 0) {
segmentation_fault(status);
}
if (!cleaning_up) {
dbgf_all(DBGT_INFO, "cleaning up (status %d)...", status);
cleaning_up = YES;
terminating = YES;
// cleanup_schedule();
// purge_link_route_orig_nodes(NULL);
keyNodes_cleanup(KCNull, NULL);
cb_plugin_hooks(PLUGIN_CB_TERM, NULL);
while (status_tree.items) {
struct status_handl *handl = avl_remove_first_item(&status_tree, -300357);
if (handl->data)
debugFree(handl->data, -300359);
debugFree(handl, -300363);
}
cleanup_plugin();
cleanup_sec();
cleanup_msg();
// cleanup_node();
cleanup_ip();
cleanup_crypt();
cleanup_config();
cleanup_prof();
// cleanup_avl();
// cleanup_tools();
cleanup_schedule();
// last, close debugging system and check for forgotten resources...
cleanup_control();
checkLeak();
if (status == CLEANUP_SUCCESS)
exit(EXIT_SUCCESS);
dbgf_all(DBGT_INFO, "...cleaning up done");
if (status == CLEANUP_RETURN)
return;
exit(EXIT_FAILURE);
}
}
/***********************************************************
Configuration data and handlers
************************************************************/
static const int32_t field_standard_sizes[FIELD_TYPE_END] = FIELD_STANDARD_SIZES;
int64_t field_get_value(const struct field_format *format, uint32_t min_msg_size, uint8_t *data, uint32_t pos_bit, uint32_t bits)
{
uint8_t host_order = format->field_host_order;
assertion(-501221, (format->field_type == FIELD_TYPE_UINT || format->field_type == FIELD_TYPE_HEX || format->field_type == FIELD_TYPE_STRING_SIZE));
assertion(-501222, (bits <= 32));
if ((bits % 8) == 0) {
assertion(-501223, (bits == 8 || bits == 16 || bits == 32));
assertion(-501168, ((pos_bit % 8) == 0));
if (bits == 8) {
return data[pos_bit / 8];
} else if (bits == 16) {
if (host_order)
return *((uint16_t*) & data[pos_bit / 8]);
else
return ntohs(*((uint16_t*) & data[pos_bit / 8]));
} else if (bits == 32) {
if (host_order)
return *((uint32_t*) & data[pos_bit / 8]);
else
return ntohl(*((uint32_t*) & data[pos_bit / 8]));
}
} else if (bits <= 16) {
uint8_t bit = 0;
uint16_t result = 0;
for (bit = 0; bit < bits; bit++) {
uint8_t val = bit_get(data, (8 * min_msg_size), (pos_bit + bit));
bit_set((uint8_t*)&result, 16, (16-bits)+bit, val);
}
return ntohs(result);
}
return FAILURE;
}
char *field_dbg_value(const struct field_format *format, uint32_t min_msg_size, uint8_t *data, uint32_t pos_bit, uint32_t bits)
{
assertion(-501200, (format && min_msg_size && data));
uint8_t field_type = format->field_type;
char *val = NULL;
void *p = (void*) (data + (pos_bit / 8));
void **pp = (void**) (data + (pos_bit / 8)); // There is problem with pointer to pointerpointer casting!!!!
uint8_t bytes = bits / 8;
if (field_type == FIELD_TYPE_UINT || field_type == FIELD_TYPE_HEX || field_type == FIELD_TYPE_STRING_SIZE || (field_type == FIELD_TYPE_INT && bits != 8 && bits != 16 && bits != 32)) {
if (bits == 0) {
val = DBG_NIL;
} else if (bits <= 32) {
static char uint32_out[ 16 ] = {0};
int64_t field_val = field_get_value(format, min_msg_size, data, pos_bit, bits);
if (format->field_type == FIELD_TYPE_HEX)
snprintf(uint32_out, sizeof (uint32_out), "%jX", field_val);
else
snprintf(uint32_out, sizeof (uint32_out), "%ji", field_val);
assertion(-501243, (strlen(uint32_out) < sizeof (uint32_out)));
val = uint32_out;
} else {
val = memAsHexString(p, bytes);
}
} else if (field_type == FIELD_TYPE_INT) {
static char int32_out[ 16 ] = {0};
val = int32_out;
if (bits == 8)
snprintf(int32_out, sizeof (int32_out), "%d", *((int8_t*) p));
else if (bits == 16)
snprintf(int32_out, sizeof (int32_out), "%d", *((int16_t*) p));
else if (bits == 32)
snprintf(int32_out, sizeof (int32_out), "%d", *((int32_t*) p));
else
val = DBG_NIL;
} else if (field_type == FIELD_TYPE_FLOAT) {
static char float_out[ 32 ] = {0};
val = float_out;
if (bits == (8*sizeof(float)))
snprintf(float_out, sizeof (float_out), "%.2f", *((float*) p));
else
val = DBG_NIL;
} else if (field_type == FIELD_TYPE_IP4) {
val = ip4AsStr(*((IP4_T*) p));
} else if (field_type == FIELD_TYPE_IPX4) {
val = ipXAsStr(AF_INET, (IPX_T*) p);
} else if (field_type == FIELD_TYPE_IPX6) {
val = ip6AsStr((IPX_T*) p);
} else if (field_type == FIELD_TYPE_IPX) {
val = ip6AsStr((IPX_T*) p);
} else if (field_type == FIELD_TYPE_NETP) {
val = *pp ? netAsStr(*((struct net_key**) pp)) : DBG_NIL;
} else if (field_type == FIELD_TYPE_MAC) {
val = macAsStr((MAC_T*) p);
} else if (field_type == FIELD_TYPE_STRING_BINARY) {
val = memAsHexString(p, bytes);
} else if (field_type == FIELD_TYPE_STRING_CHAR) {
val = memAsCharString((char*)p, bytes);
} else if (field_type == FIELD_TYPE_GLOBAL_ID) {
val = cryptShaAsString(((SHA1_T*) p));
} else if (field_type == FIELD_TYPE_UMETRIC) {
val = umetric_to_human(*((UMETRIC_T*) p));
} else if (field_type == FIELD_TYPE_FMETRIC8) {
val = umetric_to_human(fmetric_u8_to_umetric(*((FMETRIC_U8_T*) p)));
} else if (field_type == FIELD_TYPE_IPX6P) {
val = *pp ? ip6AsStr(*((IPX_T**) pp)) : DBG_NIL;
} else if (field_type == FIELD_TYPE_POINTER_CHAR) {
val = *pp ? memAsCharString(*((char**) pp), strlen(*((char**) pp))) : DBG_NIL;
} else if (field_type == FIELD_TYPE_POINTER_GLOBAL_ID) {
val = *pp ? cryptShaAsString(*((SHA1_T**)pp)) : DBG_NIL;
} else if (field_type == FIELD_TYPE_POINTER_SHORT_ID) {
val = *pp ? cryptShaAsShortStr(*((SHA1_T**)pp)) : DBG_NIL;
} else if (field_type == FIELD_TYPE_POINTER_UMETRIC) {
val = *pp ? umetric_to_human(**((UMETRIC_T**) pp)) : DBG_NIL;
} else {
assertion(-501202, 0);
}
return val ? val : "ERROR";
}
uint32_t field_iterate(struct field_iterator *it)
{
TRACE_FUNCTION_CALL;
assertion(-501171, IMPLIES(it->data_size, it->data));
const struct field_format *format;
it->field = (it->field_bits || it->field) ? (it->field + 1) : 0;
format = &(it->format[it->field]);
if (format->field_type == FIELD_TYPE_END) {
it->field = 0;
it->msg_bit_pos += ((it->min_msg_size * 8) + it->var_bits);
it->var_bits = 0;
format = &(it->format[0]);
}
it->field_bit_pos = (format->field_pos == -1) ?
it->field_bit_pos + it->field_bits : it->msg_bit_pos + format->field_pos;
if (!format->field_bits && !it->var_bits)
it->var_bits = it->data_size ? ((8*it->data_size)-it->field_bit_pos) : 0;
uint8_t field_type = format->field_type;
uint32_t field_bits = format->field_bits ? format->field_bits : it->var_bits;
int32_t std_bits = field_standard_sizes[field_type];
dbgf_all(DBGT_INFO,
"fmt.field_name=%s data_size_bits=%d min_msg_size_bits=%d msg_bit_pos=%d data=%p "
"it.field=%d it.field_bits=%d it.field_bit_pos=%d it.var_bits=%d field_bits=%d "
"fmt.field_type=%d fmt.field_bits=%d std_bits=%d",
format->field_name, (8 * it->data_size), (8 * it->min_msg_size), it->msg_bit_pos, it->data,
it->field, it->field_bits, it->field_bit_pos, it->var_bits, field_bits,
field_type, format->field_bits, std_bits);
if (it->msg_bit_pos + (it->min_msg_size * 8) + it->var_bits <=
8 * (it->data_size ? it->data_size : it->min_msg_size)) {
//printf("msg_name=%s field_name=%s\n", handl->name, format->msg_field_name);
assertion(-501172, IMPLIES(field_type == FIELD_TYPE_STRING_SIZE, !it->var_bits));
assertion(-501203, IMPLIES(field_type == FIELD_TYPE_UINT, (field_bits <= 16 || field_bits == 32)));
assertion(-501204, IMPLIES(field_type == FIELD_TYPE_HEX, (field_bits <= 16 || field_bits == 32)));
assertion(-501205, IMPLIES(field_type == FIELD_TYPE_STRING_SIZE, (field_bits <= 16 || field_bits == 32)));
// assertion(-501186, IMPLIES(it->fixed_msg_size && it->data_size, it->data_size % it->fixed_msg_size == 0));
// assertion(-501187, IMPLIES(it->fixed_msg_size, field_type != FIELD_TYPE_STRING_SIZE || !format->field_bits));
// assertion(-501188, IMPLIES(!format->field_bits && it->data_size, it->var_bits));
assertion(-501189, IMPLIES(!format->field_bits, field_type == FIELD_TYPE_STRING_CHAR || field_type == FIELD_TYPE_STRING_BINARY));
assertion(-501173, IMPLIES(field_bits == 0, format[1].field_type == FIELD_TYPE_END));
assertion(-501174, (std_bits != 0));
assertion(-501175, IMPLIES(std_bits > 0, (field_bits == (uint32_t) std_bits)));
assertion(-501176, IMPLIES(std_bits < 0, !(field_bits % (-std_bits))));
// assertion(-501206, IMPLIES(field_bits >= 8, !(field_bits % 8)));
// assertion(-501177, IMPLIES((field_bits % 8), field_bits < 8));
// assertion(-501178, IMPLIES(!(field_bits % 8), !(it->field_bit_pos % 8)));
// assertion(-501182, (it->min_msg_size * 8 >= it->field_bit_pos + field_bits));
assertion(-501183, IMPLIES(it->data_size, it->min_msg_size <= it->data_size));
// assertion(-501184, IMPLIES(it->data_size, field_bits));
assertion(-501185, IMPLIES(it->data_size, it->field_bit_pos + field_bits <= it->data_size * 8));
// assertion(-501190, IMPLIES(!format->field_host_order, (field_bits == 16 || field_bits == 32)));
// assertion(-501191, IMPLIES(!format->field_host_order, (field_type == FIELD_TYPE_UINT || field_type == FIELD_TYPE_HEX || field_type == FIELD_TYPE_STRING_SIZE)));
assertion(-501192, IMPLIES((field_type == FIELD_TYPE_UINT || field_type == FIELD_TYPE_HEX || field_type == FIELD_TYPE_STRING_SIZE), field_bits <= 32));
if (it->data_size) {
if (field_type == FIELD_TYPE_STRING_SIZE) {
int64_t var_bytes = field_get_value(format, it->min_msg_size, it->data, it->field_bit_pos, field_bits);
assertion(-501207, (var_bytes >= SUCCESS));
it->var_bits = 8 * var_bytes;
}
//msg_field_dbg(it->handl, it->field, it->data, it->pos_bit, field_bits, cn);
}
it->field_bits = field_bits;
//dbgf_all(DBGT_INFO,
return SUCCESS;
}
assertion(-501163, IMPLIES(!it->data_size, (it->field_bit_pos % (it->min_msg_size * 8) == 0)));
assertion(-501164, IMPLIES(it->data_size, it->data_size * 8 == it->field_bit_pos));
assertion(-501208, ((it->field_bit_pos % 8) == 0));
// return (it->msg_bit_pos / 8);
return (it->field_bit_pos / 8);
}
int16_t field_format_get_items(const struct field_format *format) {
int16_t i=-1;
while (format[++i].field_type != FIELD_TYPE_END) {
assertion(-501244, (i < FIELD_FORMAT_MAX_ITEMS));
}
return i;
}
uint32_t fields_dbg_lines(struct ctrl_node *cn, uint16_t relevance, uint32_t data_size, uint8_t *data,
uint32_t min_msg_size, const struct field_format *format)
{
TRACE_FUNCTION_CALL;
assertion(-501209, format);
uint32_t msgs_size = 0;
struct field_iterator it = {.format = format, .data = data, .data_size = data_size, .min_msg_size = min_msg_size};
while ((msgs_size = field_iterate(&it)) == SUCCESS) {
if (data) {
if (cn && it.field == 0)
dbg_printf(cn, "\n ");
if (format[it.field].field_relevance >= relevance) {
if (cn) {
dbg_printf(cn, " %s=%s", format[it.field].field_name,
field_dbg_value(&format[it.field], min_msg_size, data, it.field_bit_pos, it.field_bits));
} else {
dbgf_track(DBGT_INFO, " %s=%s", format[it.field].field_name,
field_dbg_value(&format[it.field], min_msg_size, data, it.field_bit_pos, it.field_bits));
}
}
/*
if (format[it.field + 1].field_type == FIELD_TYPE_END)
dbg_printf(cn, "\n");
*/
}
}
assertion(-501210, (data_size ? msgs_size == data_size : msgs_size == min_msg_size));
return msgs_size;
}
void fields_dbg_table(struct ctrl_node *cn, uint16_t relevance, uint32_t data_size, uint8_t *data,
uint32_t min_msg_size, const struct field_format *format)
{
TRACE_FUNCTION_CALL;
assertion(-501255, (format && data && cn));
uint16_t field_string_sizes[FIELD_FORMAT_MAX_ITEMS] = {0};
uint32_t columns = field_format_get_items(format);
uint32_t rows = 1/*the headline*/, bytes_per_row = 1/*the trailing '\n' or '\0'*/;
assertion(-501256, (columns && columns <= FIELD_FORMAT_MAX_ITEMS));
struct field_iterator i1 = {.format = format, .data = data, .data_size = data_size, .min_msg_size = min_msg_size};
while (field_iterate(&i1) == SUCCESS) {
if (format[i1.field].field_relevance >= relevance) {
char *val = field_dbg_value(&format[i1.field], min_msg_size, data, i1.field_bit_pos, i1.field_bits);
field_string_sizes[i1.field] = max_i32(field_string_sizes[i1.field], strlen(val));
if (i1.field == 0) {
rows++;
bytes_per_row = 1;
}
if (rows == 2) {
field_string_sizes[i1.field] =
max_i32(field_string_sizes[i1.field], strlen(format[i1.field].field_name));
}
bytes_per_row += field_string_sizes[i1.field] + 1/* the separating ' '*/;
}
}
char * out = debugMalloc(((rows * bytes_per_row) + 1), -300383);
memset(out, ' ', (rows * bytes_per_row));
uint32_t i = 0, pos = 0;
for (i = 0; i < columns; i++) {
if (format[i].field_relevance >= relevance) {
memcpy(&out[pos], format[i].field_name, strlen(format[i].field_name));
pos += field_string_sizes[i] + 1;
//dbg_printf(cn, "%s", format[i].field_name);
//dbg_spaces(cn, field_string_sizes[i] - strlen(format[i].field_name) + (i == columns - 1 ? 0 : 1));
}
if (i == columns - 1) {
out[pos++] = '\n';
//dbg_printf(cn, "\n");
}
}
struct field_iterator i2 = {.format = format, .data = data, .data_size = data_size, .min_msg_size = min_msg_size};
while(field_iterate(&i2) == SUCCESS) {
if (format[i2.field].field_relevance >= relevance) {
char *val = field_dbg_value(&format[i2.field], min_msg_size, data, i2.field_bit_pos, i2.field_bits);
memcpy(&out[pos], val, strlen(val));
pos += field_string_sizes[i2.field]+ (i2.field == columns - 1 ? 0 : 1);
//dbg_spaces(cn, field_string_sizes[i2.field] - strlen(val));
//dbg_printf(cn, "%s%s", val, (i2.field == columns - 1 ? "" : " "));
}
if (i2.field == columns - 1) {
out[pos++] = '\n';
//dbg_printf(cn, "\n");
}
}
out[pos++] = '\0';
dbg_printf(cn, "%s", out);
debugFree(out, -300384);
}
void register_status_handl(uint16_t min_msg_size, IDM_T multiline, const struct field_format* format, char *name,
int32_t(*creator) (struct status_handl *status_handl, void *data))
{
struct status_handl *handl = debugMallocReset(sizeof (struct status_handl), -300364);
handl->multiline = multiline;
handl->min_msg_size = min_msg_size;
handl->format = format;
strcpy(handl->status_name, name);
handl->frame_creator = creator;
assertion(-501224, !avl_find(&status_tree, &handl->status_name));
avl_insert(&status_tree, (void*) handl, -300357);
}
struct bmx_status {
GLOBAL_ID_T *shortId;
GLOBAL_ID_T *nodeId;
char* name;
char *nodeKey;
char *linkKey;
DHASH_T *shortDhash;
DHASH_T *dhash;
char version[(sizeof(BMX_BRANCH) - 1) + (sizeof("-") - 1) + (sizeof(BRANCH_VERSION) - 1) + 1];
uint16_t compat;
char revision[9];
IPX_T primaryIp;
struct net_key *tun6Address;
struct net_key *tun4Address;
DESC_SQN_T descSqn;
uint32_t lastDesc;
OGM_SQN_T ogmSqn;
char *uptime;
char cpu[6];
char mem[22];
char rxBpP[12];
char txBpP[12];
char txQ[12];
uint32_t nbs;
char nodes[24];
char contents[16];
};
static const struct field_format bmx_status_format[] = {
FIELD_FORMAT_INIT(FIELD_TYPE_POINTER_SHORT_ID, bmx_status, shortId, 1, FIELD_RELEVANCE_HIGH),
FIELD_FORMAT_INIT(FIELD_TYPE_POINTER_GLOBAL_ID, bmx_status, nodeId, 1, FIELD_RELEVANCE_MEDI),
FIELD_FORMAT_INIT(FIELD_TYPE_POINTER_CHAR, bmx_status, name, 1, FIELD_RELEVANCE_HIGH),
FIELD_FORMAT_INIT(FIELD_TYPE_POINTER_CHAR, bmx_status, nodeKey, 1, FIELD_RELEVANCE_HIGH),
FIELD_FORMAT_INIT(FIELD_TYPE_POINTER_CHAR, bmx_status, linkKey, 1, FIELD_RELEVANCE_HIGH),
FIELD_FORMAT_INIT(FIELD_TYPE_POINTER_SHORT_ID, bmx_status, shortDhash, 1, FIELD_RELEVANCE_MEDI),
FIELD_FORMAT_INIT(FIELD_TYPE_POINTER_GLOBAL_ID, bmx_status, dhash, 1, FIELD_RELEVANCE_MEDI),
FIELD_FORMAT_INIT(FIELD_TYPE_STRING_CHAR, bmx_status, version, 1, FIELD_RELEVANCE_MEDI),
FIELD_FORMAT_INIT(FIELD_TYPE_UINT, bmx_status, compat, 1, FIELD_RELEVANCE_MEDI),
FIELD_FORMAT_INIT(FIELD_TYPE_STRING_CHAR, bmx_status, revision, 1, FIELD_RELEVANCE_HIGH),
FIELD_FORMAT_INIT(FIELD_TYPE_IPX, bmx_status, primaryIp, 1, FIELD_RELEVANCE_HIGH),
FIELD_FORMAT_INIT(FIELD_TYPE_NETP, bmx_status, tun6Address, 1, FIELD_RELEVANCE_HIGH),
FIELD_FORMAT_INIT(FIELD_TYPE_NETP, bmx_status, tun4Address, 1, FIELD_RELEVANCE_HIGH),
FIELD_FORMAT_INIT(FIELD_TYPE_UINT, bmx_status, descSqn, 1, FIELD_RELEVANCE_HIGH),
FIELD_FORMAT_INIT(FIELD_TYPE_UINT, bmx_status, lastDesc, 1, FIELD_RELEVANCE_HIGH),
FIELD_FORMAT_INIT(FIELD_TYPE_UINT, bmx_status, ogmSqn, 1, FIELD_RELEVANCE_MEDI),
FIELD_FORMAT_INIT(FIELD_TYPE_POINTER_CHAR, bmx_status, uptime, 1, FIELD_RELEVANCE_HIGH),
FIELD_FORMAT_INIT(FIELD_TYPE_STRING_CHAR, bmx_status, cpu, 1, FIELD_RELEVANCE_HIGH),
FIELD_FORMAT_INIT(FIELD_TYPE_STRING_CHAR, bmx_status, mem, 1, FIELD_RELEVANCE_HIGH),
FIELD_FORMAT_INIT(FIELD_TYPE_STRING_CHAR, bmx_status, txQ, 1, FIELD_RELEVANCE_HIGH),
FIELD_FORMAT_INIT(FIELD_TYPE_STRING_CHAR, bmx_status, rxBpP, 1, FIELD_RELEVANCE_HIGH),
FIELD_FORMAT_INIT(FIELD_TYPE_STRING_CHAR, bmx_status, txBpP, 1, FIELD_RELEVANCE_HIGH),
FIELD_FORMAT_INIT(FIELD_TYPE_UINT, bmx_status, nbs, 1, FIELD_RELEVANCE_HIGH),
FIELD_FORMAT_INIT(FIELD_TYPE_STRING_CHAR, bmx_status, nodes, 1, FIELD_RELEVANCE_HIGH),
FIELD_FORMAT_INIT(FIELD_TYPE_STRING_CHAR, bmx_status, contents, 1, FIELD_RELEVANCE_HIGH),
FIELD_FORMAT_END
};
static int32_t bmx_status_creator(struct status_handl *handl, void *data)
{
struct tun_in_node *tin = avl_first_item(&tun_in_tree);
struct bmx_status *status = (struct bmx_status *) (handl->data = debugRealloc(handl->data, sizeof(struct bmx_status), -300365));
struct dsc_msg_pubkey *pkm;
status->nodeId = &myKey->kHash;
status->shortId = &myKey->kHash;
status->name = my_Hostname;
status->shortDhash = &myKey->on->dc->dHash;
status->dhash = &myKey->on->dc->dHash;
status->nodeKey = (pkm = contents_data(myKey->on->dc, BMX_DSC_TLV_NODE_PUBKEY)) ? cryptKeyTypeAsString(pkm->type) : DBG_NIL;
status->linkKey = (pkm = contents_data(myKey->on->dc, BMX_DSC_TLV_LINK_PUBKEY)) ? cryptKeyTypeAsString(pkm->type) : DBG_NIL;
snprintf(status->version, sizeof(status->version), "%s-%s", BMX_BRANCH, BRANCH_VERSION);
status->compat = my_compatibility;
snprintf(status->revision, 8, "%s", GIT_REV);
status->primaryIp = my_primary_ip;
status->tun4Address = tin ? &tin->tunAddr46[1] : NULL;
status->tun6Address = tin ? &tin->tunAddr46[0] : NULL;
status->descSqn = myKey->on->dc->descSqn;
status->lastDesc = (bmx_time - myKey->on->updated_timestamp) / 1000;
status->ogmSqn = myKey->on->dc->ogmSqnMaxSend;
status->uptime = get_human_uptime(0);
snprintf(status->cpu, sizeof(status->cpu), "%d.%1d", s_curr_avg_cpu_load / 10, s_curr_avg_cpu_load % 10);
snprintf(status->mem, sizeof(status->mem), "%dK/%d", debugMalloc_bytes / 1000, debugMalloc_objects);
snprintf(status->rxBpP, sizeof(status->rxBpP), "%d/%.1f", (udpRxBytesMean / DEVSTAT_PRECISION), (((float) udpRxPacketsMean) / DEVSTAT_PRECISION));
snprintf(status->txBpP, sizeof(status->txBpP), "%d/%.1f", (udpTxBytesMean / DEVSTAT_PRECISION), (((float) udpTxPacketsMean) / DEVSTAT_PRECISION));
snprintf(status->txQ, sizeof(status->txQ), "%d/%d", txBucket / BUCKET_COIN_SCALE, txBucketSize);
status->nbs = local_tree.items;
snprintf(status->nodes, sizeof(status->nodes), "%d/%d/%d", orig_tree.items, key_tree.items, descContent_tree.items);
snprintf(status->contents, sizeof(status->contents), "%d/%d", (content_tree.items - content_tree_unresolveds), content_tree.items);
return sizeof(struct bmx_status);
}
struct orig_status {
GLOBAL_ID_T *shortId;
GLOBAL_ID_T *nodeId;
char* name;
char *assessedState;
char *as;
uint16_t pref;
TIME_T brcTo;
TIME_T signTo;
TIME_T tAPTo;
TIME_T nQTo;
uint16_t friend;
uint16_t recom;
uint16_t trustees;
char S[2]; // supported by me
char s[2]; // me supported by him
char T[2]; // trusted by me;
char t[2]; // me trusted by him
char *nodeKey;
CRYPTSHA1_T *shortDHash;
CRYPTSHA1_T *dHash;
IID_T myIid;
DESC_SQN_T descSqn;
DESC_SQN_T descSqnMin;
DESC_SQN_T descSqnNext;
uint32_t lastDesc;
char descSize[20];
char contents[12]; //contentRefs
char *linkKey;
IPX_T primaryIp;
char *dev;
uint32_t nbIdx;
uint32_t myIdx;
IPX_T nbLocalIp;
char* nbName;
UMETRIC_T metric;
char ogmHist[10 + (MAX_OGM_HOP_HISTORY_SZ * 8)];
uint8_t hops;
OGM_SQN_T ogmSqn;
IID_T nbIid;
uint16_t lastRef;
char nbs[12]; //neighRefs
};
static const struct field_format orig_status_format[] = {
FIELD_FORMAT_INIT(FIELD_TYPE_POINTER_SHORT_ID, orig_status, shortId, 1, FIELD_RELEVANCE_HIGH),
FIELD_FORMAT_INIT(FIELD_TYPE_POINTER_GLOBAL_ID, orig_status, nodeId, 1, FIELD_RELEVANCE_MEDI),
FIELD_FORMAT_INIT(FIELD_TYPE_POINTER_CHAR, orig_status, name, 1, FIELD_RELEVANCE_HIGH),
FIELD_FORMAT_INIT(FIELD_TYPE_POINTER_CHAR, orig_status, assessedState, 1, FIELD_RELEVANCE_LOW),
FIELD_FORMAT_INIT(FIELD_TYPE_POINTER_CHAR, orig_status, as, 1, FIELD_RELEVANCE_HIGH),
FIELD_FORMAT_INIT(FIELD_TYPE_UINT, orig_status, pref, 1, FIELD_RELEVANCE_MEDI),
FIELD_FORMAT_INIT(FIELD_TYPE_UINT, orig_status, brcTo, 1, FIELD_RELEVANCE_MEDI),
FIELD_FORMAT_INIT(FIELD_TYPE_UINT, orig_status, signTo, 1, FIELD_RELEVANCE_MEDI),
FIELD_FORMAT_INIT(FIELD_TYPE_UINT, orig_status, tAPTo, 1, FIELD_RELEVANCE_MEDI),
FIELD_FORMAT_INIT(FIELD_TYPE_UINT, orig_status, nQTo, 1, FIELD_RELEVANCE_MEDI),
FIELD_FORMAT_INIT(FIELD_TYPE_UINT, orig_status, friend, 1, FIELD_RELEVANCE_MEDI),
FIELD_FORMAT_INIT(FIELD_TYPE_UINT, orig_status, recom, 1, FIELD_RELEVANCE_MEDI),
FIELD_FORMAT_INIT(FIELD_TYPE_UINT, orig_status, trustees, 1, FIELD_RELEVANCE_MEDI),
FIELD_FORMAT_INIT(FIELD_TYPE_STRING_CHAR, orig_status, S, 1, FIELD_RELEVANCE_HIGH),
FIELD_FORMAT_INIT(FIELD_TYPE_STRING_CHAR, orig_status, s, 1, FIELD_RELEVANCE_HIGH),
FIELD_FORMAT_INIT(FIELD_TYPE_STRING_CHAR, orig_status, T, 1, FIELD_RELEVANCE_HIGH),
FIELD_FORMAT_INIT(FIELD_TYPE_STRING_CHAR, orig_status, t, 1, FIELD_RELEVANCE_HIGH),
FIELD_FORMAT_INIT(FIELD_TYPE_POINTER_CHAR, orig_status, nodeKey, 1, FIELD_RELEVANCE_HIGH),
FIELD_FORMAT_INIT(FIELD_TYPE_UINT, orig_status, myIid, 1, FIELD_RELEVANCE_MEDI),
FIELD_FORMAT_INIT(FIELD_TYPE_POINTER_SHORT_ID, orig_status, shortDHash, 1, FIELD_RELEVANCE_MEDI),
FIELD_FORMAT_INIT(FIELD_TYPE_POINTER_GLOBAL_ID, orig_status, dHash, 1, FIELD_RELEVANCE_LOW),
FIELD_FORMAT_INIT(FIELD_TYPE_UINT, orig_status, descSqn, 1, FIELD_RELEVANCE_HIGH),
FIELD_FORMAT_INIT(FIELD_TYPE_UINT, orig_status, descSqnMin, 1, FIELD_RELEVANCE_MEDI),
FIELD_FORMAT_INIT(FIELD_TYPE_UINT, orig_status, descSqnNext, 1, FIELD_RELEVANCE_LOW),
FIELD_FORMAT_INIT(FIELD_TYPE_UINT, orig_status, lastDesc, 1, FIELD_RELEVANCE_HIGH),
FIELD_FORMAT_INIT(FIELD_TYPE_STRING_CHAR, orig_status, descSize, 1, FIELD_RELEVANCE_HIGH),
FIELD_FORMAT_INIT(FIELD_TYPE_STRING_CHAR, orig_status, contents, 1, FIELD_RELEVANCE_MEDI),
FIELD_FORMAT_INIT(FIELD_TYPE_POINTER_CHAR, orig_status, linkKey, 1, FIELD_RELEVANCE_LOW),
FIELD_FORMAT_INIT(FIELD_TYPE_IPX, orig_status, primaryIp, 1, FIELD_RELEVANCE_HIGH),
FIELD_FORMAT_INIT(FIELD_TYPE_POINTER_CHAR, orig_status, dev, 1, FIELD_RELEVANCE_HIGH),
FIELD_FORMAT_INIT(FIELD_TYPE_UINT, orig_status, myIdx, 1, FIELD_RELEVANCE_MEDI),
FIELD_FORMAT_INIT(FIELD_TYPE_UINT, orig_status, nbIdx, 1, FIELD_RELEVANCE_MEDI),
FIELD_FORMAT_INIT(FIELD_TYPE_IPX, orig_status, nbLocalIp, 1, FIELD_RELEVANCE_HIGH),
FIELD_FORMAT_INIT(FIELD_TYPE_POINTER_CHAR, orig_status, nbName, 1, FIELD_RELEVANCE_HIGH),
FIELD_FORMAT_INIT(FIELD_TYPE_UMETRIC, orig_status, metric, 1, FIELD_RELEVANCE_HIGH),
FIELD_FORMAT_INIT(FIELD_TYPE_STRING_CHAR, orig_status, ogmHist, 1, FIELD_RELEVANCE_HIGH),
FIELD_FORMAT_INIT(FIELD_TYPE_UINT, orig_status, hops, 1, FIELD_RELEVANCE_HIGH),
FIELD_FORMAT_INIT(FIELD_TYPE_UINT, orig_status, ogmSqn, 1, FIELD_RELEVANCE_HIGH),
FIELD_FORMAT_INIT(FIELD_TYPE_UINT, orig_status, nbIid, 1, FIELD_RELEVANCE_MEDI),
FIELD_FORMAT_INIT(FIELD_TYPE_UINT, orig_status, lastRef, 1, FIELD_RELEVANCE_HIGH),
FIELD_FORMAT_INIT(FIELD_TYPE_STRING_CHAR, orig_status, nbs, 1, FIELD_RELEVANCE_MEDI),
FIELD_FORMAT_END
};
STATIC_FUNC
uint8_t *key_status_page(uint8_t *sOut, uint32_t i, struct orig_node *on, struct desc_content *dc, struct key_node *kn)
{
assertion(-502237, (!!on + !!dc + !!kn == 1));
assertion(-502239, IMPLIES(kn, !kn->on && !kn->nextDesc));
assertion(-502240, IMPLIES(dc, !dc->on));
IDM_T S, s, T, t;
struct dsc_msg_pubkey *pkm;
struct orig_status *os = &(((struct orig_status*) (sOut = debugRealloc(sOut, ((i + 1) * sizeof(struct orig_status)), -300366)))[i]);
memset(os, 0, sizeof(struct orig_status));
dc = on ? on->dc : dc;
kn = dc ? dc->kn : kn;
if (kn) {
os->shortId = &kn->kHash;
os->nodeId = &kn->kHash;
os->assessedState = kn->bookedState->secName;
os->as = kn->bookedState->secAcro;
os->pref = (*(kn->bookedState->prefGet))(kn);
os->brcTo = kn->pktIdTime ? (((TIME_T) (link_purge_to - (bmx_time - kn->pktIdTime))) / 1000) : 0;
os->signTo = kn->pktSignTime ? (((TIME_T) (link_purge_to - (bmx_time - kn->pktSignTime))) / 1000) : 0;
os->tAPTo = kn->TAPTime ? (((TIME_T) (tracked_timeout - (bmx_time - kn->TAPTime))) / 1000) : 0;
os->nQTo = kn->nQTime ? (((TIME_T) (neigh_qualifying_to - (bmx_time - kn->nQTime))) / 1000) : 0;
os->friend = kn->dFriend;
os->recom = kn->recommendations_tree.items;
os->trustees = kn->trustees_tree.items;
os->S[0] = (S = supportedKnownKey(&kn->kHash)) == -1 ? 'A' : (S + '0');
os->T[0] = (T = setted_pubkey(myKey->on->dc, BMX_DSC_TLV_TRUSTS, &kn->kHash, 0)) == -1 ? 'A' : (T + '0');
os->descSqnMin = kn->descSqnMin;
os->descSqnNext = kn->nextDesc ? kn->nextDesc->descSqn : 0;
os->nodeKey = (kn->content && (kn->content->f_body_len >= sizeof(struct dsc_msg_pubkey))) ?
cryptKeyTypeAsString(((struct dsc_msg_pubkey*) kn->content->f_body)->type) : DBG_NIL;
} else {
os->S[0] = '-';
os->T[0] = '-';
}
if (dc) {
os->s[0] = (s = setted_pubkey(dc, BMX_DSC_TLV_SUPPORTS, &myKey->kHash, 0)) == -1 ? 'A' : (s + '0');
os->t[0] = (t = setted_pubkey(dc, BMX_DSC_TLV_TRUSTS, &myKey->kHash, 0)) == -1 ? 'A' : (t + '0');
os->descSqn = dc->descSqn;
snprintf(os->descSize, (sizeof(os->descSize)-1), "%d+%d", dc->desc_frame_len, dc->ref_content_len);
snprintf(os->contents, (sizeof(os->contents)-1), "%d/%d", (dc->contentRefs_tree.items - dc->unresolvedContentCounter), dc->contentRefs_tree.items);
os->dHash = &dc->dHash;
os->shortDHash = &dc->dHash;
os->lastRef = (bmx_time - dc->referred_by_others_timestamp) / 1000;
} else {
os->s[0] = '-';
os->t[0] = '-';
snprintf(os->contents, (sizeof(os->contents)-1), "---");
}
if (on) {
os->linkKey = (pkm = contents_data(dc, BMX_DSC_TLV_LINK_PUBKEY)) ? cryptKeyTypeAsString(pkm->type) : DBG_NIL;
os->name = on->k.hostname;
os->primaryIp = on->primary_ip;
os->dev = on->neighPath.link && on->neighPath.link->k.myDev ? on->neighPath.link->k.myDev->ifname_device.str : DBG_NIL;
os->myIdx = on->neighPath.link && on->neighPath.link->k.myDev ? on->neighPath.link->k.myDev->llipKey.devIdx : 0;
os->nbIdx = (on->neighPath.link ? on->neighPath.link->k.linkDev->key.devIdx : 0);
os->nbLocalIp = (on->neighPath.link ? on->neighPath.link->k.linkDev->key.llocal_ip : ZERO_IP);
os->nbName = (on->neighPath.link ? on->neighPath.link->k.linkDev->key.local->on->k.hostname : DBG_NIL);
os->metric = on->neighPath.um;
snprintf(os->ogmHist, (sizeof(os->ogmHist)-1), "%d/%d", (int)(on->neighPath.pathMetricsByteSize / sizeof(struct msg_ogm_adv_metric_t0)), on->mtcAlgo->ogm_hop_history);
uint16_t i;
for (i = 0; i < (on->neighPath.pathMetricsByteSize / sizeof(struct msg_ogm_adv_metric_t0)); i++) {
FMETRIC_U16_T fm = {.val = {.f = {.exp_fm16 = on->neighPath.pathMetrics[i].u.f.metric_exp, .mantissa_fm16 = on->neighPath.pathMetrics[i].u.f.metric_mantissa}}};
snprintf((os->ogmHist + strlen(os->ogmHist)), (sizeof(os->ogmHist) - (1 + strlen(os->ogmHist))), "%s%s%s",
(i ? "" : ":"), umetric_to_human(fmetric_to_umetric(fm)), ((i + 1)<(on->neighPath.pathMetricsByteSize / (uint16_t)sizeof(struct msg_ogm_adv_metric_t0)) ? "," : ""));
}
os->hops = on->ogmHopCount;
os->ogmSqn = on->dc->ogmSqnMaxSend;
os->lastDesc = (bmx_time - on->updated_timestamp) / 1000;
os->myIid = iid_get_myIID4x_by_node(on);
struct NeighRef_node *nref = on->neighPath.link ? avl_find_item(&kn->neighRefs_tree, &on->neighPath.link->k.linkDev->key.local) : NULL;
os->nbIid = nref ? iid_get_neighIID4x_by_node(nref) : 0;
}
snprintf(os->nbs, (sizeof(os->nbs)-1), "%d", (kn ? kn->neighRefs_tree.items : 0));
return sOut;
}
static int32_t origs_status_creator(struct status_handl *handl, void *data)
{
uint32_t i = 0;
if (data) {
struct key_node *kn = data;
handl->data = key_status_page(handl->data, 0, kn->on, (!kn->on ? kn->nextDesc : NULL), ((!kn->on && !kn->nextDesc) ? kn : NULL));
} else {
struct avl_node *it;
struct orig_node *on;
AVL_TREE(orig_name_tree, struct orig_node, k);
for (it = NULL; (on = avl_iterate_item(&orig_tree, &it));)
avl_insert(&orig_name_tree, on, -300744);
while ((on = avl_remove_first_item(&orig_name_tree, -300745)))
handl->data = key_status_page(handl->data, i++, on, NULL, NULL);
}
return((i) * sizeof(struct orig_status));
}
static int32_t keys_status_creator(struct status_handl *handl, void *data)
{
uint32_t i = 0;
if (data) {
struct key_node *kn = data;
handl->data = key_status_page(handl->data, 0, kn->on, (!kn->on ? kn->nextDesc : NULL), ((!kn->on && !kn->nextDesc) ? kn : NULL));
} else {
struct avl_node *it;
struct key_node *kn;
struct orig_node *on;
AVL_TREE(orig_name_tree, struct orig_node, k);
for (it = NULL; (on = avl_iterate_item(&orig_tree, &it));)
avl_insert(&orig_name_tree, on, -300744);
while ((on = avl_remove_first_item(&orig_name_tree, -300745)))
handl->data = key_status_page(handl->data, i++, on, NULL, NULL);
for (it = NULL; (kn = avl_iterate_item(&key_tree, &it));) {
if (kn->nextDesc)
handl->data = key_status_page(handl->data, i++, NULL, kn->nextDesc, NULL);
if (!kn->on && !kn->nextDesc)
handl->data = key_status_page(handl->data, i++, NULL, NULL, kn);
}
}
return((i) * sizeof(struct orig_status));
}
struct ref_status {
GLOBAL_ID_T *shortId;
GLOBAL_ID_T *nodeId;
char* name;
char *state;
DESC_SQN_T descSqn;
char contents[12]; //contentRefs
uint16_t lastDesc;
CRYPTSHA1_T *shortDHash;
CRYPTSHA1_T *dHash;
uint16_t lastRef;
char nbs[12]; //neighRefs
GLOBAL_ID_T *nbId;
char* nbName;
uint32_t rootLen;
uint32_t virtLen;
uint32_t unresolveds;
};
static const struct field_format ref_status_format[] = {
FIELD_FORMAT_INIT(FIELD_TYPE_POINTER_SHORT_ID, ref_status, shortId, 1, FIELD_RELEVANCE_HIGH),
FIELD_FORMAT_INIT(FIELD_TYPE_POINTER_GLOBAL_ID, ref_status, nodeId, 1, FIELD_RELEVANCE_MEDI),
FIELD_FORMAT_INIT(FIELD_TYPE_POINTER_CHAR, ref_status, name, 1, FIELD_RELEVANCE_HIGH),
FIELD_FORMAT_INIT(FIELD_TYPE_POINTER_CHAR, ref_status, state, 1, FIELD_RELEVANCE_HIGH),
FIELD_FORMAT_INIT(FIELD_TYPE_UINT, ref_status, descSqn, 1, FIELD_RELEVANCE_HIGH),
FIELD_FORMAT_INIT(FIELD_TYPE_STRING_CHAR, ref_status, contents, 1, FIELD_RELEVANCE_HIGH),
FIELD_FORMAT_INIT(FIELD_TYPE_UINT, ref_status, lastDesc, 1, FIELD_RELEVANCE_HIGH),
FIELD_FORMAT_INIT(FIELD_TYPE_POINTER_SHORT_ID, ref_status, shortDHash, 1, FIELD_RELEVANCE_HIGH),
FIELD_FORMAT_INIT(FIELD_TYPE_POINTER_GLOBAL_ID, ref_status, dHash, 1, FIELD_RELEVANCE_MEDI),
FIELD_FORMAT_INIT(FIELD_TYPE_UINT, ref_status, lastRef, 1, FIELD_RELEVANCE_HIGH),
FIELD_FORMAT_INIT(FIELD_TYPE_STRING_CHAR, ref_status, nbs, 1, FIELD_RELEVANCE_HIGH),
FIELD_FORMAT_INIT(FIELD_TYPE_POINTER_SHORT_ID, ref_status, nbId, 1, FIELD_RELEVANCE_HIGH),
FIELD_FORMAT_INIT(FIELD_TYPE_POINTER_CHAR, ref_status, nbName, 1, FIELD_RELEVANCE_HIGH),
FIELD_FORMAT_INIT(FIELD_TYPE_UINT, ref_status, rootLen, 1, FIELD_RELEVANCE_HIGH),
FIELD_FORMAT_INIT(FIELD_TYPE_UINT, ref_status, virtLen, 1, FIELD_RELEVANCE_HIGH),
FIELD_FORMAT_INIT(FIELD_TYPE_UINT, ref_status, unresolveds, 1, FIELD_RELEVANCE_HIGH),
FIELD_FORMAT_END
};
STATIC_FUNC
uint8_t *ref_status_page(uint8_t *sOut, uint32_t i, struct NeighRef_node *ref, uint8_t shownSqn)
{
struct key_node *kn = ref->kn;
struct desc_content *dc = kn ? (kn->on ? kn->on->dc : kn->nextDesc) : (NULL);
struct orig_node *on = kn ? kn->on : NULL;
assertion(-502496, (ref->shown != shownSqn));
struct ref_status *rs = &(((struct ref_status*) (sOut = debugRealloc(sOut, ((i + 1) * sizeof(struct ref_status)), -300366)))[i]);
memset(rs, 0, sizeof(struct ref_status));
ref->shown = shownSqn;
snprintf(rs->contents, sizeof(rs->contents), "---");
snprintf(rs->nbs, sizeof(rs->nbs), "---");
rs->lastRef = (iid_get_neighIID4x_timeout_by_node(ref) / 1000);
rs->nbName = ref->nn->on->k.hostname;
rs->nbId = &ref->nn->on->k.nodeId;
if (kn) {
rs->shortId = &kn->kHash;
rs->nodeId = &kn->kHash;
rs->state = kn->bookedState->secName;
}
if (dc) {
rs->dHash = &dc->dHash;
rs->shortDHash = &dc->dHash;
rs->descSqn = dc->descSqn;
snprintf(rs->contents, sizeof(rs->contents), "%d/%d", (dc->contentRefs_tree.items - dc->unresolvedContentCounter), dc->contentRefs_tree.items);
rs->rootLen = dc->desc_frame_len;
rs->virtLen = dc->ref_content_len;
rs->unresolveds = dc->unresolvedContentCounter;
}
snprintf(rs->nbs, sizeof(rs->nbs), "%d", (kn ? kn->neighRefs_tree.items : 0));
if (on) {
rs->name = on->k.hostname;
rs->lastDesc = (bmx_time - on->updated_timestamp) / 1000;
}
return sOut;
}
static int32_t ref_status_creator(struct status_handl *handl, void *data)
{
uint32_t i = 0;
struct avl_node *it;
struct avl_node *an;
struct orig_node *on;
struct NeighRef_node *ref;
struct key_node *kn;
struct neigh_node *nn;
static uint8_t shownSqn = 0;
shownSqn = ((uint8_t) (shownSqn + 1)) ? (shownSqn + 1) : (shownSqn + 2);
AVL_TREE(orig_name_tree, struct orig_node, k);
for (it = NULL; (on = avl_iterate_item(&orig_tree, &it));)
avl_insert(&orig_name_tree, on, -300746);
while ((on = avl_remove_first_item(&orig_name_tree, -300747))) {
for (an = NULL; (ref = avl_iterate_item(&on->kn->neighRefs_tree, &an));)
handl->data = ref_status_page(handl->data, i++, ref, shownSqn);
}
uint32_t namedRefs = i;
for (it = NULL; (kn = avl_iterate_item(&key_tree, &it));) {
if (kn->nextDesc && !kn->on) {
for (an = NULL; (ref = avl_iterate_item(&kn->neighRefs_tree, &an));)
handl->data = ref_status_page(handl->data, i++, ref, shownSqn);
}
}
uint32_t descRefs = i - namedRefs;
for (it = NULL; (kn = avl_iterate_item(&key_tree, &it));) {
if (!kn->nextDesc && !kn->on) {
for (an = NULL; (ref = avl_iterate_item(&kn->neighRefs_tree, &an));)
handl->data = ref_status_page(handl->data, i++, ref, shownSqn);
}
}
uint32_t claimedRefs = i - (namedRefs + descRefs);
uint32_t droppedDRefs = 0;
uint32_t droppedSRefs = 0;
uint32_t allRefs = 0;
for (it = NULL; (nn = avl_iterate_item(&local_tree, &it));) {
allRefs += nn->neighIID4x_repos.tot_used;
IID_T iid;
for (iid = 0; (iid < nn->neighIID4x_repos.max_free && (ref = iid_get_node_by_neighIID4x(&nn->neighIID4x_repos, iid, NO))); iid++) {
if (ref->kn)
droppedDRefs++;
else
handl->data = ref_status_page(handl->data, i++, ref, shownSqn);
if (ref->shown != shownSqn)
droppedSRefs++;
}
}
dbgf(droppedSRefs ? DBGL_CHANGES : DBGL_ALL, droppedSRefs ? DBGT_WARN : DBGT_INFO,
"all=%d shown=%d != (%d = (named=%d + desc=%d + claimed=%d)) dDropped=%d sDropped=%d",
allRefs, i, (namedRefs + descRefs + claimedRefs), namedRefs, descRefs, claimedRefs, droppedDRefs, droppedSRefs);
assertion(-502510, (allRefs == i));
return((i) * sizeof(struct ref_status));
}
STATIC_FUNC
int32_t opt_version(uint8_t cmd, uint8_t _save, struct opt_type *opt, struct opt_parent *patch, struct ctrl_node *cn)
{
TRACE_FUNCTION_CALL;
if ( cmd != OPT_APPLY )
return SUCCESS;
assertion(-501257, !strcmp(opt->name, ARG_VERSION));
dbg_printf(cn, "version=%s-%s compatibility=%d revision=%s id=%s descSqn=%d ip=%s hostname=%s\n",
BMX_BRANCH, BRANCH_VERSION, my_compatibility, GIT_REV, cryptShaAsString(&myKey->kHash), myKey->on ? (int)myKey->on->dc->descSqn : -1, ip6AsStr(&my_primary_ip), my_Hostname);
if (initializing)
cleanup_all(CLEANUP_SUCCESS);
return SUCCESS;
}
int32_t opt_status(uint8_t cmd, uint8_t _save, struct opt_type *opt, struct opt_parent *patch, struct ctrl_node *cn)
{
TRACE_FUNCTION_CALL;
if ( cmd == OPT_CHECK || cmd == OPT_APPLY) {
int32_t relevance = DEF_RELEVANCE;
struct opt_child *c = NULL;
while ((c = list_iterate(&patch->childs_instance_list, c))) {
if (!strcmp(c->opt->name, ARG_RELEVANCE)) {
relevance = strtol(c->val, NULL, 10);
}
}
struct avl_node *it = NULL;
struct status_handl *handl = NULL;
uint32_t data_len;
char status_name[sizeof (((struct status_handl *) NULL)->status_name)] = {0};
if (patch->val)
strncpy(status_name, patch->val, sizeof (status_name));
else
strncpy(status_name, opt->name, sizeof (status_name));
if ((handl = avl_closest_item(&status_tree, status_name)) && !strncmp(handl->status_name, status_name, strlen(status_name))) {
if (cmd == OPT_APPLY) {
prof_start( opt_status, main);
if ((data_len = ((*(handl->frame_creator))(handl, NULL)))) {
uint16_t i;
char upper[strlen(handl->status_name)+1];
for(i=0; (i <= strlen(handl->status_name)); i++)
upper[i] = toupper(handl->status_name[i]);
dbg_printf(cn, "%s:\n", upper);
fields_dbg_table(cn, relevance, data_len, handl->data, handl->min_msg_size, handl->format);
}
prof_stop();
}
} else {
dbg_printf(cn, "requested %s must be one of: ", ARG_VALUE_FORM);
while ((handl = avl_iterate_item(&status_tree, &it))) {
dbg_printf(cn, "%s ", handl->status_name);
}
dbg_printf(cn, "\n");
return FAILURE;
}
}
return SUCCESS;
}
int32_t opt_list_show(uint8_t cmd, uint8_t _save, struct opt_type *opt, struct opt_parent *patch, struct ctrl_node *cn)
{
TRACE_FUNCTION_CALL;
if ( cmd == OPT_CHECK || cmd == OPT_APPLY) {
int32_t relevance = MIN_RELEVANCE;
struct avl_node *it = NULL;
struct status_handl *handl = NULL;
uint32_t data_len;
char status_name[sizeof (((struct status_handl *) NULL)->status_name)] = {0};
if (patch->val)
strncpy(status_name, patch->val, sizeof (status_name));
else
strncpy(status_name, opt->name, sizeof (status_name));
if ((handl = avl_find_item(&status_tree, status_name))) {
if (cmd == OPT_APPLY) {
prof_start( opt_list_show, main);
if ((data_len = ((*(handl->frame_creator))(handl, NULL)))) {
dbg_printf(cn, "%s:", handl->status_name);
fields_dbg_lines(cn, relevance, data_len, handl->data, handl->min_msg_size, handl->format);
dbg_printf(cn, "\n");
}
prof_stop();
}
} else {
dbg_printf(cn, "requested %s must be one of: ", ARG_VALUE_FORM);
while ((handl = avl_iterate_item(&status_tree, &it))) {
dbg_printf(cn, "%s ", handl->status_name);
}
dbg_printf(cn, "\n");
return FAILURE;
}
}
return SUCCESS;
}
int32_t opt_flush_all(uint8_t cmd, uint8_t _save, struct opt_type *opt, struct opt_parent *patch, struct ctrl_node *cn)
{
TRACE_FUNCTION_CALL;
if (cmd == OPT_APPLY) {
purge_tx_task_tree(NULL, NULL, NULL, NULL, YES);
keyNodes_cleanup(KCNull, myKey);
}
return SUCCESS;
}
STATIC_FUNC
int32_t opt_hostname(uint8_t cmd, uint8_t _save, struct opt_type *opt, struct opt_parent *patch, struct ctrl_node *cn)
{
static uint8_t checked = NO;
if ( (cmd == OPT_SET_POST) && initializing && !checked ) {
checked = YES;
if (gethostname(my_Hostname, MAX_HOSTNAME_LEN))
return FAILURE;
my_Hostname[MAX_HOSTNAME_LEN - 1] = 0;
if (validate_name_string(my_Hostname, MAX_HOSTNAME_LEN, NULL) == FAILURE) {
dbg_sys(DBGT_ERR, "illegal hostname %s", my_Hostname);
return FAILURE;
}
}
return SUCCESS;
}
DESC_SQN_T newDescriptionSqn( char* newPath, uint8_t exitIfFailure )
{
static DESC_SQN_T currSqn = 0;
static char path[MAX_PATH_SIZE];
FILE* file = NULL;
int ret;
char *goto_error_code = NULL;
assertion(-502014, XOR(newPath, strlen(path) ));
if (!strlen(path)) {
strcpy(path, newPath);
if (wordlen(path) + 1 >= MAX_PATH_SIZE || path[0] != '/')
goto_error(finish, "path has illegal format");
if (check_dir(path, YES, YES, YES) == FAILURE)
goto_error(finish, "dir can not be created");
}
if (currSqn==0) {
if ((file = fopen(path, "r+"))) {
if ((fscanf(file, "%u", &currSqn) == 1) && (fseek(file, 0, SEEK_SET) == 0) &&
(currSqn = (((currSqn + DESC_SQN_SAVE_INTERVAL) / DESC_SQN_SAVE_INTERVAL) * DESC_SQN_SAVE_INTERVAL) + DESC_SQN_REBOOT_ADDS) &&
((ret = fprintf(file, "%u", currSqn)) > 0) &&
(fclose(file) == 0) && (truncate(path, ret) == 0)) {
dbgf_sys(DBGT_INFO, "Updating existing %s=%s descSqn=%d", ARG_DSQN_PATH, path, currSqn );
file=NULL;
} else {
goto_error(finish, "has illegal content");
}
} else if ((file = fopen(path, "w"))) {
if (
(currSqn = DESC_SQN_REBOOT_ADDS) &&
(ret = fprintf(file, "%u", currSqn)) > 0) {
dbgf_sys(DBGT_WARN, "Created new %s=%s starting with descSqn=%d", ARG_DSQN_PATH, path, currSqn );
} else {
goto_error(finish, "new file can not be updated!");
}
} else {
goto_error(finish, "can not be created!");
}
} else if ((++currSqn)%DESC_SQN_SAVE_INTERVAL) {
dbgf_track(DBGT_INFO, "Not Updating existing %s=%s", ARG_DSQN_PATH, path);
} else if ((file = fopen(path, "w")) && ((ret = fprintf(file, "%u", currSqn)) > 0)) {
dbgf_track(DBGT_INFO, "Updating existing %s=%s", ARG_DSQN_PATH, path);
} else {
goto_error(finish, "old file can not be updated!");
}
finish: {
if(file)
fclose(file);
if (goto_error_code) {
dbgf_sys(DBGT_ERR, "%s=%s %s! errno=%s", ARG_DSQN_PATH, path, goto_error_code, strerror(errno));
if (exitIfFailure)
cleanup_all(-502015);
return 0;
}
dbgf_track(DBGT_INFO, "New descSqn=%d", currSqn);
return currSqn;
}
}
static struct opt_type bmx_options[]=
{
// ord parent long_name shrt Attributes *ival min max default *func,*syntax,*help
{ODI,0,ARG_VERSION, 'v',9,2,A_PS0,A_USR,A_DYI,A_ARG,A_ANY, 0, 0, 0, 0,0, opt_version,
0, "show version"},
{ODI,0,ARG_COMPATIBILITY, 0, 3,1,A_PS1,A_ADM,A_INI,A_CFA,A_ANY, &my_compatibility,MIN_COMPATIBILITY,MAX_COMPATIBILITY,DEF_COMPATIBILITY,0, 0,
ARG_VALUE_FORM, "set (elastic) compatibility version"},
//order must be after ARG_KEY_PATH and before ARG_AUTO_IP6_PREFIX and ARG_TUN_IN_DEV (which use self, initialized from init_self, called from opt_hostname):
{ODI,0,ARG_HOSTNAME, 0, 5,0,A_PS1,A_ADM,A_INI,A_CFA,A_ANY, 0, 0, 0, 0,0, opt_hostname,
ARG_VALUE_FORM, "set advertised hostname of node"},
{ODI,0,ARG_LIST, 0 , 9,1,A_PS1 ,A_USR,A_DYN,A_ARG,A_ANY, 0, 0, 0, 0,0, opt_list_show,
ARG_VALUE_FORM, "list status information about given context. E.g.:" ARG_STATUS ", " ARG_INTERFACES ", " ARG_LINKS ", " ARG_ORIGINATORS " " ARG_CREDITS ", ..." "\n"},
{ODI,0,ARG_SHOW, 's', 9,1,A_PS1N,A_USR,A_DYN,A_ARG,A_ANY, 0, 0, 0, 0,0, opt_status,
ARG_VALUE_FORM, "show status information about given context. E.g.:" ARG_STATUS ", " ARG_INTERFACES ", " ARG_LINKS ", " ARG_ORIGINATORS " " ARG_CREDITS ", ..." "\n"},
{ODI,ARG_SHOW,ARG_RELEVANCE,'r',9,1,A_CS1,A_USR,A_DYN,A_ARG,A_ANY, 0, MIN_RELEVANCE, MAX_RELEVANCE, DEF_RELEVANCE,0, opt_status,
ARG_VALUE_FORM, HLP_ARG_RELEVANCE}
,
{ODI,0,ARG_STATUS, 0, 9,1,A_PS0,A_USR,A_DYN,A_ARG,A_ANY, 0, 0, 0, 0,0, opt_status,
0, "show status\n"},
{ODI,0,ARG_ORIGINATORS, 0, 9,1,A_PS0N,A_USR,A_DYN,A_ARG,A_ANY, 0, 0, 0, 0,0, opt_status,
0, "show originators\n"}
,
{ODI,0,ARG_KEYS, 0, 9,1,A_PS0N,A_USR,A_DYN,A_ARG,A_ANY, 0, 0, 0, 0,0, opt_status,
0, "show keys and their description references\n"}
,
{ODI,0,ARG_DESCREFS, 0, 9,1,A_PS0N,A_USR,A_DYN,A_ARG,A_ANY, 0, 0, 0, 0,0, opt_status,
0, "show description references\n"}
,
{ODI,0,"flushAll", 0, 9,1,A_PS0,A_ADM,A_DYN,A_ARG,A_ANY, 0, 0, 0, 0,0, opt_flush_all,
0, "purge all neighbors and routes on the fly"}
,
#ifndef LESS_OPTIONS
{ODI,0,ARG_DAD_TO, 0, 9,1,A_PS1,A_ADM,A_DYI,A_CFA,A_ANY, &dad_to, MIN_DAD_TO, MAX_DAD_TO, DEF_DAD_TO,0, 0,
ARG_VALUE_FORM, "duplicate address (DAD) detection timout in ms"}
#endif
};
STATIC_FUNC
void bmx(void)
{
struct avl_node *an;
struct dev_node *dev;
TIME_T frequent_timeout, seldom_timeout;
TIME_T s_last_cpu_time = 0, s_curr_cpu_time = 0;
frequent_timeout = seldom_timeout = bmx_time;
update_my_description();
initializing = NO;
while (!terminating) {
TIME_T wait = task_next( );
if ( wait )
wait4Event( XMIN( wait, MAX_SELECT_TIMEOUT_MS ) );
// if (my_description_changed)
// update_my_description_adv();
// The regular tasks...
if ( U32_LT( frequent_timeout + 1000, bmx_time ) ) {
// check for changed interface konfigurations...
for (an = NULL; (dev = avl_iterate_item(&dev_name_tree, &an));) {
if ( dev->active )
sysctl_config( dev );
}
close_ctrl_node( CTRL_CLEANUP, NULL );
/*
struct list_node *list_pos;
list_for_each( list_pos, &dbgl_clients[DBGL_ALL] ) {
struct ctrl_node *cn = (list_entry( list_pos, struct dbgl_node, list ))->cn;
dbg_printf( cn, "------------------ DEBUG ------------------ \n" );
check_apply_parent_option( ADD, OPT_APPLY, 0, get_option( 0, 0, ARG_STATUS ), 0, cn );
check_apply_parent_option( ADD, OPT_APPLY, 0, get_option( 0, 0, ARG_LINKS ), 0, cn );
check_apply_parent_option( ADD, OPT_APPLY, 0, get_option( 0, 0, ARG_LOCALS ), 0, cn );
check_apply_parent_option( ADD, OPT_APPLY, 0, get_option( 0, 0, ARG_ORIGINATORS ), 0, cn );
dbg_printf( cn, "--------------- END DEBUG ---------------\n" );
}
*/
/* preparing the next debug_timeout */
frequent_timeout = bmx_time;
}
if ( U32_LT( seldom_timeout + 5000, bmx_time ) ) {
//node_tasks();
// check for corrupted memory..
checkIntegrity();
/* generating cpu load statistics... */
s_curr_cpu_time = (TIME_T)clock();
s_curr_avg_cpu_load = ( (s_curr_cpu_time - s_last_cpu_time) / (TIME_T)(bmx_time - seldom_timeout) );
s_last_cpu_time = s_curr_cpu_time;
seldom_timeout = bmx_time;
}
}
}
int main(int argc, char *argv[])
{
#ifdef CORE_LIMIT
#include <sys/time.h>
#include <sys/resource.h>
struct rlimit rlim = {.rlim_cur = (CORE_LIMIT * 1024), .rlim_max = (CORE_LIMIT * 1024) };
if (setrlimit(RLIMIT_CORE, &rlim) != 0) {
printf("setrlimit RLIMIT_CORE=%d failed: %s\n", (CORE_LIMIT * 1024), strerror(errno));
}
#endif
My_pid = getpid();
signal( SIGINT, handler );
signal( SIGTERM, handler );
signal( SIGPIPE, SIG_IGN );
signal( SIGSEGV, segmentation_fault );
#ifdef TEST_DEBUG_MALLOC
debugMalloc(1, -300525); //testing debugMalloc
#endif
init_control();
init_schedule();
init_tools();
init_avl();
init_prof();
// init_config();
init_crypt();
init_ip();
init_msg();
init_desc();
init_content();
init_sec();
init_key();
// init_node();
init_ogm();
if (init_plugin() == SUCCESS) {
activate_plugin((metrics_get_plugin()), NULL, NULL);
activate_plugin((link_get_plugin()), NULL, NULL);
activate_plugin((hna_get_plugin()), NULL, NULL);
#ifdef TRAFFIC_DUMP
struct plugin * dump_get_plugin(void);
activate_plugin((dump_get_plugin()), NULL, NULL);
#endif
} else {
assertion(-500809, (0));
}
prof_start( main, NULL );
register_options_array(bmx_options, sizeof( bmx_options), CODE_CATEGORY_NAME);
register_status_handl(sizeof(struct bmx_status), 0, bmx_status_format, ARG_STATUS, bmx_status_creator);
register_status_handl(sizeof(struct orig_status), 1, orig_status_format, ARG_ORIGINATORS, origs_status_creator);
register_status_handl(sizeof(struct orig_status), 1, orig_status_format, ARG_KEYS, keys_status_creator);
register_status_handl(sizeof(struct ref_status), 1, ref_status_format, ARG_DESCREFS, ref_status_creator);
apply_init_args( argc, argv );
bmx();
cleanup_all( CLEANUP_SUCCESS );
return -1;
}
You can’t perform that action at this time.