diff --git a/Makefile b/Makefile index c363fbb..5820736 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,7 @@ WWW_OWNER = www-data # ############################ -SRC := sammler.c configfile.c event.c helper.c logging.c network.c plugins.c probe.c +SRC := sammler.c configfile.c event.c helper.c logging.c network.c plugins.c probe.c sockaddr.c CFLAGS := -O2 -Wall -MMD -fno-stack-protector -I. LDFLAGS := -ldl -rdynamic diff --git a/network.c b/network.c index dbcf036..64deb19 100644 --- a/network.c +++ b/network.c @@ -16,6 +16,7 @@ #include "network.h" #include "plugins.h" #include "rrdtool.h" +#include "sockaddr.h" #define PKTSIZE 1400 @@ -124,42 +125,13 @@ static int net_receive(int socket, void *privdata) return 0; } -static int parse_saddr(const char *addr, struct sockaddr_in *sa) -{ - char *addr_cpy = strdup(addr); - if (addr_cpy == NULL) { - log_print(LOG_WARN, "parse_saddr(): out of memory"); - return -1; - } - - char *tmp; - char *ip = strtok_r(addr_cpy, ":", &tmp); - if (ip == NULL) { - free(addr_cpy); - return -1; - } - - char *port = strtok_r(NULL, ":", &tmp); - if (port == NULL) { - free(addr_cpy); - return -1; - } - - sa->sin_family = AF_INET; - sa->sin_port = htons(atoi(port)); - int ret = inet_aton(ip, &sa->sin_addr); - - free(addr_cpy); - return (ret != 0) ? 0 : -1; -} - static struct net_entry * create_net_entry(const char *value) { struct net_entry *entry = malloc(sizeof(struct net_entry)); if (entry == NULL) return NULL; - if (parse_saddr(value, &entry->addr) == -1) { + if (parse_sockaddr(value, &entry->addr) < 0) { free(entry); return NULL; } @@ -190,10 +162,7 @@ static int net_init_srv_cb(const char *value, void *privdata) entry->event = event_add_readfd(NULL, entry->socket, net_receive, NULL); list_add(&entry->list, &srv_list); - log_print(LOG_INFO, "listen on %s:%d", - inet_ntoa(entry->addr.sin_addr), - ntohs(entry->addr.sin_port)); - + log_print(LOG_INFO, "listen on %s", get_sockaddr_buf(&entry->addr)); return 0; } @@ -206,10 +175,7 @@ static int net_init_cli_cb(const char *value, void *privdata) } list_add(&entry->list, &cli_list); - log_print(LOG_INFO, "forwarding to %s:%d", - inet_ntoa(entry->addr.sin_addr), - ntohs(entry->addr.sin_port)); - + log_print(LOG_INFO, "forwarding to %s", get_sockaddr_buf(&entry->addr)); return 0; } diff --git a/sockaddr.c b/sockaddr.c new file mode 100644 index 0000000..0559097 --- /dev/null +++ b/sockaddr.c @@ -0,0 +1,117 @@ +/*************************************************************************** + * Copyright (C) 07/2007 by Olaf Rempel * + * razzor@kopf-tisch.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; version 2 of the License * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include +#include +#include + +#include +#include +#include +#include + +int parse_sockaddr(const char *addr, struct sockaddr_in *sa) +{ + char *buf = strdup(addr); + if (buf == NULL) + return -1; + + char *tmp; + char *ipstr = strtok_r(buf, ":", &tmp); + if (ipstr == NULL) { + free(buf); + return -2; + } + + sa->sin_family = AF_INET; + if (inet_pton(AF_INET, ipstr, &sa->sin_addr) <= 0) { + free(buf); + return -3; + } + + char *portstr = strtok_r(NULL, " \r\n", &tmp); + if (portstr == NULL) { + free(buf); + return -4; + } + + int port = atoi(portstr); + if (port < 0 || port > 65535) { + free(buf); + return -5; + } + + sa->sin_port = htons(port); + free(buf); + return 0; +} + +int parse_subnet(const char *addr, struct in_addr *net, struct in_addr *mask) +{ + char *buf = strdup(addr); + if (buf == NULL) + return -1; + + char *tmp; + char *netstr = strtok_r(buf, "/", &tmp); + if (netstr == NULL) { + free(buf); + return -2; + } + + if (inet_pton(AF_INET, netstr, net) <= 0) { + free(buf); + return -3; + } + + char *maskstr = strtok_r(NULL, " \r\n", &tmp); + if (maskstr == NULL) { + mask->s_addr = ~0; + + } else if (inet_pton(AF_INET, maskstr, mask) <= 0) { + int maskbits = atoi(maskstr); + if (maskbits < 0 || maskbits > 32) { + free(buf); + return -4; + } + + mask->s_addr = htonl(~0 << (32 - maskbits)); + } + + free(buf); + return 0; +} + +int get_sockaddr(char *buf, int size, struct sockaddr_in *addr) +{ + return snprintf(buf, size, "%s:%d", inet_ntoa(addr->sin_addr), ntohs(addr->sin_port)); +} + +char * get_sockaddr_buf(struct sockaddr_in *addr) +{ + static char ret[24]; + get_sockaddr(ret, sizeof(ret), addr); + return ret; +} + +int same_sockaddr(struct sockaddr_in *a, struct sockaddr_in *b) +{ + return !((a->sin_family ^ b->sin_family) | + (a->sin_addr.s_addr ^ b->sin_addr.s_addr) | + (a->sin_port ^ b->sin_port)); +} diff --git a/sockaddr.h b/sockaddr.h new file mode 100644 index 0000000..6d1d936 --- /dev/null +++ b/sockaddr.h @@ -0,0 +1,14 @@ +#ifndef _SOCKADDR_H_ +#define _SOCKADDR_H_ + +#include + +int parse_sockaddr(const char *addr, struct sockaddr_in *sa); +int parse_subnet(const char *addr, struct in_addr *net, struct in_addr *mask); + +int get_sockaddr(char *buf, int size, struct sockaddr_in *addr); +char * get_sockaddr_buf(struct sockaddr_in *addr); + +int same_sockaddr(struct sockaddr_in *a, struct sockaddr_in *b); + +#endif /* _SOCKADDR_H_ */