summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2013-04-17 21:42:22 +0200
committerMatthias Schiffer <mschiffer@universe-factory.net>2013-04-17 21:44:02 +0200
commitdaf3d6e8db9ef39b50dce040f864fb409bd7044a (patch)
tree49abaa8d953a515f4b8b445d46f7480ee1f8c3fd
parent41ea8e454937444da4d2bb33fe768adb5b02776b (diff)
downloadfastd-daf3d6e8db9ef39b50dce040f864fb409bd7044a.tar
fastd-daf3d6e8db9ef39b50dce040f864fb409bd7044a.zip
Fix handling of the local address in shell commands
Without this fix, using on-establish/disestablish/verify would cause a strange zero port when a bind with a random port was used, and a segmentation fault with dynamic binds.
-rw-r--r--src/fastd.c40
-rw-r--r--src/fastd.h6
-rw-r--r--src/peer.c4
-rw-r--r--src/protocol_ec25519_fhmqvc.c4
4 files changed, 46 insertions, 8 deletions
diff --git a/src/fastd.c b/src/fastd.c
index 3c3d130..d82589e 100644
--- a/src/fastd.c
+++ b/src/fastd.c
@@ -261,13 +261,33 @@ static int bind_socket(fastd_context_t *ctx, const fastd_bind_address_t *addr, b
if (warn) {
if (addr->bindtodev)
pr_warn(ctx, "unable to bind to %B on `%s'", &addr->addr, addr->bindtodev);
- else
+ else
pr_warn(ctx, "unable to bind to %B", &addr->addr);
}
return -1;
}
+static bool set_bound_address(fastd_context_t *ctx, fastd_socket_t *sock) {
+ fastd_peer_address_t addr = {};
+ socklen_t len = sizeof(addr);
+
+ if (getsockname(sock->fd, &addr.sa, &len) < 0) {
+ pr_error_errno(ctx, "getsockname");
+ return false;
+ }
+
+ if (len > sizeof(addr)) {
+ pr_error(ctx, "getsockname: got strange long address");
+ return false;
+ }
+
+ sock->bound_addr = calloc(1, sizeof(addr));
+ *sock->bound_addr = addr;
+
+ return true;
+}
+
static bool bind_sockets(fastd_context_t *ctx) {
unsigned i;
@@ -278,10 +298,15 @@ static bool bind_sockets(fastd_context_t *ctx) {
ctx->socks[i].fd = bind_socket(ctx, ctx->socks[i].addr, ctx->socks[i].fd < -1);
if (ctx->socks[i].fd >= 0) {
+ if (!set_bound_address(ctx, &ctx->socks[i])) {
+ fastd_socket_close(ctx, &ctx->socks[i]);
+ continue;
+ }
+
if (ctx->socks[i].addr->bindtodev)
- pr_info(ctx, "successfully bound to %B on `%s'", &ctx->socks[i].addr->addr, ctx->socks[i].addr->bindtodev);
+ pr_info(ctx, "successfully bound to %B on `%s'", ctx->socks[i].bound_addr, ctx->socks[i].addr->bindtodev);
else
- pr_info(ctx, "successfully bound to %B", &ctx->socks[i].addr->addr);
+ pr_info(ctx, "successfully bound to %B", ctx->socks[i].bound_addr);
}
}
@@ -302,8 +327,15 @@ fastd_socket_t* fastd_socket_open(fastd_context_t *ctx, fastd_peer_t *peer, int
sock->fd = fd;
sock->addr = NULL;
+ sock->bound_addr = NULL;
sock->peer = peer;
+ if (!set_bound_address(ctx, sock)) {
+ fastd_socket_close(ctx, sock);
+ free(sock);
+ return NULL;
+ }
+
return sock;
}
@@ -799,7 +831,7 @@ static void handle_socket(fastd_context_t *ctx, fastd_socket_t *sock) {
fastd_peer_address_t recvaddr;
socklen_t recvaddrlen = sizeof(recvaddr);
-
+
ssize_t len = recvfrom(sock->fd, buffer.data, buffer.len, 0, (struct sockaddr*)&recvaddr, &recvaddrlen);
if (len <= 0) {
if (len < 0 && errno != EINTR)
diff --git a/src/fastd.h b/src/fastd.h
index 9b1191a..9736e08 100644
--- a/src/fastd.h
+++ b/src/fastd.h
@@ -142,6 +142,7 @@ struct fastd_bind_address {
struct fastd_socket {
int fd;
const fastd_bind_address_t *addr;
+ fastd_peer_address_t *bound_addr;
fastd_peer_t *peer;
};
@@ -458,6 +459,11 @@ static inline void fastd_socket_close(fastd_context_t *ctx, fastd_socket_t *sock
sock->fd = -2;
}
+
+ if (sock->bound_addr) {
+ free(sock->bound_addr);
+ sock->bound_addr = NULL;
+ }
}
static inline bool timespec_after(const struct timespec *tp1, const struct timespec *tp2) {
diff --git a/src/peer.c b/src/peer.c
index 55f0467..f4d62e3 100644
--- a/src/peer.c
+++ b/src/peer.c
@@ -36,14 +36,14 @@ static inline void on_establish(fastd_context_t *ctx, const fastd_peer_t *peer)
if (!ctx->conf->on_establish)
return;
- fastd_shell_exec(ctx, ctx->conf->on_establish, ctx->conf->on_establish_dir, peer, &peer->sock->addr->addr, &peer->address, NULL);
+ fastd_shell_exec(ctx, ctx->conf->on_establish, ctx->conf->on_establish_dir, peer, peer->sock->bound_addr, &peer->address, NULL);
}
static inline void on_disestablish(fastd_context_t *ctx, const fastd_peer_t *peer) {
if (!ctx->conf->on_disestablish)
return;
- fastd_shell_exec(ctx, ctx->conf->on_disestablish, ctx->conf->on_disestablish_dir, peer, &peer->sock->addr->addr, &peer->address, NULL);
+ fastd_shell_exec(ctx, ctx->conf->on_disestablish, ctx->conf->on_disestablish_dir, peer, peer->sock->bound_addr, &peer->address, NULL);
}
static inline void free_socket(fastd_context_t *ctx, fastd_peer_t *peer) {
diff --git a/src/protocol_ec25519_fhmqvc.c b/src/protocol_ec25519_fhmqvc.c
index eea95e4..d0dad5b 100644
--- a/src/protocol_ec25519_fhmqvc.c
+++ b/src/protocol_ec25519_fhmqvc.c
@@ -627,7 +627,7 @@ static inline fastd_peer_t* add_temporary(fastd_context_t *ctx, fastd_socket_t *
/* Ugly hack */
peer->protocol_state->last_serial--;
- if (!fastd_peer_verify_temporary(ctx, peer, &sock->addr->addr, address)) {
+ if (!fastd_peer_verify_temporary(ctx, peer, sock->bound_addr, address)) {
pr_debug(ctx, "ignoring handshake from %P[%I] (verification failed)", peer, address);
fastd_peer_delete(ctx, peer);
return NULL;
@@ -674,7 +674,7 @@ static void protocol_handshake_handle(fastd_context_t *ctx, fastd_socket_t *sock
}
if (fastd_peer_is_temporary(peer) && !temporary_added) {
- if (!fastd_peer_verify_temporary(ctx, peer, &sock->addr->addr, address)) {
+ if (!fastd_peer_verify_temporary(ctx, peer, sock->bound_addr, address)) {
pr_debug(ctx, "ignoring handshake from %P[%I] (verification failed)", peer, address);
return;
}