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;