xref: /linux-6.15/include/linux/sunrpc/addr.h (revision b2441318)
1*b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */
25976687aSJeff Layton /*
35976687aSJeff Layton  * linux/include/linux/sunrpc/addr.h
45976687aSJeff Layton  *
55976687aSJeff Layton  * Various routines for copying and comparing sockaddrs and for
65976687aSJeff Layton  * converting them to and from presentation format.
75976687aSJeff Layton  */
85976687aSJeff Layton #ifndef _LINUX_SUNRPC_ADDR_H
95976687aSJeff Layton #define _LINUX_SUNRPC_ADDR_H
105976687aSJeff Layton 
115976687aSJeff Layton #include <linux/socket.h>
125976687aSJeff Layton #include <linux/in.h>
135976687aSJeff Layton #include <linux/in6.h>
145976687aSJeff Layton #include <net/ipv6.h>
155976687aSJeff Layton 
165976687aSJeff Layton size_t		rpc_ntop(const struct sockaddr *, char *, const size_t);
175976687aSJeff Layton size_t		rpc_pton(struct net *, const char *, const size_t,
185976687aSJeff Layton 			 struct sockaddr *, const size_t);
195976687aSJeff Layton char *		rpc_sockaddr2uaddr(const struct sockaddr *, gfp_t);
205976687aSJeff Layton size_t		rpc_uaddr2sockaddr(struct net *, const char *, const size_t,
215976687aSJeff Layton 				   struct sockaddr *, const size_t);
225976687aSJeff Layton 
rpc_get_port(const struct sockaddr * sap)235976687aSJeff Layton static inline unsigned short rpc_get_port(const struct sockaddr *sap)
245976687aSJeff Layton {
255976687aSJeff Layton 	switch (sap->sa_family) {
265976687aSJeff Layton 	case AF_INET:
275976687aSJeff Layton 		return ntohs(((struct sockaddr_in *)sap)->sin_port);
285976687aSJeff Layton 	case AF_INET6:
295976687aSJeff Layton 		return ntohs(((struct sockaddr_in6 *)sap)->sin6_port);
305976687aSJeff Layton 	}
315976687aSJeff Layton 	return 0;
325976687aSJeff Layton }
335976687aSJeff Layton 
rpc_set_port(struct sockaddr * sap,const unsigned short port)345976687aSJeff Layton static inline void rpc_set_port(struct sockaddr *sap,
355976687aSJeff Layton 				const unsigned short port)
365976687aSJeff Layton {
375976687aSJeff Layton 	switch (sap->sa_family) {
385976687aSJeff Layton 	case AF_INET:
395976687aSJeff Layton 		((struct sockaddr_in *)sap)->sin_port = htons(port);
405976687aSJeff Layton 		break;
415976687aSJeff Layton 	case AF_INET6:
425976687aSJeff Layton 		((struct sockaddr_in6 *)sap)->sin6_port = htons(port);
435976687aSJeff Layton 		break;
445976687aSJeff Layton 	}
455976687aSJeff Layton }
465976687aSJeff Layton 
475976687aSJeff Layton #define IPV6_SCOPE_DELIMITER		'%'
485976687aSJeff Layton #define IPV6_SCOPE_ID_LEN		sizeof("%nnnnnnnnnn")
495976687aSJeff Layton 
rpc_cmp_addr4(const struct sockaddr * sap1,const struct sockaddr * sap2)507b0ce60cSAnna Schumaker static inline bool rpc_cmp_addr4(const struct sockaddr *sap1,
515976687aSJeff Layton 				 const struct sockaddr *sap2)
525976687aSJeff Layton {
535976687aSJeff Layton 	const struct sockaddr_in *sin1 = (const struct sockaddr_in *)sap1;
545976687aSJeff Layton 	const struct sockaddr_in *sin2 = (const struct sockaddr_in *)sap2;
555976687aSJeff Layton 
565976687aSJeff Layton 	return sin1->sin_addr.s_addr == sin2->sin_addr.s_addr;
575976687aSJeff Layton }
585976687aSJeff Layton 
__rpc_copy_addr4(struct sockaddr * dst,const struct sockaddr * src)595976687aSJeff Layton static inline bool __rpc_copy_addr4(struct sockaddr *dst,
605976687aSJeff Layton 				    const struct sockaddr *src)
615976687aSJeff Layton {
625976687aSJeff Layton 	const struct sockaddr_in *ssin = (struct sockaddr_in *) src;
635976687aSJeff Layton 	struct sockaddr_in *dsin = (struct sockaddr_in *) dst;
645976687aSJeff Layton 
655976687aSJeff Layton 	dsin->sin_family = ssin->sin_family;
665976687aSJeff Layton 	dsin->sin_addr.s_addr = ssin->sin_addr.s_addr;
675976687aSJeff Layton 	return true;
685976687aSJeff Layton }
695976687aSJeff Layton 
705976687aSJeff Layton #if IS_ENABLED(CONFIG_IPV6)
rpc_cmp_addr6(const struct sockaddr * sap1,const struct sockaddr * sap2)717b0ce60cSAnna Schumaker static inline bool rpc_cmp_addr6(const struct sockaddr *sap1,
725976687aSJeff Layton 				 const struct sockaddr *sap2)
735976687aSJeff Layton {
745976687aSJeff Layton 	const struct sockaddr_in6 *sin1 = (const struct sockaddr_in6 *)sap1;
755976687aSJeff Layton 	const struct sockaddr_in6 *sin2 = (const struct sockaddr_in6 *)sap2;
765976687aSJeff Layton 
775976687aSJeff Layton 	if (!ipv6_addr_equal(&sin1->sin6_addr, &sin2->sin6_addr))
785976687aSJeff Layton 		return false;
795976687aSJeff Layton 	else if (ipv6_addr_type(&sin1->sin6_addr) & IPV6_ADDR_LINKLOCAL)
805976687aSJeff Layton 		return sin1->sin6_scope_id == sin2->sin6_scope_id;
815976687aSJeff Layton 
825976687aSJeff Layton 	return true;
835976687aSJeff Layton }
845976687aSJeff Layton 
__rpc_copy_addr6(struct sockaddr * dst,const struct sockaddr * src)855976687aSJeff Layton static inline bool __rpc_copy_addr6(struct sockaddr *dst,
865976687aSJeff Layton 				    const struct sockaddr *src)
875976687aSJeff Layton {
885976687aSJeff Layton 	const struct sockaddr_in6 *ssin6 = (const struct sockaddr_in6 *) src;
895976687aSJeff Layton 	struct sockaddr_in6 *dsin6 = (struct sockaddr_in6 *) dst;
905976687aSJeff Layton 
915976687aSJeff Layton 	dsin6->sin6_family = ssin6->sin6_family;
925976687aSJeff Layton 	dsin6->sin6_addr = ssin6->sin6_addr;
935976687aSJeff Layton 	dsin6->sin6_scope_id = ssin6->sin6_scope_id;
945976687aSJeff Layton 	return true;
955976687aSJeff Layton }
965976687aSJeff Layton #else	/* !(IS_ENABLED(CONFIG_IPV6) */
rpc_cmp_addr6(const struct sockaddr * sap1,const struct sockaddr * sap2)979fba8e30STrond Myklebust static inline bool rpc_cmp_addr6(const struct sockaddr *sap1,
985976687aSJeff Layton 				   const struct sockaddr *sap2)
995976687aSJeff Layton {
1005976687aSJeff Layton 	return false;
1015976687aSJeff Layton }
1025976687aSJeff Layton 
__rpc_copy_addr6(struct sockaddr * dst,const struct sockaddr * src)1035976687aSJeff Layton static inline bool __rpc_copy_addr6(struct sockaddr *dst,
1045976687aSJeff Layton 				    const struct sockaddr *src)
1055976687aSJeff Layton {
1065976687aSJeff Layton 	return false;
1075976687aSJeff Layton }
1085976687aSJeff Layton #endif	/* !(IS_ENABLED(CONFIG_IPV6) */
1095976687aSJeff Layton 
1105976687aSJeff Layton /**
1115976687aSJeff Layton  * rpc_cmp_addr - compare the address portion of two sockaddrs.
1125976687aSJeff Layton  * @sap1: first sockaddr
1135976687aSJeff Layton  * @sap2: second sockaddr
1145976687aSJeff Layton  *
1155976687aSJeff Layton  * Just compares the family and address portion. Ignores port, but
1165976687aSJeff Layton  * compares the scope if it's a link-local address.
1175976687aSJeff Layton  *
1185976687aSJeff Layton  * Returns true if the addrs are equal, false if they aren't.
1195976687aSJeff Layton  */
rpc_cmp_addr(const struct sockaddr * sap1,const struct sockaddr * sap2)1205976687aSJeff Layton static inline bool rpc_cmp_addr(const struct sockaddr *sap1,
1215976687aSJeff Layton 				const struct sockaddr *sap2)
1225976687aSJeff Layton {
1235976687aSJeff Layton 	if (sap1->sa_family == sap2->sa_family) {
1245976687aSJeff Layton 		switch (sap1->sa_family) {
1255976687aSJeff Layton 		case AF_INET:
1267b0ce60cSAnna Schumaker 			return rpc_cmp_addr4(sap1, sap2);
1275976687aSJeff Layton 		case AF_INET6:
1287b0ce60cSAnna Schumaker 			return rpc_cmp_addr6(sap1, sap2);
1295976687aSJeff Layton 		}
1305976687aSJeff Layton 	}
1315976687aSJeff Layton 	return false;
1325976687aSJeff Layton }
1335976687aSJeff Layton 
1345976687aSJeff Layton /**
13558cc8a55SAnna Schumaker  * rpc_cmp_addr_port - compare the address and port number of two sockaddrs.
13658cc8a55SAnna Schumaker  * @sap1: first sockaddr
13758cc8a55SAnna Schumaker  * @sap2: second sockaddr
13858cc8a55SAnna Schumaker  */
rpc_cmp_addr_port(const struct sockaddr * sap1,const struct sockaddr * sap2)13958cc8a55SAnna Schumaker static inline bool rpc_cmp_addr_port(const struct sockaddr *sap1,
14058cc8a55SAnna Schumaker 				     const struct sockaddr *sap2)
14158cc8a55SAnna Schumaker {
14258cc8a55SAnna Schumaker 	if (!rpc_cmp_addr(sap1, sap2))
14358cc8a55SAnna Schumaker 		return false;
14458cc8a55SAnna Schumaker 	return rpc_get_port(sap1) == rpc_get_port(sap2);
14558cc8a55SAnna Schumaker }
14658cc8a55SAnna Schumaker 
14758cc8a55SAnna Schumaker /**
1485976687aSJeff Layton  * rpc_copy_addr - copy the address portion of one sockaddr to another
1495976687aSJeff Layton  * @dst: destination sockaddr
1505976687aSJeff Layton  * @src: source sockaddr
1515976687aSJeff Layton  *
1525976687aSJeff Layton  * Just copies the address portion and family. Ignores port, scope, etc.
1535976687aSJeff Layton  * Caller is responsible for making certain that dst is large enough to hold
1545976687aSJeff Layton  * the address in src. Returns true if address family is supported. Returns
1555976687aSJeff Layton  * false otherwise.
1565976687aSJeff Layton  */
rpc_copy_addr(struct sockaddr * dst,const struct sockaddr * src)1575976687aSJeff Layton static inline bool rpc_copy_addr(struct sockaddr *dst,
1585976687aSJeff Layton 				 const struct sockaddr *src)
1595976687aSJeff Layton {
1605976687aSJeff Layton 	switch (src->sa_family) {
1615976687aSJeff Layton 	case AF_INET:
1625976687aSJeff Layton 		return __rpc_copy_addr4(dst, src);
1635976687aSJeff Layton 	case AF_INET6:
1645976687aSJeff Layton 		return __rpc_copy_addr6(dst, src);
1655976687aSJeff Layton 	}
1665976687aSJeff Layton 	return false;
1675976687aSJeff Layton }
1685976687aSJeff Layton 
1695976687aSJeff Layton /**
1705976687aSJeff Layton  * rpc_get_scope_id - return scopeid for a given sockaddr
1715976687aSJeff Layton  * @sa: sockaddr to get scopeid from
1725976687aSJeff Layton  *
1735976687aSJeff Layton  * Returns the value of the sin6_scope_id for AF_INET6 addrs, or 0 if
1745976687aSJeff Layton  * not an AF_INET6 address.
1755976687aSJeff Layton  */
rpc_get_scope_id(const struct sockaddr * sa)1765976687aSJeff Layton static inline u32 rpc_get_scope_id(const struct sockaddr *sa)
1775976687aSJeff Layton {
1785976687aSJeff Layton 	if (sa->sa_family != AF_INET6)
1795976687aSJeff Layton 		return 0;
1805976687aSJeff Layton 
1815976687aSJeff Layton 	return ((struct sockaddr_in6 *) sa)->sin6_scope_id;
1825976687aSJeff Layton }
1835976687aSJeff Layton 
1845976687aSJeff Layton #endif /* _LINUX_SUNRPC_ADDR_H */
185