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