On Mon, Mar 11, 2019 at 05:11:56PM +0100, Otto Moerbeek wrote: > > I was going to test your diff but it does not apply. Your mailer seems > to convert spaces and or tabs to funny char sequences. Please fix > (test by mailing to yourself and applying with patch(1)) and resend, > > -Otto >
So I reworked the diff to apply and use the proper formatting (regulart sapces and tabs instead of UTF-8 non breaking spaces). I also fixed a case of parsing IPv6 addresses. Anyone willing to ok? -Otto Index: conf.y =================================================================== RCS file: /cvs/src/usr.sbin/sasyncd/conf.y,v retrieving revision 1.19 diff -u -p -r1.19 conf.y --- conf.y 9 Apr 2017 02:40:24 -0000 1.19 +++ conf.y 12 Mar 2019 12:59:18 -0000 @@ -30,8 +30,10 @@ #include <sys/types.h> #include <sys/stat.h> #include <sys/socket.h> +#include <arpa/inet.h> #include <ctype.h> #include <fcntl.h> +#include <ifaddrs.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -48,6 +50,7 @@ struct cfgstate cfgstate; int conflen = 0; char *confbuf, *confptr; +int check_peer_addr(const char *); int yyparse(void); int yylex(void); void yyerror(const char *); @@ -172,17 +175,8 @@ setting : INTERFACE STRING | PEER STRING { struct syncpeer *peer; - int duplicate = 0; - for (peer = LIST_FIRST(&cfgstate.peerlist); peer; - peer = LIST_NEXT(peer, link)) - if (strcmp($2, peer->name) == 0) { - duplicate++; - break; - } - if (duplicate) - free($2); - else { + if (check_peer_addr($2)) { peer = calloc(1, sizeof *peer); if (!peer) { log_err("config: calloc(1, %lu) " @@ -191,10 +185,11 @@ setting : INTERFACE STRING YYERROR; } peer->name = $2; - } - LIST_INSERT_HEAD(&cfgstate.peerlist, peer, link); - cfgstate.peercnt++; - log_msg(2, "config: add peer %s", peer->name); + LIST_INSERT_HEAD(&cfgstate.peerlist, peer, link); + cfgstate.peercnt++; + log_msg(2, "config: add peer %s", peer->name); + } else + free($2); } | LISTEN ON STRING af port { @@ -284,6 +279,72 @@ match(char *token) } int +check_peer_addr(const char *peer_addr) +{ + int valid = 1; + short peer_family = AF_UNSPEC; + struct ifaddrs *ifap = 0, *ifa; + struct syncpeer *peer; + struct sockaddr_in sa; + struct sockaddr_in6 sa6; + + if (inet_pton(AF_INET, peer_addr, &sa.sin_addr) == 1) + peer_family = AF_INET; + + if (peer_family == AF_UNSPEC && inet_pton(AF_INET6, peer_addr, + &sa6.sin6_addr) == 1) + peer_family = AF_INET6; + + if (peer_family == AF_UNSPEC) { + log_msg(2, "config: skip unparseable peer %s", peer_addr); + valid = 0; + } + + if (valid && getifaddrs(&ifap) == 0) { + for (ifa = ifap; ifa; ifa = ifa->ifa_next) { + if (!ifa->ifa_addr || ifa->ifa_addr->sa_family != + peer_family) + continue; + + switch (ifa->ifa_addr->sa_family) { + case AF_INET: + if (memcmp(&sa.sin_addr, + &((struct sockaddr_in *)ifa->ifa_addr)->sin_addr, + sizeof(struct in_addr)) == 0) + valid = 0; + break; + case AF_INET6: + if (memcmp(&sa6.sin6_addr, + &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr, + sizeof(struct in6_addr)) == 0) + valid = 0; + break; + } + + if (!valid) { + log_msg(2, "config: skip local peer %s", + peer_addr); + break; + } + } + freeifaddrs(ifap); + } + + if (valid) { + for (peer = LIST_FIRST(&cfgstate.peerlist); peer; + peer = LIST_NEXT(peer, link)) { + if (strcmp(peer_addr, peer->name) == 0) { + log_msg(2, "config: skip duplicate peer %s", + peer_addr); + valid = 0; + } + } + } + + return valid; +} + +int yylex(void) { char *p; @@ -325,7 +386,7 @@ yylex(void) /* Numerical token? */ if (isdigit(*confptr)) { for (p = confptr; *p; p++) - if (*p == '.') /* IP address, or bad input */ + if (*p == '.' || *p == ':') /* IP address, or bad input */ goto is_string; v = (int)strtol(confptr, (char **)NULL, 10); yylval.val = v;