summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/config.c2
-rw-r--r--src/config.y4
-rw-r--r--src/fastd.h4
-rw-r--r--src/log.c8
-rw-r--r--src/socket.c16
5 files changed, 27 insertions, 7 deletions
diff --git a/src/config.c b/src/config.c
index 66b69c7..1793b7b 100644
--- a/src/config.c
+++ b/src/config.c
@@ -112,7 +112,7 @@ void fastd_config_mac(fastd_context_t *ctx, fastd_config_t *conf, const char *na
void fastd_config_bind_address(fastd_context_t *ctx UNUSED, fastd_config_t *conf, const fastd_peer_address_t *address, const char *bindtodev, bool default_v4, bool default_v6) {
#ifndef USE_BINDTODEVICE
- if (bindtodev)
+ if (bindtodev && !fastd_peer_address_is_v6_ll(address))
exit_error(ctx, "config error: device bind configuration not supported on this system");
#endif
diff --git a/src/config.y b/src/config.y
index b7243a5..878f6e7 100644
--- a/src/config.y
+++ b/src/config.y
@@ -292,6 +292,10 @@ interface: TOK_STRING { free(conf->ifname); conf->ifname = strdup($1->str); }
bind: bind_address maybe_bind_interface maybe_bind_default {
fastd_config_bind_address(ctx, conf, &$1, $2 ? $2->str : NULL, $3 == AF_UNSPEC || $3 == AF_INET, $3 == AF_UNSPEC || $3 == AF_INET6);
}
+ | TOK_ADDR6_SCOPED maybe_port maybe_bind_default {
+ fastd_peer_address_t addr = { .in6 = { .sin6_family = AF_INET6, .sin6_addr = $1.addr, .sin6_port = htons($2) } };
+ fastd_config_bind_address(ctx, conf, &addr, $1.ifname, $3 == AF_UNSPEC || $3 == AF_INET, $3 == AF_UNSPEC || $3 == AF_INET6);
+ }
;
bind_address:
diff --git a/src/fastd.h b/src/fastd.h
index ddd05a3..219dc2e 100644
--- a/src/fastd.h
+++ b/src/fastd.h
@@ -363,6 +363,10 @@ static inline size_t fastd_max_outer_packet(const fastd_context_t *ctx) {
return PACKET_TYPE_LEN + fastd_max_inner_packet(ctx) + ctx->conf->max_overhead;
}
+static inline bool fastd_peer_address_is_v6_ll(const fastd_peer_address_t *addr) {
+ return (addr->sa.sa_family == AF_INET6 && IN6_IS_ADDR_LINKLOCAL(&addr->in6.sin6_addr));
+}
+
static inline fastd_string_stack_t* fastd_string_stack_dup(const char *str) {
fastd_string_stack_t *ret = malloc(alignto(sizeof(fastd_string_stack_t) + strlen(str) + 1, 8));
ret->next = NULL;
diff --git a/src/log.c b/src/log.c
index 81dfb20..fb3a8af 100644
--- a/src/log.c
+++ b/src/log.c
@@ -68,11 +68,11 @@ static size_t snprint_peer_address(const fastd_context_t *ctx, char *buffer, siz
if (inet_ntop(AF_INET6, &address->in6.sin6_addr, addr_buf, sizeof(addr_buf))) {
if (IN6_IS_ADDR_LINKLOCAL(&address->in6.sin6_addr)) {
char ifname_buf[IF_NAMESIZE];
- return snprintf_safe(buffer, size, "[%s%%%s]:%u", addr_buf, if_indextoname(address->in6.sin6_scope_id, ifname_buf), ntohs(address->in6.sin6_port));
- }
- else {
- return snprintf_safe(buffer, size, "[%s]:%u", addr_buf, ntohs(address->in6.sin6_port));
+ if (if_indextoname(address->in6.sin6_scope_id, ifname_buf))
+ return snprintf_safe(buffer, size, "[%s%%%s]:%u", addr_buf, if_indextoname(address->in6.sin6_scope_id, ifname_buf), ntohs(address->in6.sin6_port));
}
+
+ return snprintf_safe(buffer, size, "[%s]:%u", addr_buf, ntohs(address->in6.sin6_port));
}
else
return 0;
diff --git a/src/socket.c b/src/socket.c
index af99894..25f50e7 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -77,7 +77,7 @@ static int bind_socket(fastd_context_t *ctx, const fastd_bind_address_t *addr, b
}
#ifdef USE_BINDTODEVICE
- if (addr->bindtodev) {
+ if (addr->bindtodev && !fastd_peer_address_is_v6_ll(&addr->addr)) {
if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, addr->bindtodev, strlen(addr->bindtodev))) {
if (warn)
pr_warn_errno(ctx, "setsockopt: unable to bind to device");
@@ -107,6 +107,18 @@ static int bind_socket(fastd_context_t *ctx, const fastd_bind_address_t *addr, b
fastd_peer_address_t bind_address = addr->addr;
+ if (fastd_peer_address_is_v6_ll(&addr->addr) && addr->bindtodev) {
+ bind_address.in6.sin6_scope_id = atoi(addr->bindtodev);
+
+ if (!bind_address.in6.sin6_scope_id)
+ bind_address.in6.sin6_scope_id = if_nametoindex(addr->bindtodev);
+
+ if (!bind_address.in6.sin6_scope_id) {
+ pr_warn_errno(ctx, "if_nametoindex");
+ goto error;
+ }
+ }
+
if (bind_address.sa.sa_family == AF_UNSPEC) {
memset(&bind_address, 0, sizeof(bind_address));
bind_address.sa.sa_family = af;
@@ -180,7 +192,7 @@ bool fastd_socket_handle_binds(fastd_context_t *ctx) {
if (!ctx->socks[i].addr->addr.sa.sa_family)
bound_addr.sa.sa_family = AF_UNSPEC;
- if (ctx->socks[i].addr->bindtodev)
+ if (ctx->socks[i].addr->bindtodev && !fastd_peer_address_is_v6_ll(&bound_addr))
pr_info(ctx, "successfully bound to %B on `%s'", &bound_addr, ctx->socks[i].addr->bindtodev);
else
pr_info(ctx, "successfully bound to %B", &bound_addr);