Commit 01fd79e6 authored by David Howells's avatar David Howells

afs: Fix address list parsing

The parsing of port specifiers in the address list obtained from the DNS
resolution upcall doesn't work as in4_pton() and in6_pton() will fail on
encountering an unexpected delimiter (in this case, the '+' marking the
port number).  However, in*_pton() can't be given multiple specifiers.

Fix this by finding the delimiter in advance and not relying on in*_pton()
to find the end of the address for us.

Fixes: 8b2a464c ("afs: Add an address list concept")
Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
parent b61f7dcf
...@@ -121,7 +121,7 @@ struct afs_addr_list *afs_parse_text_addrs(const char *text, size_t len, ...@@ -121,7 +121,7 @@ struct afs_addr_list *afs_parse_text_addrs(const char *text, size_t len,
p = text; p = text;
do { do {
struct sockaddr_rxrpc *srx = &alist->addrs[alist->nr_addrs]; struct sockaddr_rxrpc *srx = &alist->addrs[alist->nr_addrs];
char tdelim = delim; const char *q, *stop;
if (*p == delim) { if (*p == delim) {
p++; p++;
...@@ -130,28 +130,33 @@ struct afs_addr_list *afs_parse_text_addrs(const char *text, size_t len, ...@@ -130,28 +130,33 @@ struct afs_addr_list *afs_parse_text_addrs(const char *text, size_t len,
if (*p == '[') { if (*p == '[') {
p++; p++;
tdelim = ']'; q = memchr(p, ']', end - p);
} else {
for (q = p; q < end; q++)
if (*q == '+' || *q == delim)
break;
} }
if (in4_pton(p, end - p, if (in4_pton(p, q - p,
(u8 *)&srx->transport.sin6.sin6_addr.s6_addr32[3], (u8 *)&srx->transport.sin6.sin6_addr.s6_addr32[3],
tdelim, &p)) { -1, &stop)) {
srx->transport.sin6.sin6_addr.s6_addr32[0] = 0; srx->transport.sin6.sin6_addr.s6_addr32[0] = 0;
srx->transport.sin6.sin6_addr.s6_addr32[1] = 0; srx->transport.sin6.sin6_addr.s6_addr32[1] = 0;
srx->transport.sin6.sin6_addr.s6_addr32[2] = htonl(0xffff); srx->transport.sin6.sin6_addr.s6_addr32[2] = htonl(0xffff);
} else if (in6_pton(p, end - p, } else if (in6_pton(p, q - p,
srx->transport.sin6.sin6_addr.s6_addr, srx->transport.sin6.sin6_addr.s6_addr,
tdelim, &p)) { -1, &stop)) {
/* Nothing to do */ /* Nothing to do */
} else { } else {
goto bad_address; goto bad_address;
} }
if (tdelim == ']') { if (stop != q)
if (p == end || *p != ']') goto bad_address;
goto bad_address;
p = q;
if (q < end && *q == ']')
p++; p++;
}
if (p < end) { if (p < end) {
if (*p == '+') { if (*p == '+') {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment