0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020 #include <net/ipv6.h>
0021 #include <linux/sunrpc/addr.h>
0022 #include <linux/sunrpc/msg_prot.h>
0023 #include <linux/slab.h>
0024 #include <linux/export.h>
0025
0026 #if IS_ENABLED(CONFIG_IPV6)
0027
0028 static size_t rpc_ntop6_noscopeid(const struct sockaddr *sap,
0029 char *buf, const int buflen)
0030 {
0031 const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap;
0032 const struct in6_addr *addr = &sin6->sin6_addr;
0033
0034
0035
0036
0037
0038
0039 if (ipv6_addr_any(addr))
0040 return snprintf(buf, buflen, "::");
0041
0042
0043
0044
0045
0046
0047 if (ipv6_addr_loopback(addr))
0048 return snprintf(buf, buflen, "::1");
0049
0050
0051
0052
0053
0054
0055
0056 if (ipv6_addr_v4mapped(addr))
0057 return snprintf(buf, buflen, "::ffff:%pI4",
0058 &addr->s6_addr32[3]);
0059
0060
0061
0062
0063 return snprintf(buf, buflen, "%pI6c", addr);
0064 }
0065
0066 static size_t rpc_ntop6(const struct sockaddr *sap,
0067 char *buf, const size_t buflen)
0068 {
0069 const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap;
0070 char scopebuf[IPV6_SCOPE_ID_LEN];
0071 size_t len;
0072 int rc;
0073
0074 len = rpc_ntop6_noscopeid(sap, buf, buflen);
0075 if (unlikely(len == 0))
0076 return len;
0077
0078 if (!(ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL))
0079 return len;
0080 if (sin6->sin6_scope_id == 0)
0081 return len;
0082
0083 rc = snprintf(scopebuf, sizeof(scopebuf), "%c%u",
0084 IPV6_SCOPE_DELIMITER, sin6->sin6_scope_id);
0085 if (unlikely((size_t)rc >= sizeof(scopebuf)))
0086 return 0;
0087
0088 len += rc;
0089 if (unlikely(len >= buflen))
0090 return 0;
0091
0092 strcat(buf, scopebuf);
0093 return len;
0094 }
0095
0096 #else
0097
0098 static size_t rpc_ntop6_noscopeid(const struct sockaddr *sap,
0099 char *buf, const int buflen)
0100 {
0101 return 0;
0102 }
0103
0104 static size_t rpc_ntop6(const struct sockaddr *sap,
0105 char *buf, const size_t buflen)
0106 {
0107 return 0;
0108 }
0109
0110 #endif
0111
0112 static int rpc_ntop4(const struct sockaddr *sap,
0113 char *buf, const size_t buflen)
0114 {
0115 const struct sockaddr_in *sin = (struct sockaddr_in *)sap;
0116
0117 return snprintf(buf, buflen, "%pI4", &sin->sin_addr);
0118 }
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129 size_t rpc_ntop(const struct sockaddr *sap, char *buf, const size_t buflen)
0130 {
0131 switch (sap->sa_family) {
0132 case AF_INET:
0133 return rpc_ntop4(sap, buf, buflen);
0134 case AF_INET6:
0135 return rpc_ntop6(sap, buf, buflen);
0136 }
0137
0138 return 0;
0139 }
0140 EXPORT_SYMBOL_GPL(rpc_ntop);
0141
0142 static size_t rpc_pton4(const char *buf, const size_t buflen,
0143 struct sockaddr *sap, const size_t salen)
0144 {
0145 struct sockaddr_in *sin = (struct sockaddr_in *)sap;
0146 u8 *addr = (u8 *)&sin->sin_addr.s_addr;
0147
0148 if (buflen > INET_ADDRSTRLEN || salen < sizeof(struct sockaddr_in))
0149 return 0;
0150
0151 memset(sap, 0, sizeof(struct sockaddr_in));
0152
0153 if (in4_pton(buf, buflen, addr, '\0', NULL) == 0)
0154 return 0;
0155
0156 sin->sin_family = AF_INET;
0157 return sizeof(struct sockaddr_in);
0158 }
0159
0160 #if IS_ENABLED(CONFIG_IPV6)
0161 static int rpc_parse_scope_id(struct net *net, const char *buf,
0162 const size_t buflen, const char *delim,
0163 struct sockaddr_in6 *sin6)
0164 {
0165 char p[IPV6_SCOPE_ID_LEN + 1];
0166 size_t len;
0167 u32 scope_id = 0;
0168 struct net_device *dev;
0169
0170 if ((buf + buflen) == delim)
0171 return 1;
0172
0173 if (*delim != IPV6_SCOPE_DELIMITER)
0174 return 0;
0175
0176 if (!(ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL))
0177 return 0;
0178
0179 len = (buf + buflen) - delim - 1;
0180 if (len > IPV6_SCOPE_ID_LEN)
0181 return 0;
0182
0183 memcpy(p, delim + 1, len);
0184 p[len] = 0;
0185
0186 dev = dev_get_by_name(net, p);
0187 if (dev != NULL) {
0188 scope_id = dev->ifindex;
0189 dev_put(dev);
0190 } else {
0191 if (kstrtou32(p, 10, &scope_id) != 0)
0192 return 0;
0193 }
0194
0195 sin6->sin6_scope_id = scope_id;
0196 return 1;
0197 }
0198
0199 static size_t rpc_pton6(struct net *net, const char *buf, const size_t buflen,
0200 struct sockaddr *sap, const size_t salen)
0201 {
0202 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap;
0203 u8 *addr = (u8 *)&sin6->sin6_addr.in6_u;
0204 const char *delim;
0205
0206 if (buflen > (INET6_ADDRSTRLEN + IPV6_SCOPE_ID_LEN) ||
0207 salen < sizeof(struct sockaddr_in6))
0208 return 0;
0209
0210 memset(sap, 0, sizeof(struct sockaddr_in6));
0211
0212 if (in6_pton(buf, buflen, addr, IPV6_SCOPE_DELIMITER, &delim) == 0)
0213 return 0;
0214
0215 if (!rpc_parse_scope_id(net, buf, buflen, delim, sin6))
0216 return 0;
0217
0218 sin6->sin6_family = AF_INET6;
0219 return sizeof(struct sockaddr_in6);
0220 }
0221 #else
0222 static size_t rpc_pton6(struct net *net, const char *buf, const size_t buflen,
0223 struct sockaddr *sap, const size_t salen)
0224 {
0225 return 0;
0226 }
0227 #endif
0228
0229
0230
0231
0232
0233
0234
0235
0236
0237
0238
0239
0240
0241
0242
0243
0244 size_t rpc_pton(struct net *net, const char *buf, const size_t buflen,
0245 struct sockaddr *sap, const size_t salen)
0246 {
0247 unsigned int i;
0248
0249 for (i = 0; i < buflen; i++)
0250 if (buf[i] == ':')
0251 return rpc_pton6(net, buf, buflen, sap, salen);
0252 return rpc_pton4(buf, buflen, sap, salen);
0253 }
0254 EXPORT_SYMBOL_GPL(rpc_pton);
0255
0256
0257
0258
0259
0260
0261
0262
0263
0264
0265 char *rpc_sockaddr2uaddr(const struct sockaddr *sap, gfp_t gfp_flags)
0266 {
0267 char portbuf[RPCBIND_MAXUADDRPLEN];
0268 char addrbuf[RPCBIND_MAXUADDRLEN];
0269 unsigned short port;
0270
0271 switch (sap->sa_family) {
0272 case AF_INET:
0273 if (rpc_ntop4(sap, addrbuf, sizeof(addrbuf)) == 0)
0274 return NULL;
0275 port = ntohs(((struct sockaddr_in *)sap)->sin_port);
0276 break;
0277 case AF_INET6:
0278 if (rpc_ntop6_noscopeid(sap, addrbuf, sizeof(addrbuf)) == 0)
0279 return NULL;
0280 port = ntohs(((struct sockaddr_in6 *)sap)->sin6_port);
0281 break;
0282 default:
0283 return NULL;
0284 }
0285
0286 if (snprintf(portbuf, sizeof(portbuf),
0287 ".%u.%u", port >> 8, port & 0xff) > (int)sizeof(portbuf))
0288 return NULL;
0289
0290 if (strlcat(addrbuf, portbuf, sizeof(addrbuf)) > sizeof(addrbuf))
0291 return NULL;
0292
0293 return kstrdup(addrbuf, gfp_flags);
0294 }
0295
0296
0297
0298
0299
0300
0301
0302
0303
0304
0305
0306
0307
0308
0309
0310 size_t rpc_uaddr2sockaddr(struct net *net, const char *uaddr,
0311 const size_t uaddr_len, struct sockaddr *sap,
0312 const size_t salen)
0313 {
0314 char *c, buf[RPCBIND_MAXUADDRLEN + sizeof('\0')];
0315 u8 portlo, porthi;
0316 unsigned short port;
0317
0318 if (uaddr_len > RPCBIND_MAXUADDRLEN)
0319 return 0;
0320
0321 memcpy(buf, uaddr, uaddr_len);
0322
0323 buf[uaddr_len] = '\0';
0324 c = strrchr(buf, '.');
0325 if (unlikely(c == NULL))
0326 return 0;
0327 if (unlikely(kstrtou8(c + 1, 10, &portlo) != 0))
0328 return 0;
0329
0330 *c = '\0';
0331 c = strrchr(buf, '.');
0332 if (unlikely(c == NULL))
0333 return 0;
0334 if (unlikely(kstrtou8(c + 1, 10, &porthi) != 0))
0335 return 0;
0336
0337 port = (unsigned short)((porthi << 8) | portlo);
0338
0339 *c = '\0';
0340 if (rpc_pton(net, buf, strlen(buf), sap, salen) == 0)
0341 return 0;
0342
0343 switch (sap->sa_family) {
0344 case AF_INET:
0345 ((struct sockaddr_in *)sap)->sin_port = htons(port);
0346 return sizeof(struct sockaddr_in);
0347 case AF_INET6:
0348 ((struct sockaddr_in6 *)sap)->sin6_port = htons(port);
0349 return sizeof(struct sockaddr_in6);
0350 }
0351
0352 return 0;
0353 }
0354 EXPORT_SYMBOL_GPL(rpc_uaddr2sockaddr);