sammler/network.c
2006-09-30 22:55:04 +02:00

181 lines
3.5 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include "configfile.h"
#include "list.h"
#include "logging.h"
#include "network.h"
#include "plugins.h"
#include "rrdtool.h"
#define BUFSIZE 1024
static LIST_HEAD(fwd_list);
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;
int size;
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)
{
struct fwd_entry *entry;
entry = malloc(sizeof(struct fwd_entry));
if (entry == NULL) {
log_print(LOG_ERROR, "net_add_cli(): out of memory");
return -1;
}
if (parse_address(addr, &entry->sa) == -1) {
free(entry);
return -1;
}
if ((entry->sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
log_print(LOG_ERROR, "net_add_cli(): socket()");
free(entry);
return -1;
}
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;
}
int net_init_cli()
{
struct conf_section *section;
struct conf_tupel *tupel;
section = config_get_section("global");
if (section == NULL)
return 0;
int retval = 0;
list_for_each_entry(tupel, &section->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;
}
int net_init_srv()
{
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;
}
log_print(LOG_INFO, "listen on %s:%d", inet_ntoa(sa_srv.sin_addr), ntohs(sa_srv.sin_port));
return srv_sock;
}