[PATCH v2] net/ceph/messenger: support IPv6 Link-Local with scope identifier
Max Kellermann <[email protected]> Mon, 6 Jul 2026 09:44:02 +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 --- net/ceph/messenger.c | 37 ++++++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 34b3097b4c7b..f7c7179589af 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -1221,19 +1221,38 @@ 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; + /* 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(&init_net, 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