#include #include #include #include #include #include #include #include #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)); // log_print(LOG_DEBUG, "net_submit: %s", tx_buf); } int net_receive(int socket) { char *hostname, *plugin, *filename, *ds_id, *data; int size, num; 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'; // log_print(LOG_DEBUG, "net_receive: %s|%s|%s|%d|%s", hostname, plugin, filename, atoi(ds_id), data); 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, §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; } 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; }