#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/un.h>
#include <sys/time.h>
#include <libloose.h>
static void config_cb(__uint32_t job_id, int client_fd, char *msg);
static void deinit_cb(__uint32_t job_id, int client_fd, char *msg);
static void discon_cb(__uint32_t job_id, int client_fd, char *msg);
static void ipc_cb(char *node_id, __uint32_t job_id, int client_fd, char *msg);
static int do_ping(__uint32_t job_id, int client_fd, char *node_id);
static int timer_cb(void *arg);
#define TRUE 1
#define FALSE !TRUE
#define KNOWN_UNUSED_PARAM(x) { int __bleh; __bleh = (int) x;}
typedef struct nodelist
{
char node_id[64];
unsigned int ip_address;
int subscribers[255];
int timer_tag;
struct nodelist *next;
struct nodelist *prev;
} NODELIST;
static NODELIST *node_create(char *node_id);
static NODELIST *lookup_node(char *node_id);
static void node_destroy(NODELIST *node);
static void node_remove_client(NODELIST *node, int client_fd);
static int node_add_client(NODELIST *node, int client_fd);
static NODELIST *nodelist_head = NULL;
static NODELIST *nodelist_tail = NULL;
int main(argc, argv)
int argc;
char **argv;
{
KNOWN_UNUSED_PARAM(argc);
KNOWN_UNUSED_PARAM(argv);
lm_init();
lm_nexxus_connect();
if (lm_register("ICMP ECHO",
"ICMP Echo Tester",
"Sends ICMP ECHO messages to a remote host to test connectivity",
"San Mehat (nettwerk@valinux.com)",
"ICMP_ECHO",
1,
0) < 0)
{
printf("Unable to register module with Nexxus\n");
exit(-1);
}
lm_main_loop(config_cb, deinit_cb, discon_cb, ipc_cb);
exit(0);
}
static int timer_cb(void *arg)
{
NODELIST *node = (NODELIST *) arg;
int rc;
rc = do_ping(0, 0, node->node_id);
#if 0
printf("[PING] Node '%s' -> %s\n",
node->node_id,
(rc == 0 ? "OK" : "FAIL"));
#endif
return(TRUE);
}
static void config_cb(__uint32_t job_id, int client_fd, char *msg)
{
NODELIST *node;
char *cmd_module;
char *node_id;
KNOWN_UNUSED_PARAM(job_id);
KNOWN_UNUSED_PARAM(client_fd);
cmd_module = strtok(msg, ":");
node_id = strtok(NULL, ":");
node = lookup_node(node_id);
if (!strcasecmp(cmd_module, "NODE"))
node = node_create(node_id);
else if (!strcasecmp(cmd_module, "END_NODE"))
{
}
else if (!strcasecmp(cmd_module, "ADDITION"))
{
node = node_create(node_id);
}
else if (!strcasecmp(cmd_module, "DELETION"))
{
node_destroy(node);
}
else if (!strcasecmp(cmd_module, "RENAME"))
{
char *new_name;
if (!(new_name = strtok(NULL,":")))
{
printf("[ICMP ECHO] Malformatted cfg msg\n");
return;
}
strcpy(node->node_id, new_name);
}
else if (!strcasecmp(cmd_module, "GLOBAL"))
{
char *variable;
char *value;
if (!(variable = strtok(NULL,":")))
{
printf("[ICMP ECHO] Malformatted cfg msg\n");
return;
}
if (!(value = strtok(NULL,":")))
{
printf("[ICMP ECHO] Malformatted cfg msg\n");
return;
}
if (!strcasecmp(variable, "IP_ADDRESS"))
{
struct in_addr addr;
char msg[255];
node->ip_address = inet_addr(value);
addr.s_addr = node->ip_address;
snprintf(msg,sizeof(msg),"Node '%s' (ip %s) ready",
node_id,inet_ntoa(addr));
lm_log(msg);
}
}
else if (!strcasecmp(cmd_module, "ICMP_ECHO"))
{
char *variable;
if (!(variable = strtok(NULL,":")))
{
printf("[ICMP ECHO] Malformatted cfg msg\n");
return;
}
printf("[ICMP ECHO] Received unknown local module variable '%s'\n",
variable);
}
else
printf("[ICMP ECHO] Received unknown config event <%s>\n",cmd_module);
}
static void deinit_cb(__uint32_t job_id, int client_fd, char *msg)
{
KNOWN_UNUSED_PARAM(job_id);
KNOWN_UNUSED_PARAM(client_fd);
KNOWN_UNUSED_PARAM(msg);
printf("[ICMP ECHO] Received request to shutdown\n");
lm_nexxus_disconnect();
exit(0);
}
static void discon_cb(__uint32_t job_id, int client_fd, char *msg)
{
NODELIST *node;
KNOWN_UNUSED_PARAM(job_id);
KNOWN_UNUSED_PARAM(msg);
node = nodelist_head;
while(node)
{
node_remove_client(node, client_fd);
node = node->next;
}
}
static void ipc_cb(char *node_id, __uint32_t job_id, int client_fd, char *msg)
{
char *cmd;
char response_msg[255];
char *node_id_glob;
NODELIST *node;
if (!(cmd = strtok(msg, ":")))
goto out_malformatted;
if (!(node_id_glob = strtok(msg, ":")))
goto out_malformatted;
if (!(node = lookup_node(node_id)))
{
sprintf(response_msg,
"%d:%d:FOR:JOB_ERROR:NODE_NOT_FOUND",
job_id,
client_fd);
lm_send_to_nexxus(response_msg);
return;
}
if (!strcasecmp(cmd, "PING"))
{
do_ping(job_id, client_fd, node_id);
}
else if (!strcasecmp(cmd, "AUTO_PING_SET"))
{
char *mode;
if (!(mode = strtok(NULL, ":")))
goto out_malformatted;
if (!strcasecmp(mode, "ON"))
node_add_client(node, client_fd);
else if (!strcasecmp(mode, "OFF"))
node_remove_client(node, client_fd);
else
goto out_malformatted;
sprintf(response_msg,
"%d:%d:FOR:JOB_COMPLETED",
job_id,
client_fd);
lm_send_to_nexxus(response_msg);
}
else
{
sprintf(response_msg,
"%d:%d:FOR:JOB_ERROR:UNSUPPORTED_MESSAGE",
job_id,
client_fd);
lm_send_to_nexxus(response_msg);
}
return;
out_malformatted:
sprintf(response_msg,
"%d:%d:FOR:JOB_ERROR:MALFORMATTED_MESSAGE",
job_id,
client_fd);
lm_send_to_nexxus(response_msg);
}
static int node_add_client(NODELIST *node, int client_fd)
{
int I_c1;
for (I_c1 = 0; I_c1 < 255; I_c1 ++)
{
if (node->subscribers[I_c1] == client_fd)
{
printf("[ICMP ECHO] client fd %d already subscribed!\n",client_fd);
return(0);
}
}
/* New subscription */
if (node->timer_tag == -1)
node->timer_tag = lm_timer_add(15,
timer_cb,
node);
for (I_c1 = 0; I_c1 < 255; I_c1 ++)
{
if (node->subscribers[I_c1] == -1)
{
node->subscribers[I_c1] = client_fd;
return(0);
}
}
if (I_c1 == 255)
{
printf("[ICMP ECHO] No client slots available\n");
return(-1);
}
return(0);
}
static void node_remove_client(NODELIST *node, int client_fd)
{
int I_c1;
int cnt = 0;
for (I_c1 = 0; I_c1 < 255; I_c1 ++)
{
if (node->subscribers[I_c1] == client_fd)
{
node->subscribers[I_c1] = -1;
break;
}
}
if (I_c1 == 255)
return; // Not subscribed
for (I_c1 = 0; I_c1 < 255; I_c1 ++)
if (node->subscribers[I_c1] != -1)
cnt++;
if (cnt == 0)
{
lm_timer_remove(node->timer_tag);
node->timer_tag = -1;
}
}
static int do_ping(__uint32_t job_id, int client_fd, char *node_id)
{
char response_msg[255];
char SZ_command[255];
char SZ_line[255];
NODELIST *node;
FILE *pipe;
struct in_addr addr;
char *p = NULL;
char *q;
int I_c1;
if (!(node = lookup_node(node_id)))
{
if (job_id)
{
sprintf(response_msg,
"%d:%d:FOR:JOB_ERROR:NODE_NOT_FOUND",
job_id,
client_fd);
lm_send_to_nexxus(response_msg);
}
return(-1);
}
addr.s_addr = node->ip_address;
sprintf(SZ_command,"/bin/ping -c 1 %s", inet_ntoa(addr));
if (!(pipe = popen(SZ_command,"r")))
{
if (job_id)
{
sprintf(response_msg,
"%d:%d:FOR:JOB_ERROR:INTERNAL_ERROR (%m)",
job_id,
client_fd);
lm_send_to_nexxus(response_msg);
}
return(-1);
}
while(fgets(SZ_line, sizeof(SZ_line), pipe))
{
p = q = NULL;
SZ_line[(strlen(SZ_line)-1)] = 0x00;
if (strstr(SZ_line,"bytes from"))
{
if (!(p = strstr(SZ_line, "time=")))
{
sprintf(response_msg,
"%d:%d:FOR:JOB_ERROR:INTERNAL_ERROR (NO TIME)",
job_id,
client_fd);
lm_send_to_nexxus(response_msg);
pclose(pipe);
return(-1);
}
p+=5;
if (!(q = rindex(SZ_line, ' ')))
{
sprintf(response_msg,
"%d:%d:FOR:JOB_ERROR:INTERNAL_ERROR (NO TIME)",
job_id,
client_fd);
lm_send_to_nexxus(response_msg);
pclose(pipe);
return(-1);
}
*q=0;
break;
}
}
if (job_id)
{
if (!p)
{
sprintf(response_msg,
"%d:%d:FOR:%s:TIMED_OUT",
job_id,
client_fd,
node->node_id);
lm_send_to_nexxus(response_msg);
}
else
{
sprintf(response_msg,
"%d:%d:FOR:%s",
job_id,
client_fd,
p);
lm_send_to_nexxus(response_msg);
}
sprintf(response_msg,
"%d:%d:FOR:JOB_COMPLETED",
job_id,
client_fd);
lm_send_to_nexxus(response_msg);
}
else
{
for (I_c1 = 0; I_c1 < 255; I_c1 ++)
{
if (node->subscribers[I_c1] != -1)
{
if (!p)
{
sprintf(response_msg,
"0:%d:FOR:%s:TIMED_OUT",
node->subscribers[I_c1],
node->node_id);
}
else
{
sprintf(response_msg,
"%d:%d:FOR:%s",
job_id,
client_fd,
p);
}
lm_send_to_nexxus(response_msg);
}
}
}
pclose(pipe);
if (p)
return(0);
else
return(-1);
}
static NODELIST *node_create(char *node_id)
{
NODELIST *new;
int I_c1;
if (!(new = (NODELIST *) malloc(sizeof(NODELIST))))
return(0);
memset(new, 0, sizeof(NODELIST));
if (!nodelist_head)
nodelist_head = nodelist_tail = new;
else
{
nodelist_tail->next = new;
new->prev = nodelist_tail;
nodelist_tail = new;
}
for (I_c1=0; I_c1 <255;I_c1++)
new->subscribers[I_c1] = -1;
new->timer_tag = -1;
strcpy(new->node_id, node_id);
return(new);
}
static NODELIST *lookup_node(char *node_id)
{
NODELIST *scan;
if (!node_id)
return(NULL);
scan = nodelist_head;
while(scan)
{
if (!strcmp(node_id, scan->node_id))
return(scan);
scan = scan->next;
}
return(NULL);
}
static void node_destroy(NODELIST *node)
{
if (node == nodelist_head)
{
nodelist_head = nodelist_head->next;
if (nodelist_head)
nodelist_head->prev = NULL;
else
nodelist_tail = NULL;
}
else if (node == nodelist_tail)
{
nodelist_tail = nodelist_tail->prev;
if (nodelist_tail)
nodelist_tail->next = NULL;
else
nodelist_head = NULL;
}
else
{
node->next->prev = node->prev;
node->prev->next = node->next;
}
free(node);
} |