diff options
-rw-r--r-- | src/config.y | 25 | ||||
-rw-r--r-- | src/lex.c | 40 |
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) @@ -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) { |