^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright 2009, Oracle. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Convert socket addresses to presentation addresses and universal
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * addresses, and vice versa.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Universal addresses are introduced by RFC 1833 and further refined by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * recent RFCs describing NFSv4. The universal address format is part
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * of the external (network) interface provided by rpcbind version 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * and 4, and by NFSv4. Such an address is a string containing a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * presentation format IP address followed by a port number in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * "hibyte.lobyte" format.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * IPv6 addresses can also include a scope ID, typically denoted by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * a '%' followed by a device name or a non-negative integer. Refer to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * RFC 4291, Section 2.2 for details on IPv6 presentation formats.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <net/ipv6.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/sunrpc/addr.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/sunrpc/msg_prot.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #if IS_ENABLED(CONFIG_IPV6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) static size_t rpc_ntop6_noscopeid(const struct sockaddr *sap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) char *buf, const int buflen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) const struct in6_addr *addr = &sin6->sin6_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * RFC 4291, Section 2.2.2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * Shorthanded ANY address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) if (ipv6_addr_any(addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) return snprintf(buf, buflen, "::");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * RFC 4291, Section 2.2.2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * Shorthanded loopback address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) if (ipv6_addr_loopback(addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) return snprintf(buf, buflen, "::1");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) * RFC 4291, Section 2.2.3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) * Special presentation address format for mapped v4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) * addresses.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) if (ipv6_addr_v4mapped(addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) return snprintf(buf, buflen, "::ffff:%pI4",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) &addr->s6_addr32[3]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) * RFC 4291, Section 2.2.1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) return snprintf(buf, buflen, "%pI6c", addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) static size_t rpc_ntop6(const struct sockaddr *sap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) char *buf, const size_t buflen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) char scopebuf[IPV6_SCOPE_ID_LEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) size_t len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) len = rpc_ntop6_noscopeid(sap, buf, buflen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) if (unlikely(len == 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) if (!(ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) if (sin6->sin6_scope_id == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) rc = snprintf(scopebuf, sizeof(scopebuf), "%c%u",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) IPV6_SCOPE_DELIMITER, sin6->sin6_scope_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) if (unlikely((size_t)rc >= sizeof(scopebuf)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) len += rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) if (unlikely(len >= buflen))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) strcat(buf, scopebuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) #else /* !IS_ENABLED(CONFIG_IPV6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) static size_t rpc_ntop6_noscopeid(const struct sockaddr *sap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) char *buf, const int buflen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) static size_t rpc_ntop6(const struct sockaddr *sap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) char *buf, const size_t buflen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) #endif /* !IS_ENABLED(CONFIG_IPV6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) static int rpc_ntop4(const struct sockaddr *sap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) char *buf, const size_t buflen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) const struct sockaddr_in *sin = (struct sockaddr_in *)sap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) return snprintf(buf, buflen, "%pI4", &sin->sin_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) * rpc_ntop - construct a presentation address in @buf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) * @sap: socket address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) * @buf: construction area
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) * @buflen: size of @buf, in bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) * Plants a %NUL-terminated string in @buf and returns the length
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) * of the string, excluding the %NUL. Otherwise zero is returned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) size_t rpc_ntop(const struct sockaddr *sap, char *buf, const size_t buflen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) switch (sap->sa_family) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) case AF_INET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) return rpc_ntop4(sap, buf, buflen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) case AF_INET6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) return rpc_ntop6(sap, buf, buflen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) EXPORT_SYMBOL_GPL(rpc_ntop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) static size_t rpc_pton4(const char *buf, const size_t buflen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) struct sockaddr *sap, const size_t salen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) struct sockaddr_in *sin = (struct sockaddr_in *)sap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) u8 *addr = (u8 *)&sin->sin_addr.s_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) if (buflen > INET_ADDRSTRLEN || salen < sizeof(struct sockaddr_in))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) memset(sap, 0, sizeof(struct sockaddr_in));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) if (in4_pton(buf, buflen, addr, '\0', NULL) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) sin->sin_family = AF_INET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) return sizeof(struct sockaddr_in);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) #if IS_ENABLED(CONFIG_IPV6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) static int rpc_parse_scope_id(struct net *net, const char *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) const size_t buflen, const char *delim,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) struct sockaddr_in6 *sin6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) char p[IPV6_SCOPE_ID_LEN + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) size_t len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) u32 scope_id = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) struct net_device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) if ((buf + buflen) == delim)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) if (*delim != IPV6_SCOPE_DELIMITER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) if (!(ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) len = (buf + buflen) - delim - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) if (len > IPV6_SCOPE_ID_LEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) memcpy(p, delim + 1, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) p[len] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) dev = dev_get_by_name(net, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) if (dev != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) scope_id = dev->ifindex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) dev_put(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) if (kstrtou32(p, 10, &scope_id) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) sin6->sin6_scope_id = scope_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) static size_t rpc_pton6(struct net *net, const char *buf, const size_t buflen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) struct sockaddr *sap, const size_t salen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) u8 *addr = (u8 *)&sin6->sin6_addr.in6_u;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) const char *delim;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) if (buflen > (INET6_ADDRSTRLEN + IPV6_SCOPE_ID_LEN) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) salen < sizeof(struct sockaddr_in6))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) memset(sap, 0, sizeof(struct sockaddr_in6));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) if (in6_pton(buf, buflen, addr, IPV6_SCOPE_DELIMITER, &delim) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) if (!rpc_parse_scope_id(net, buf, buflen, delim, sin6))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) sin6->sin6_family = AF_INET6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) return sizeof(struct sockaddr_in6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) static size_t rpc_pton6(struct net *net, const char *buf, const size_t buflen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) struct sockaddr *sap, const size_t salen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) * rpc_pton - Construct a sockaddr in @sap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) * @net: applicable network namespace
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) * @buf: C string containing presentation format IP address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) * @buflen: length of presentation address in bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) * @sap: buffer into which to plant socket address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) * @salen: size of buffer in bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) * Returns the size of the socket address if successful; otherwise
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) * zero is returned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) * Plants a socket address in @sap and returns the size of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) * socket address, if successful. Returns zero if an error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) * occurred.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) size_t rpc_pton(struct net *net, const char *buf, const size_t buflen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) struct sockaddr *sap, const size_t salen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) for (i = 0; i < buflen; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) if (buf[i] == ':')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) return rpc_pton6(net, buf, buflen, sap, salen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) return rpc_pton4(buf, buflen, sap, salen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) EXPORT_SYMBOL_GPL(rpc_pton);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) * rpc_sockaddr2uaddr - Construct a universal address string from @sap.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) * @sap: socket address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) * @gfp_flags: allocation mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) * Returns a %NUL-terminated string in dynamically allocated memory;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) * otherwise NULL is returned if an error occurred. Caller must
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) * free the returned string.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) char *rpc_sockaddr2uaddr(const struct sockaddr *sap, gfp_t gfp_flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) char portbuf[RPCBIND_MAXUADDRPLEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) char addrbuf[RPCBIND_MAXUADDRLEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) unsigned short port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) switch (sap->sa_family) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) case AF_INET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) if (rpc_ntop4(sap, addrbuf, sizeof(addrbuf)) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) port = ntohs(((struct sockaddr_in *)sap)->sin_port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) case AF_INET6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) if (rpc_ntop6_noscopeid(sap, addrbuf, sizeof(addrbuf)) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) port = ntohs(((struct sockaddr_in6 *)sap)->sin6_port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) if (snprintf(portbuf, sizeof(portbuf),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) ".%u.%u", port >> 8, port & 0xff) > (int)sizeof(portbuf))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) if (strlcat(addrbuf, portbuf, sizeof(addrbuf)) > sizeof(addrbuf))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) return kstrdup(addrbuf, gfp_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) * rpc_uaddr2sockaddr - convert a universal address to a socket address.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) * @net: applicable network namespace
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) * @uaddr: C string containing universal address to convert
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) * @uaddr_len: length of universal address string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) * @sap: buffer into which to plant socket address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) * @salen: size of buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) * @uaddr does not have to be '\0'-terminated, but kstrtou8() and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) * rpc_pton() require proper string termination to be successful.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) * Returns the size of the socket address if successful; otherwise
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) * zero is returned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) size_t rpc_uaddr2sockaddr(struct net *net, const char *uaddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) const size_t uaddr_len, struct sockaddr *sap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) const size_t salen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) char *c, buf[RPCBIND_MAXUADDRLEN + sizeof('\0')];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) u8 portlo, porthi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) unsigned short port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) if (uaddr_len > RPCBIND_MAXUADDRLEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) memcpy(buf, uaddr, uaddr_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) buf[uaddr_len] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) c = strrchr(buf, '.');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) if (unlikely(c == NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) if (unlikely(kstrtou8(c + 1, 10, &portlo) != 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) *c = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) c = strrchr(buf, '.');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) if (unlikely(c == NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) if (unlikely(kstrtou8(c + 1, 10, &porthi) != 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) port = (unsigned short)((porthi << 8) | portlo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) *c = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) if (rpc_pton(net, buf, strlen(buf), sap, salen) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) switch (sap->sa_family) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) case AF_INET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) ((struct sockaddr_in *)sap)->sin_port = htons(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) return sizeof(struct sockaddr_in);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) case AF_INET6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) ((struct sockaddr_in6 *)sap)->sin6_port = htons(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) return sizeof(struct sockaddr_in6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) EXPORT_SYMBOL_GPL(rpc_uaddr2sockaddr);