[PATCH v3] net/ceph/messenger: support IPv6 Link-Local with scope identifier
Max Kellermann <[email protected]> Wed, 8 Jul 2026 22:38:58 +0200
| Newsgroups | org.kernel.vger.ceph-devel,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
Implement ceph_pton() using inet_pton_with_scope(). This minimal patch preserves the ceph_pton() API and thus requires copying the parameter to a null-terminated string. Signed-off-by: Max Kellermann <[email protected]> --- v1->v2: - check "ipend" before dereferencing it v2->v3: - fix indentation - use the caller's network namespace instead of init_ns - stop parsing at the port separator Signed-off-by: Max Kellermann <[email protected]> --- net/ceph/messenger.c | 45 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 36 insertions(+), 9 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 34b3097b4c7b..21dfff074e7d 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -1221,19 +1221,46 @@ void ceph_addr_set_port(struct ceph_entity_addr *addr, int p) static int ceph_pton(const char *str, size_t len, struct ceph_entity_addr *addr, char delim, const char **ipend) { - memset(&addr->in_addr, 0, sizeof(addr->in_addr)); + const char *delim_p; + char *copy; + struct sockaddr_storage stor = { 0 }; + int ret; - if (in4_pton(str, len, (u8 *)&((struct sockaddr_in *)&addr->in_addr)->sin_addr.s_addr, delim, ipend)) { - put_unaligned(AF_INET, &addr->in_addr.ss_family); - return 0; - } + delim_p = memchr(str, delim, len); + if (delim_p) + /* delimiter was found - stop parsing there */ + len = delim_p - str; - if (in6_pton(str, len, (u8 *)&((struct sockaddr_in6 *)&addr->in_addr)->sin6_addr.s6_addr, delim, ipend)) { - put_unaligned(AF_INET6, &addr->in_addr.ss_family); - return 0; + delim_p = memchr(str, ':', len); + if (delim_p && !memchr(delim_p + 1, ':', str + len - delim_p - 1)) + /* a single colon was found - stop parsing there + * because the caller wants to parse the port + * number + */ + len = delim_p - str; + + /* the input string might not be null terminated, so copy it + * to a null-terminated string + */ + copy = kstrndup(str, len, GFP_NOFS); + if (!copy) + return -ENOMEM; + + ret = inet_pton_with_scope(current->nsproxy->net_ns, AF_UNSPEC, copy, NULL, &stor); + kfree(copy); + + if (!ret) { + /* ceph_entity_addr might be misaligned, so we have to + * parse to a stack variable first + */ + memcpy(&addr->in_addr, &stor, sizeof(stor)); + + /* return the end of the parsed portion to the caller on success */ + if (ipend) + *ipend = str + len; } - return -EINVAL; + return ret; } /* -- 2.47.3