*
* Copyright (C) 1992-2001 Andrew Tridgell <tridge@samba.org>
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
- * Copyright (C) 2002-2020 Wayne Davison
+ * Copyright (C) 2002-2022 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
static void client_sockaddr(int fd, struct sockaddr_storage *ss, socklen_t *ss_len);
static int check_name(const char *ipaddr, const struct sockaddr_storage *ss, char *name_buf, size_t name_buf_size);
-static int valid_ipaddr(const char *s);
+static int valid_ipaddr(const char *s, int allow_scope);
/* Return the IP addr of the client as a string. */
char *client_addr(int fd)
if ((p = strchr(ipaddr_buf, ' ')) != NULL)
*p = '\0';
}
- if (valid_ipaddr(ipaddr_buf))
+ if (valid_ipaddr(ipaddr_buf, True))
return ipaddr_buf;
}
break;
#endif
default:
- assert(0);
+ NOISY_DEATH("Unknown ai_family value");
}
freeaddrinfo(answer);
}
-/* Try to read an haproxy header (V1 or V2). Returns 1 on success or 0 on failure. */
-int read_haproxy_header(int fd)
+/* Try to read a proxy protocol header (V1 or V2). Returns 1 on success or 0 on failure. */
+int read_proxy_protocol_header(int fd)
{
union {
struct {
if (size != sizeof hdr.v2.addr.ip4)
return 0;
inet_ntop(AF_INET, hdr.v2.addr.ip4.src_addr, ipaddr_buf, sizeof ipaddr_buf);
- return valid_ipaddr(ipaddr_buf);
+ return valid_ipaddr(ipaddr_buf, False);
+#ifdef INET6
case PROXY_FAM_TCPv6:
if (size != sizeof hdr.v2.addr.ip6)
return 0;
inet_ntop(AF_INET6, hdr.v2.addr.ip6.src_addr, ipaddr_buf, sizeof ipaddr_buf);
- return valid_ipaddr(ipaddr_buf);
+ return valid_ipaddr(ipaddr_buf, False);
+#endif
default:
break;
}
if ((sp = strchr(p, ' ')) == NULL)
return 0;
*sp = '\0';
- if (!valid_ipaddr(p))
+ if (!valid_ipaddr(p, False))
return 0;
strlcpy(ipaddr_buf, p, sizeof ipaddr_buf); /* It will always fit when valid. */
if ((sp = strchr(p, ' ')) == NULL)
return 0;
*sp = '\0';
- if (!valid_ipaddr(p))
+ if (!valid_ipaddr(p, False))
return 0;
/* Ignore destination address. */
}
#ifdef INET6
- if (GET_SOCKADDR_FAMILY(ss) == AF_INET6 &&
- IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)ss)->sin6_addr)) {
+ if (GET_SOCKADDR_FAMILY(ss) == AF_INET6
+ && IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)ss)->sin6_addr)) {
/* OK, so ss is in the IPv6 family, but it is really
* an IPv4 address: something like
* "::ffff:10.130.1.2". If we use it as-is, then the
/* There is a macro to extract the mapped part
* (IN6_V4MAPPED_TO_SINADDR ?), but it does not seem
* to be present in the Linux headers. */
- memcpy(&sin->sin_addr, &sin6.sin6_addr.s6_addr[12],
- sizeof sin->sin_addr);
+ memcpy(&sin->sin_addr, &sin6.sin6_addr.s6_addr[12], sizeof sin->sin_addr);
}
#endif
}
sin1 = (const struct sockaddr_in *) ss;
sin2 = (const struct sockaddr_in *) ai->ai_addr;
- return memcmp(&sin1->sin_addr, &sin2->sin_addr,
- sizeof sin1->sin_addr);
+ return memcmp(&sin1->sin_addr, &sin2->sin_addr, sizeof sin1->sin_addr);
}
#ifdef INET6
sin1 = (const struct sockaddr_in6 *) ss;
sin2 = (const struct sockaddr_in6 *) ai->ai_addr;
- if (ai->ai_addrlen < sizeof (struct sockaddr_in6)) {
+ if (ai->ai_addrlen < (int)sizeof (struct sockaddr_in6)) {
rprintf(FLOG, "%s: too short sockaddr_in6; length=%d\n",
fn, (int)ai->ai_addrlen);
return 1;
}
- if (memcmp(&sin1->sin6_addr, &sin2->sin6_addr,
- sizeof sin1->sin6_addr))
+ if (memcmp(&sin1->sin6_addr, &sin2->sin6_addr, sizeof sin1->sin6_addr))
return 1;
#ifdef HAVE_SOCKADDR_IN6_SCOPE_ID
}
/* Returns 1 for a valid IPv4 or IPv6 addr, or 0 for a bad one. */
-static int valid_ipaddr(const char *s)
+static int valid_ipaddr(const char *s, int allow_scope)
{
int i;
for (count = 0; count < 8; count++) {
if (!*s)
- return saw_double_colon && count < 7;
+ return saw_double_colon;
+ if (allow_scope && *s == '%') {
+ if (saw_double_colon)
+ break;
+ return 0;
+ }
if (strchr(s, ':') == NULL && strchr(s, '.') != NULL) {
if ((!saw_double_colon && count != 6) || (saw_double_colon && count > 6))
}
}
- if (!ipv4_at_end)
- return !*s;
+ if (!ipv4_at_end) {
+ if (allow_scope && *s == '%')
+ for (s++; isAlNum(s); s++) { }
+ return !*s && s[-1] != '%';
+ }
}
/* IPv4 */