2006-08-03 19:49:07 +02:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <unistd.h>
|
2006-09-30 20:27:56 +02:00
|
|
|
#include <string.h>
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <netinet/in.h>
|
|
|
|
#include <netinet/ip.h>
|
|
|
|
#include <arpa/inet.h>
|
2006-08-03 19:49:07 +02:00
|
|
|
|
|
|
|
#include "configfile.h"
|
2006-09-30 20:27:56 +02:00
|
|
|
#include "list.h"
|
2006-08-03 19:49:07 +02:00
|
|
|
#include "logging.h"
|
2006-09-30 20:27:56 +02:00
|
|
|
#include "network.h"
|
2006-09-30 17:10:32 +02:00
|
|
|
#include "plugins.h"
|
2006-09-30 20:27:56 +02:00
|
|
|
#include "rrdtool.h"
|
2006-08-03 19:49:07 +02:00
|
|
|
|
2006-09-30 20:27:56 +02:00
|
|
|
#define BUFSIZE 1024
|
2006-08-03 19:49:07 +02:00
|
|
|
|
2006-09-30 20:27:56 +02:00
|
|
|
static LIST_HEAD(fwd_list);
|
2006-08-03 19:49:07 +02:00
|
|
|
|
2006-09-30 20:27:56 +02:00
|
|
|
struct fwd_entry {
|
|
|
|
struct list_head list;
|
|
|
|
struct sockaddr_in sa;
|
|
|
|
int sock;
|
|
|
|
};
|
|
|
|
|
|
|
|
// todo: never freed..
|
|
|
|
static char *tx_buf, *rx_buf;
|
|
|
|
|
|
|
|
void net_submit(char *hostname, char *plugin, char *filename, int ds_id, char *data)
|
|
|
|
{
|
|
|
|
int size = snprintf(tx_buf, BUFSIZE, "%s:%s:%s:%d %s", hostname, plugin, filename, ds_id, data);
|
|
|
|
if (size < 0 || size >= BUFSIZE) {
|
|
|
|
log_print(LOG_ERROR, "net_submit(): arguments too long");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct fwd_entry *entry;
|
|
|
|
list_for_each_entry(entry, &fwd_list, list)
|
|
|
|
sendto(entry->sock, tx_buf, size +1, 0, (struct sockaddr *)&entry->sa, sizeof(entry->sa));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
int net_receive(int socket)
|
|
|
|
{
|
|
|
|
char *hostname, *plugin, *filename, *ds_id, *data;
|
2006-09-30 21:31:53 +02:00
|
|
|
int size;
|
2006-09-30 20:27:56 +02:00
|
|
|
|
|
|
|
size = recv(socket, rx_buf, BUFSIZE, 0);
|
|
|
|
|
|
|
|
hostname = rx_buf;
|
|
|
|
plugin = strchr(rx_buf, ':');
|
|
|
|
if (plugin == NULL)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
*plugin++ = '\0';
|
|
|
|
filename = strchr(plugin, ':');
|
|
|
|
if (filename == NULL)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
*filename++ = '\0';
|
|
|
|
ds_id = strchr(filename, ':');
|
|
|
|
if (ds_id == NULL)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
*ds_id++ = '\0';
|
|
|
|
|
|
|
|
data = strchr(ds_id, ' ');
|
|
|
|
if (data == NULL)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
*data++ = '\0';
|
|
|
|
|
|
|
|
rrd_submit(hostname, plugin, filename, atoi(ds_id), data);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int parse_address(char *addr, struct sockaddr_in *sa)
|
|
|
|
{
|
|
|
|
if (addr == NULL)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
char *port = strchr(addr, ':');
|
|
|
|
if (port == NULL)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
*port = '\0';
|
|
|
|
|
|
|
|
sa->sin_family = AF_INET;
|
|
|
|
sa->sin_port = htons(atoi(port +1));
|
|
|
|
inet_aton(addr, &sa->sin_addr);
|
|
|
|
|
|
|
|
*port = ':';
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int net_add_cli(char *addr)
|
2006-08-03 19:49:07 +02:00
|
|
|
{
|
2006-09-30 20:27:56 +02:00
|
|
|
struct fwd_entry *entry;
|
2006-08-03 19:49:07 +02:00
|
|
|
|
2006-09-30 20:27:56 +02:00
|
|
|
entry = malloc(sizeof(struct fwd_entry));
|
|
|
|
if (entry == NULL) {
|
|
|
|
log_print(LOG_ERROR, "net_add_cli(): out of memory");
|
|
|
|
return -1;
|
2006-08-03 19:49:07 +02:00
|
|
|
}
|
|
|
|
|
2006-09-30 20:27:56 +02:00
|
|
|
if (parse_address(addr, &entry->sa) == -1) {
|
|
|
|
free(entry);
|
|
|
|
return -1;
|
|
|
|
}
|
2006-08-03 19:49:07 +02:00
|
|
|
|
2006-09-30 20:27:56 +02:00
|
|
|
if ((entry->sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
|
|
|
|
log_print(LOG_ERROR, "net_add_cli(): socket()");
|
|
|
|
free(entry);
|
|
|
|
return -1;
|
2006-08-03 19:49:07 +02:00
|
|
|
}
|
|
|
|
|
2006-09-30 20:27:56 +02:00
|
|
|
log_print(LOG_INFO, "forwarding to %s:%d", inet_ntoa(entry->sa.sin_addr), ntohs(entry->sa.sin_port));
|
|
|
|
list_add_tail(&entry->list, &fwd_list);
|
|
|
|
return 0;
|
|
|
|
}
|
2006-08-03 19:49:07 +02:00
|
|
|
|
2006-09-30 20:27:56 +02:00
|
|
|
int net_init_cli()
|
|
|
|
{
|
|
|
|
struct conf_section *section;
|
|
|
|
struct conf_tupel *tupel;
|
|
|
|
|
|
|
|
section = config_get_section("global");
|
|
|
|
if (section == NULL)
|
|
|
|
return 0;
|
2006-08-03 19:49:07 +02:00
|
|
|
|
2006-09-30 20:27:56 +02:00
|
|
|
int retval = 0;
|
|
|
|
list_for_each_entry(tupel, §ion->tupel, list) {
|
|
|
|
if (!strcmp(tupel->option, "forward"))
|
|
|
|
retval |= (net_add_cli(tupel->parameter) != -1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (retval) {
|
|
|
|
tx_buf = malloc(BUFSIZE);
|
|
|
|
if (tx_buf == NULL) {
|
|
|
|
log_print(LOG_ERROR, "net_init_cli(): out of memory");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return retval;
|
2006-08-03 19:49:07 +02:00
|
|
|
}
|
|
|
|
|
2006-09-30 20:27:56 +02:00
|
|
|
int net_init_srv()
|
2006-08-03 19:49:07 +02:00
|
|
|
{
|
2006-09-30 20:27:56 +02:00
|
|
|
struct sockaddr_in sa_srv;
|
|
|
|
int srv_sock;
|
|
|
|
|
|
|
|
char *listen = config_get_string("global", "listen", NULL);
|
|
|
|
if (parse_address(listen, &sa_srv) == -1)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if ((srv_sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
|
|
|
|
log_print(LOG_ERROR, "net_init_src(): socket()");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bind(srv_sock, (struct sockaddr *)&sa_srv, sizeof(sa_srv)) < 0) {
|
|
|
|
log_print(LOG_ERROR, "net_init_src(): bind()");
|
|
|
|
close(srv_sock);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
rx_buf = malloc(BUFSIZE);
|
|
|
|
if (rx_buf == NULL) {
|
|
|
|
log_print(LOG_ERROR, "net_init_srv(): out of memory");
|
|
|
|
return 0;
|
|
|
|
}
|
2006-08-03 19:49:07 +02:00
|
|
|
|
2006-09-30 20:27:56 +02:00
|
|
|
log_print(LOG_INFO, "listen on %s:%d", inet_ntoa(sa_srv.sin_addr), ntohs(sa_srv.sin_port));
|
2006-08-03 19:49:07 +02:00
|
|
|
|
2006-09-30 20:27:56 +02:00
|
|
|
return srv_sock;
|
2006-08-03 19:49:07 +02:00
|
|
|
}
|