summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/config.y25
-rw-r--r--src/lex.c40
2 files changed, 62 insertions, 3 deletions
diff --git a/src/config.y b/src/config.y
index a14794f..b7243a5 100644
--- a/src/config.y
+++ b/src/config.y
@@ -47,6 +47,10 @@
struct in_addr addr4;
struct in6_addr addr6;
fastd_peer_address_t addr;
+ struct {
+ struct in6_addr addr;
+ char ifname[IFNAMSIZ];
+ } addr6_scoped;
const char *error;
}
@@ -60,6 +64,7 @@
%token <addr4> TOK_ADDR4
%token <addr6> TOK_ADDR6
+%token <addr6_scoped> TOK_ADDR6_SCOPED
%token TOK_ADDRESSES
%token TOK_ANY
@@ -468,6 +473,26 @@ peer_remote: TOK_ADDR4 port {
(*remote)->address.in6.sin6_port = htons($2);
fastd_peer_address_simplify(&(*remote)->address);
}
+ | TOK_ADDR6_SCOPED port {
+ char addrbuf[INET6_ADDRSTRLEN];
+ size_t addrlen;
+ fastd_remote_config_t **remote = &conf->peers->remotes;
+ while (*remote)
+ remote = &(*remote)->next;
+
+ inet_ntop(AF_INET6, &$1.addr, addrbuf, sizeof(addrbuf));
+ addrlen = strlen(addrbuf);
+
+ *remote = calloc(1, sizeof(fastd_remote_config_t));
+
+ (*remote)->hostname = malloc(addrlen + strlen($1.ifname) + 2);
+ memcpy((*remote)->hostname, addrbuf, addrlen);
+ (*remote)->hostname[addrlen] = '%';
+ strcpy((*remote)->hostname+addrlen+1, $1.ifname);
+
+ (*remote)->address.sa.sa_family = AF_INET6;
+ (*remote)->address.in.sin_port = htons($2);
+ }
| maybe_af TOK_STRING port maybe_float {
fastd_remote_config_t **remote = &conf->peers->remotes;
while (*remote)
diff --git a/src/lex.c b/src/lex.c
index bf54b6f..ee58339 100644
--- a/src/lex.c
+++ b/src/lex.c
@@ -279,20 +279,54 @@ static int parse_ipv6_address(YYSTYPE *yylval, YYLTYPE *yylloc, fastd_lex_t *lex
break;
}
- bool ok = (current(lex) == ']');
+ char cur = current(lex);
+
+ bool ifname = (cur == '%') ? lex->start + lex->tok_len + 1 : 0;
+
+ bool ok = ifname || (cur == ']');
if (ok) {
lex->buffer[lex->start + lex->tok_len] = 0;
- ok = inet_pton(AF_INET6, lex->buffer+lex->start+1, &yylval->addr6);
+ ok = inet_pton(AF_INET6, lex->buffer+lex->start+1, ifname ? &yylval->addr6_scoped.addr : &yylval->addr6);
}
if (!ok)
return syntax_error(yylval, lex);
+ if (ifname) {
+ consume(lex, false);
+
+ size_t pos = 0;
+
+ while (true) {
+ if (!next(yylloc, lex, true))
+ return syntax_error(yylval, lex);
+
+ cur = current(lex);
+
+ if (cur == ']')
+ break;
+
+ if (cur == '\\') {
+ if (!next(yylloc, lex, true))
+ return syntax_error(yylval, lex);
+
+ cur = current(lex);
+ }
+
+ if (pos == sizeof(yylval->addr6_scoped.ifname)-1)
+ return syntax_error(yylval, lex);
+
+ yylval->addr6_scoped.ifname[pos++] = cur;
+ }
+
+ yylval->addr6_scoped.ifname[pos] = 0;
+ }
+
next(yylloc, lex, true);
consume(lex, true);
- return TOK_ADDR6;
+ return ifname ? TOK_ADDR6_SCOPED : TOK_ADDR6;
}
static int parse_ipv4_address(YYSTYPE *yylval, YYLTYPE *yylloc, fastd_lex_t *lex) {