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-10-08 16:33:07 +02:00
|
|
|
#include "helper.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-10-11 16:47:48 +02:00
|
|
|
#define BUFSIZE 8192
|
2006-08-03 19:49:07 +02:00
|
|
|
|
2006-10-08 16:33:07 +02:00
|
|
|
static struct sockaddr_in fwd_sa;
|
|
|
|
static int fwd_sock;
|
2006-09-30 20:27:56 +02:00
|
|
|
|
|
|
|
// todo: never freed..
|
|
|
|
static char *tx_buf, *rx_buf;
|
2006-10-11 16:47:48 +02:00
|
|
|
static int tx_pos;
|
2006-09-30 20:27:56 +02:00
|
|
|
|
2007-03-31 22:31:07 +02:00
|
|
|
int net_submit(const char *hostname, const char *plugin, const char *filename, int ds_id, const char *data)
|
2006-09-30 20:27:56 +02:00
|
|
|
{
|
2006-10-11 16:47:48 +02:00
|
|
|
int size = snprintf(tx_buf + tx_pos, BUFSIZE - tx_pos, "%s:%s:%s:%d %s\n",
|
|
|
|
hostname, plugin, filename, ds_id, data);
|
|
|
|
|
|
|
|
if (size < 0 || size >= BUFSIZE - tx_pos) {
|
2006-09-30 20:27:56 +02:00
|
|
|
log_print(LOG_ERROR, "net_submit(): arguments too long");
|
2006-10-11 16:47:48 +02:00
|
|
|
// TODO: retry with flushed buffer?
|
2006-10-07 20:48:20 +02:00
|
|
|
return -1;
|
2006-09-30 20:27:56 +02:00
|
|
|
}
|
|
|
|
|
2006-10-11 16:47:48 +02:00
|
|
|
tx_pos += size;
|
2006-10-07 20:48:20 +02:00
|
|
|
return 0;
|
2006-09-30 20:27:56 +02:00
|
|
|
}
|
|
|
|
|
2007-03-31 22:31:07 +02:00
|
|
|
int net_submit_flush(void)
|
2006-09-30 20:27:56 +02:00
|
|
|
{
|
2006-10-11 16:47:48 +02:00
|
|
|
if (tx_pos != 0)
|
|
|
|
sendto(fwd_sock, tx_buf, tx_pos, 0, (struct sockaddr *)&fwd_sa, sizeof(fwd_sa));
|
2006-09-30 20:27:56 +02:00
|
|
|
|
2006-10-11 16:47:48 +02:00
|
|
|
tx_pos = 0;
|
|
|
|
return 0;
|
|
|
|
}
|
2006-09-30 20:27:56 +02:00
|
|
|
|
2006-10-11 16:47:48 +02:00
|
|
|
int net_receive(int socket)
|
|
|
|
{
|
|
|
|
int size = recv(socket, rx_buf, BUFSIZE, 0);
|
|
|
|
int rx_pos = 0;
|
|
|
|
|
|
|
|
char *delim;
|
|
|
|
while ((delim = memchr(rx_buf + rx_pos, '\n', size - rx_pos))) {
|
|
|
|
*delim = '\0';
|
|
|
|
|
|
|
|
char *data[2], *part[4];
|
|
|
|
int ret = strsplit(rx_buf + rx_pos, " ", data, 2);
|
|
|
|
if (ret != 2) {
|
|
|
|
log_print(LOG_ERROR, "net_receive() abort data-split");
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = strsplit(data[0], ":", part, 4);
|
|
|
|
if (ret != 4) {
|
|
|
|
log_print(LOG_ERROR, "net_receive() abort header-split");
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
rrd_submit(part[0], part[1], part[2], atoi(part[3]), data[1]);
|
|
|
|
|
|
|
|
rx_pos = (delim - rx_buf) +1;
|
|
|
|
}
|
2006-09-30 20:27:56 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2007-03-31 22:31:07 +02:00
|
|
|
static int net_config_get_saddr(const char *section, const char *option, struct sockaddr_in *sa)
|
2007-03-31 22:15:00 +02:00
|
|
|
{
|
|
|
|
char *part[2];
|
|
|
|
|
|
|
|
const char *ret = config_get_string(section, option, NULL);
|
|
|
|
if (ret == NULL)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (strsplit(ret, ":", part, 2) != 2)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
sa->sin_family = AF_INET;
|
|
|
|
sa->sin_port = htons(atoi(part[1]));
|
|
|
|
inet_aton(part[0], &sa->sin_addr);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2007-03-31 22:31:07 +02:00
|
|
|
int net_init_cli(void)
|
2006-08-03 19:49:07 +02:00
|
|
|
{
|
2007-03-31 22:15:00 +02:00
|
|
|
int ret = net_config_get_saddr("global", "forward", &fwd_sa);
|
2006-10-08 16:33:07 +02:00
|
|
|
if (ret < 0)
|
2006-09-30 20:27:56 +02:00
|
|
|
return -1;
|
2006-08-03 19:49:07 +02:00
|
|
|
|
2006-10-07 20:48:20 +02:00
|
|
|
tx_buf = malloc(BUFSIZE);
|
|
|
|
if (tx_buf == NULL) {
|
|
|
|
log_print(LOG_ERROR, "net_init_cli(): out of memory");
|
|
|
|
return -1;
|
|
|
|
}
|
2006-09-30 20:27:56 +02:00
|
|
|
|
2006-10-11 16:47:48 +02:00
|
|
|
tx_pos = 0;
|
|
|
|
|
2006-10-08 16:33:07 +02:00
|
|
|
fwd_sock = socket(PF_INET, SOCK_DGRAM, 0);
|
|
|
|
if (fwd_sock < 0) {
|
|
|
|
log_print(LOG_ERROR, "net_init_cli(): socket()");
|
2006-10-07 20:48:20 +02:00
|
|
|
return -1;
|
2006-09-30 20:27:56 +02:00
|
|
|
}
|
|
|
|
|
2006-10-08 16:33:07 +02:00
|
|
|
log_print(LOG_INFO, "forwarding to %s:%d", inet_ntoa(fwd_sa.sin_addr), ntohs(fwd_sa.sin_port));
|
|
|
|
return 0;
|
2006-08-03 19:49:07 +02:00
|
|
|
}
|
|
|
|
|
2007-03-31 22:31:07 +02:00
|
|
|
int net_init_srv(void)
|
2006-08-03 19:49:07 +02:00
|
|
|
{
|
2006-09-30 20:27:56 +02:00
|
|
|
struct sockaddr_in sa_srv;
|
|
|
|
|
2007-03-31 22:15:00 +02:00
|
|
|
int ret = net_config_get_saddr("global", "listen", &sa_srv);
|
2006-10-08 16:33:07 +02:00
|
|
|
if (ret < 0)
|
2006-09-30 20:27:56 +02:00
|
|
|
return -1;
|
|
|
|
|
2006-10-08 16:33:07 +02:00
|
|
|
int srv_sock = socket(PF_INET, SOCK_DGRAM, 0);
|
|
|
|
if (srv_sock < 0) {
|
2006-09-30 20:27:56 +02:00
|
|
|
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");
|
2006-10-07 20:48:20 +02:00
|
|
|
close(srv_sock);
|
|
|
|
return -1;
|
2006-09-30 20:27:56 +02:00
|
|
|
}
|
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));
|
|
|
|
return srv_sock;
|
2006-08-03 19:49:07 +02:00
|
|
|
}
|