summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2013-08-20 16:16:55 +0200
committerMatthias Schiffer <mschiffer@universe-factory.net>2013-08-20 16:16:55 +0200
commitd52f208d9fb6381f3c3656c5916866a4b779fa82 (patch)
tree05b08cf037283f1c7a9e10001c962f42422a9aac
parentf6640a80f4be19e988fd7426c3f897f4d3f614e4 (diff)
downloadfastd-d52f208d9fb6381f3c3656c5916866a4b779fa82.tar
fastd-d52f208d9fb6381f3c3656c5916866a4b779fa82.zip
Use v4-mapped addresses for IPv4 peers on IPv6 sockets
This is needed at least on FreeBSD
-rw-r--r--src/peer.c13
-rw-r--r--src/peer.h1
-rw-r--r--src/send.c9
3 files changed, 23 insertions, 0 deletions
diff --git a/src/peer.c b/src/peer.c
index dae8141..fc22a50 100644
--- a/src/peer.c
+++ b/src/peer.c
@@ -324,6 +324,19 @@ void fastd_peer_address_simplify(fastd_peer_address_t *addr) {
}
}
+void fastd_peer_address_widen(fastd_peer_address_t *addr) {
+ if (addr->sa.sa_family == AF_INET) {
+ struct sockaddr_in addr4 = addr->in;
+
+ memset(addr, 0, sizeof(fastd_peer_address_t));
+ addr->in6.sin6_family = AF_INET6;
+ addr->in6.sin6_port = addr4.sin_port;
+ addr->in6.sin6_addr.s6_addr[10] = 0xff;
+ addr->in6.sin6_addr.s6_addr[11] = 0xff;
+ memcpy(&addr->in6.sin6_addr.s6_addr[12], &addr4.sin_addr.s_addr, 4);
+ }
+}
+
static inline void reset_peer_address(fastd_context_t *ctx, fastd_peer_t *peer) {
if (fastd_peer_is_established(peer))
diff --git a/src/peer.h b/src/peer.h
index 7d85c39..1c939b5 100644
--- a/src/peer.h
+++ b/src/peer.h
@@ -100,6 +100,7 @@ struct fastd_remote_config {
bool fastd_peer_address_equal(const fastd_peer_address_t *addr1, const fastd_peer_address_t *addr2);
void fastd_peer_address_simplify(fastd_peer_address_t *addr);
+void fastd_peer_address_widen(fastd_peer_address_t *addr);
static inline uint16_t fastd_peer_address_get_port(const fastd_peer_address_t *addr) {
switch (addr->sa.sa_family) {
diff --git a/src/send.c b/src/send.c
index 8707e31..3a990d2 100644
--- a/src/send.c
+++ b/src/send.c
@@ -70,6 +70,7 @@ static void send_type(fastd_context_t *ctx, const fastd_socket_t *sock, const fa
struct msghdr msg = {};
char cbuf[1024] = {};
+ fastd_peer_address_t remote_addr6;
switch (remote_addr->sa.sa_family) {
case AF_INET:
@@ -86,6 +87,14 @@ static void send_type(fastd_context_t *ctx, const fastd_socket_t *sock, const fa
exit_bug(ctx, "unsupported address family");
}
+ if (sock->bound_addr->sa.sa_family == AF_INET6) {
+ remote_addr6 = *remote_addr;
+ fastd_peer_address_widen(&remote_addr6);
+
+ msg.msg_name = (void*)&remote_addr6.in6;
+ msg.msg_namelen = sizeof(struct sockaddr_in6);
+ }
+
struct iovec iov[2] = {
{ .iov_base = &packet_type, .iov_len = 1 },
{ .iov_base = buffer.data, .iov_len = buffer.len }