diff options
-rw-r--r-- | Makefile | 1 | ||||
-rw-r--r-- | pingu_burst.c | 3 | ||||
-rw-r--r-- | pingu_burst.h | 5 | ||||
-rw-r--r-- | pingu_iface.c | 57 | ||||
-rw-r--r-- | pingu_iface.h | 8 | ||||
-rw-r--r-- | pingu_ping.c | 26 | ||||
-rw-r--r-- | sockaddr_util.c | 41 | ||||
-rw-r--r-- | sockaddr_util.h | 18 |
8 files changed, 122 insertions, 37 deletions
@@ -22,6 +22,7 @@ pingu_OBJS = \ pingu_iface.o \ pingu_netlink.o \ pingu_ping.o \ + sockaddr_util.o \ xlib.o pingu_LIBS = -lev diff --git a/pingu_burst.c b/pingu_burst.c index 3c3fe5b..e09c1ce 100644 --- a/pingu_burst.c +++ b/pingu_burst.c @@ -38,7 +38,8 @@ void ping_burst_start(struct ev_loop *loop, struct pingu_host *host) } for (rp = ai; rp != NULL; rp = rp->ai_next) { - host->burst.saddr = *ai->ai_addr; + sockaddr_init(&host->burst.saddr, ai->ai_family, + ai->ai_addr); r = pingu_ping_send(loop, host, 0); if (r == 0) break; diff --git a/pingu_burst.h b/pingu_burst.h index c42ddfa..6e3b5e6 100644 --- a/pingu_burst.h +++ b/pingu_burst.h @@ -7,10 +7,11 @@ #include <ev.h> #include "list.h" +#include "sockaddr_util.h" struct pingu_burst { - struct sockaddr saddr; - size_t saddrlen; + union sockaddr_any saddr; +// size_t saddrlen; int pings_sent; int pings_replied; int active; diff --git a/pingu_iface.c b/pingu_iface.c index 7b97c62..cbd4e40 100644 --- a/pingu_iface.c +++ b/pingu_iface.c @@ -16,6 +16,7 @@ #include "pingu_host.h" #include "pingu_iface.h" #include "pingu_ping.h" +#include "sockaddr_util.h" static struct list_head iface_list = LIST_INITIALIZER(iface_list); @@ -50,7 +51,8 @@ static int pingu_iface_init_socket(struct ev_loop *loop, return -1; } - ev_io_init(&iface->socket_watcher, pingu_iface_socket_cb, iface->fd, EV_READ); + ev_io_init(&iface->socket_watcher, pingu_iface_socket_cb, + iface->fd, EV_READ); ev_io_start(loop, &iface->socket_watcher); return 0; } @@ -112,20 +114,59 @@ struct pingu_iface *pingu_iface_new(struct ev_loop *loop, const char *name) void pingu_iface_set_addr(struct pingu_iface *iface, int family, void *data, int len) { - struct sockaddr_in *sin; - memset(&iface->primary_addr, 0, sizeof(iface->primary_addr)); - if (len <= 0) { + sockaddr_init(&iface->primary_addr, family, data); + if (len <= 0 || data == NULL) { log_debug("%s: address removed", iface->name); return; } - iface->primary_addr.sa.sa_family = family; + log_debug("%s: new address: %s", iface->name, + inet_ntoa(iface->primary_addr.sin.sin_addr)); +} + +void pingu_gateway_add_sorted(struct pingu_iface *iface, + struct pingu_gateway *new_gw) +{ + struct pingu_gateway *gw; + list_for_each_entry(gw, &iface->gateway_list, gateway_list_entry) { + if (gw->metric > new_gw->metric) { + list_add_tail(&new_gw->gateway_list_entry, + &gw->gateway_list_entry); + return; + } + } + list_add_tail(&new_gw->gateway_list_entry, &iface->gateway_list); +} + +struct pingu_gateway *pingu_gateway_new(int family, void *addr, + int metric) +{ + struct pingu_gateway *gw = calloc(1, sizeof(struct pingu_gateway)); + if (gw == NULL) { + log_perror("Failed to allocate gateway"); + return NULL; + } + gw->gw.sa.sa_family = family; + gw->metric = metric; switch (family) { case AF_INET: - sin = (struct sockaddr_in *)&iface->primary_addr; - memcpy(&sin->sin_addr, data, len); - log_debug("%s: new address: %s", iface->name, inet_ntoa(sin->sin_addr)); + memcpy(&gw->gw.sin.sin_addr, addr, + sizeof(gw->gw.sin.sin_addr)); + break; + case AF_INET6: + memcpy(&gw->gw.sin6.sin6_addr, addr, + sizeof(gw->gw.sin6.sin6_addr)); break; } + return gw; +} + +void pingu_iface_add_gateway(struct pingu_iface *iface, int family, + void *addr, int metric) +{ + struct pingu_gateway *gw = pingu_gateway_new(family, addr, + metric); + if (gw != NULL) + pingu_gateway_add_sorted(iface, gw); } int pingu_iface_init(struct ev_loop *loop, struct list_head *host_list) diff --git a/pingu_iface.h b/pingu_iface.h index e690506..5d94136 100644 --- a/pingu_iface.h +++ b/pingu_iface.h @@ -3,13 +3,9 @@ #include <netinet/in.h> #include <ev.h> -#include "list.h" -union sockaddr_any { - struct sockaddr sa; - struct sockaddr_in sin; - struct sockaddr_in6 sin6; -}; +#include "sockaddr_util.h" +#include "list.h" struct pingu_gateway { union sockaddr_any gw; diff --git a/pingu_ping.c b/pingu_ping.c index 5e5ef84..5ad0ab2 100644 --- a/pingu_ping.c +++ b/pingu_ping.c @@ -18,9 +18,7 @@ #include "pingu_host.h" #include "pingu_iface.h" #include "pingu_ping.h" - -#define SOCK_ADDR_IN_PTR(sa) ((struct sockaddr_in *)(sa)) -#define SOCK_ADDR_IN_ADDR(sa) SOCK_ADDR_IN_PTR(sa)->sin_addr +#include "sockaddr_util.h" #define PING_SEQ_MAX 32000 @@ -58,20 +56,8 @@ static struct pingu_ping *pingu_ping_add(struct ev_loop *loop, return ping; } -static int sockaddr_cmp(struct sockaddr *a, struct sockaddr *b) -{ - if (a->sa_family != b->sa_family) - return -1; - switch (a->sa_family) { - case AF_INET: - return (SOCK_ADDR_IN_ADDR(a).s_addr - SOCK_ADDR_IN_ADDR(b).s_addr); - break; - } - return -1; -} - static struct pingu_ping *pingu_ping_find(struct icmphdr *icp, - struct sockaddr *from, + union sockaddr_any *from, struct list_head *ping_list) { struct pingu_ping *ping; @@ -110,7 +96,7 @@ int pingu_ping_send(struct ev_loop *loop, struct pingu_host *host, return pingu_host_set_status(host, 0) - 1; seq = pingu_ping_get_seq(); - r = icmp_send_ping(host->iface->fd, &host->burst.saddr, + r = icmp_send_ping(host->iface->fd, &host->burst.saddr.sa, sizeof(host->burst.saddr), seq, packetlen); if (r < 0) { if (set_status_on_failure) @@ -124,18 +110,18 @@ int pingu_ping_send(struct ev_loop *loop, struct pingu_host *host, void pingu_ping_read_reply(struct ev_loop *loop, struct pingu_iface *iface) { - struct sockaddr from; + union sockaddr_any from; unsigned char buf[1500]; struct iphdr *ip = (struct iphdr *) buf; struct pingu_ping *ping; - int len = icmp_read_reply(iface->fd, &from, sizeof(from), buf, + int len = icmp_read_reply(iface->fd, &from.sa, sizeof(from), buf, sizeof(buf)); if (len <= 0) return; ping = pingu_ping_find((struct icmphdr *) &buf[ip->ihl * 4], &from, - &iface->ping_list); + &iface->ping_list); if (ping == NULL) return; diff --git a/sockaddr_util.c b/sockaddr_util.c new file mode 100644 index 0000000..ab67b2e --- /dev/null +++ b/sockaddr_util.c @@ -0,0 +1,41 @@ + +#include <netinet/in.h> +#include <string.h> + +#include "sockaddr_util.h" + +int sockaddr_cmp(union sockaddr_any *a, union sockaddr_any *b) +{ + if (a->sa.sa_family != b->sa.sa_family) + return a->sa.sa_family - b->sa.sa_family; + switch (a->sa.sa_family) { + case AF_INET: + return a->sin.sin_addr.s_addr - b->sin.sin_addr.s_addr; + break; + case AF_INET6: + return memcmp((char *) &a->sin6.sin6_addr, + (char *) &b->sin6.sin6_addr, + sizeof(a->sin6.sin6_addr)); + break; + } + return -1; +} + +union sockaddr_any *sockaddr_init(union sockaddr_any *sa, int family, + void *addr) +{ + memset(sa, 0, sizeof(sa)); + if (addr == NULL) + return sa; + sa->sa.sa_family = family; + switch (family) { + case AF_INET: + sa->sin.sin_addr.s_addr = *(uint32_t *)addr; + break; + case AF_INET6: + memcpy(&sa->sin6.sin6_addr, addr, + sizeof(sa->sin6.sin6_addr)); + break; + } + return sa; +} diff --git a/sockaddr_util.h b/sockaddr_util.h new file mode 100644 index 0000000..654941e --- /dev/null +++ b/sockaddr_util.h @@ -0,0 +1,18 @@ +/* sockaddr_any utils */ + +#ifndef SOCKADDR_UTIL_H +#define SOCKADDR_UTIL_H + +#include <netinet/in.h> + +union sockaddr_any { + struct sockaddr sa; + struct sockaddr_in sin; + struct sockaddr_in6 sin6; +}; + +int sockaddr_cmp(union sockaddr_any *a, union sockaddr_any *b); +union sockaddr_any *sockaddr_init(union sockaddr_any *sa, int family, + void *addr); + +#endif /* SOCKADDR_UTIL_H */ |