addr.h (5063B)
1/* SPDX-License-Identifier: GPL-2.0 */ 2/* 3 * linux/include/linux/sunrpc/addr.h 4 * 5 * Various routines for copying and comparing sockaddrs and for 6 * converting them to and from presentation format. 7 */ 8#ifndef _LINUX_SUNRPC_ADDR_H 9#define _LINUX_SUNRPC_ADDR_H 10 11#include <linux/socket.h> 12#include <linux/in.h> 13#include <linux/in6.h> 14#include <net/ipv6.h> 15 16size_t rpc_ntop(const struct sockaddr *, char *, const size_t); 17size_t rpc_pton(struct net *, const char *, const size_t, 18 struct sockaddr *, const size_t); 19char * rpc_sockaddr2uaddr(const struct sockaddr *, gfp_t); 20size_t rpc_uaddr2sockaddr(struct net *, const char *, const size_t, 21 struct sockaddr *, const size_t); 22 23static inline unsigned short rpc_get_port(const struct sockaddr *sap) 24{ 25 switch (sap->sa_family) { 26 case AF_INET: 27 return ntohs(((struct sockaddr_in *)sap)->sin_port); 28 case AF_INET6: 29 return ntohs(((struct sockaddr_in6 *)sap)->sin6_port); 30 } 31 return 0; 32} 33 34static inline void rpc_set_port(struct sockaddr *sap, 35 const unsigned short port) 36{ 37 switch (sap->sa_family) { 38 case AF_INET: 39 ((struct sockaddr_in *)sap)->sin_port = htons(port); 40 break; 41 case AF_INET6: 42 ((struct sockaddr_in6 *)sap)->sin6_port = htons(port); 43 break; 44 } 45} 46 47#define IPV6_SCOPE_DELIMITER '%' 48#define IPV6_SCOPE_ID_LEN sizeof("%nnnnnnnnnn") 49 50static inline bool rpc_cmp_addr4(const struct sockaddr *sap1, 51 const struct sockaddr *sap2) 52{ 53 const struct sockaddr_in *sin1 = (const struct sockaddr_in *)sap1; 54 const struct sockaddr_in *sin2 = (const struct sockaddr_in *)sap2; 55 56 return sin1->sin_addr.s_addr == sin2->sin_addr.s_addr; 57} 58 59static inline bool __rpc_copy_addr4(struct sockaddr *dst, 60 const struct sockaddr *src) 61{ 62 const struct sockaddr_in *ssin = (struct sockaddr_in *) src; 63 struct sockaddr_in *dsin = (struct sockaddr_in *) dst; 64 65 dsin->sin_family = ssin->sin_family; 66 dsin->sin_addr.s_addr = ssin->sin_addr.s_addr; 67 return true; 68} 69 70#if IS_ENABLED(CONFIG_IPV6) 71static inline bool rpc_cmp_addr6(const struct sockaddr *sap1, 72 const struct sockaddr *sap2) 73{ 74 const struct sockaddr_in6 *sin1 = (const struct sockaddr_in6 *)sap1; 75 const struct sockaddr_in6 *sin2 = (const struct sockaddr_in6 *)sap2; 76 77 if (!ipv6_addr_equal(&sin1->sin6_addr, &sin2->sin6_addr)) 78 return false; 79 else if (ipv6_addr_type(&sin1->sin6_addr) & IPV6_ADDR_LINKLOCAL) 80 return sin1->sin6_scope_id == sin2->sin6_scope_id; 81 82 return true; 83} 84 85static inline bool __rpc_copy_addr6(struct sockaddr *dst, 86 const struct sockaddr *src) 87{ 88 const struct sockaddr_in6 *ssin6 = (const struct sockaddr_in6 *) src; 89 struct sockaddr_in6 *dsin6 = (struct sockaddr_in6 *) dst; 90 91 dsin6->sin6_family = ssin6->sin6_family; 92 dsin6->sin6_addr = ssin6->sin6_addr; 93 dsin6->sin6_scope_id = ssin6->sin6_scope_id; 94 return true; 95} 96#else /* !(IS_ENABLED(CONFIG_IPV6) */ 97static inline bool rpc_cmp_addr6(const struct sockaddr *sap1, 98 const struct sockaddr *sap2) 99{ 100 return false; 101} 102 103static inline bool __rpc_copy_addr6(struct sockaddr *dst, 104 const struct sockaddr *src) 105{ 106 return false; 107} 108#endif /* !(IS_ENABLED(CONFIG_IPV6) */ 109 110/** 111 * rpc_cmp_addr - compare the address portion of two sockaddrs. 112 * @sap1: first sockaddr 113 * @sap2: second sockaddr 114 * 115 * Just compares the family and address portion. Ignores port, but 116 * compares the scope if it's a link-local address. 117 * 118 * Returns true if the addrs are equal, false if they aren't. 119 */ 120static inline bool rpc_cmp_addr(const struct sockaddr *sap1, 121 const struct sockaddr *sap2) 122{ 123 if (sap1->sa_family == sap2->sa_family) { 124 switch (sap1->sa_family) { 125 case AF_INET: 126 return rpc_cmp_addr4(sap1, sap2); 127 case AF_INET6: 128 return rpc_cmp_addr6(sap1, sap2); 129 } 130 } 131 return false; 132} 133 134/** 135 * rpc_cmp_addr_port - compare the address and port number of two sockaddrs. 136 * @sap1: first sockaddr 137 * @sap2: second sockaddr 138 */ 139static inline bool rpc_cmp_addr_port(const struct sockaddr *sap1, 140 const struct sockaddr *sap2) 141{ 142 if (!rpc_cmp_addr(sap1, sap2)) 143 return false; 144 return rpc_get_port(sap1) == rpc_get_port(sap2); 145} 146 147/** 148 * rpc_copy_addr - copy the address portion of one sockaddr to another 149 * @dst: destination sockaddr 150 * @src: source sockaddr 151 * 152 * Just copies the address portion and family. Ignores port, scope, etc. 153 * Caller is responsible for making certain that dst is large enough to hold 154 * the address in src. Returns true if address family is supported. Returns 155 * false otherwise. 156 */ 157static inline bool rpc_copy_addr(struct sockaddr *dst, 158 const struct sockaddr *src) 159{ 160 switch (src->sa_family) { 161 case AF_INET: 162 return __rpc_copy_addr4(dst, src); 163 case AF_INET6: 164 return __rpc_copy_addr6(dst, src); 165 } 166 return false; 167} 168 169/** 170 * rpc_get_scope_id - return scopeid for a given sockaddr 171 * @sa: sockaddr to get scopeid from 172 * 173 * Returns the value of the sin6_scope_id for AF_INET6 addrs, or 0 if 174 * not an AF_INET6 address. 175 */ 176static inline u32 rpc_get_scope_id(const struct sockaddr *sa) 177{ 178 if (sa->sa_family != AF_INET6) 179 return 0; 180 181 return ((struct sockaddr_in6 *) sa)->sin6_scope_id; 182} 183 184#endif /* _LINUX_SUNRPC_ADDR_H */