aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNatanael Copa <ncopa@alpinelinux.org>2011-07-28 13:55:06 +0200
committerNatanael Copa <ncopa@alpinelinux.org>2011-07-28 13:55:06 +0200
commita0d284cc34c26b8be322eeccd9a46a2e4526a878 (patch)
tree3e0aeb0b08c9f736a08b28e3e1ddb305e32858f1
parenta8986413c299c77c6f57f7e8f8f0e5abf1a882c9 (diff)
downloadpingu-a0d284cc34c26b8be322eeccd9a46a2e4526a878.tar.bz2
pingu-a0d284cc34c26b8be322eeccd9a46a2e4526a878.tar.xz
pingu: use sockaddr_any
add common sockaddr utility functions
-rw-r--r--Makefile1
-rw-r--r--pingu_burst.c3
-rw-r--r--pingu_burst.h5
-rw-r--r--pingu_iface.c57
-rw-r--r--pingu_iface.h8
-rw-r--r--pingu_ping.c26
-rw-r--r--sockaddr_util.c41
-rw-r--r--sockaddr_util.h18
8 files changed, 122 insertions, 37 deletions
diff --git a/Makefile b/Makefile
index 696c82d..5d9d233 100644
--- a/Makefile
+++ b/Makefile
@@ -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 */