1 /* 2 * Copyright (c) 2006-2021, RT-Thread Development Team 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 * 6 * Change Logs: 7 * Date Author Notes 8 * 2018-05-18 ChenYong First version 9 */ 10 11 #ifndef __NETDEV_IPADDR_H__ 12 #define __NETDEV_IPADDR_H__ 13 14 #include <stdint.h> 15 #include <rtconfig.h> 16 17 #ifdef __cplusplus 18 extern "C" { 19 #endif 20 21 /* 22 * Definitions of bits in internet address integers. 23 * On subnets, the decomposition of addresses to host and net parts 24 * is done according to subnet mask, not the masks here. 25 */ 26 #define IN_CLASSA(i) (((long)(i) & 0x80000000) == 0) 27 #define IN_CLASSA_NET 0xff000000 28 #define IN_CLASSA_NSHIFT 24 29 #define IN_CLASSA_HOST 0x00ffffff 30 #define IN_CLASSA_MAX 128 31 32 #define IN_CLASSB(i) (((long)(i) & 0xc0000000) == 0x80000000) 33 #define IN_CLASSB_NET 0xffff0000 34 #define IN_CLASSB_NSHIFT 16 35 #define IN_CLASSB_HOST 0x0000ffff 36 #define IN_CLASSB_MAX 65536 37 38 #define IN_CLASSC(i) (((long)(i) & 0xe0000000) == 0xc0000000) 39 #define IN_CLASSC_NET 0xffffff00 40 #define IN_CLASSC_NSHIFT 8 41 #define IN_CLASSC_HOST 0x000000ff 42 43 #define IN_CLASSD(i) (((long)(i) & 0xf0000000) == 0xe0000000) 44 #define IN_MULTICAST(i) IN_CLASSD(i) 45 46 #define IN_EXPERIMENTAL(i) (((long)(i) & 0xe0000000) == 0xe0000000) 47 #define IN_BADCLASS(i) (((long)(i) & 0xf0000000) == 0xf0000000) 48 49 #define IN_LOOPBACKNET 127 /* official! */ 50 51 /* IP address types for use in ip_addr_t.type member */ 52 enum netdev_ip_addr_type { 53 /** IPv4 */ 54 IPADDR_TYPE_V4 = 0U, 55 /** IPv6 */ 56 IPADDR_TYPE_V6 = 6U, 57 /** IPv4+IPv6 ("dual-stack") */ 58 IPADDR_TYPE_ANY = 46U 59 }; 60 61 #if NETDEV_IPV4 62 /** IPv4 only: set the IP address given as an u32_t */ 63 #define ip4_addr_set_u32(dest_ipaddr, src_u32) ((dest_ipaddr)->addr = (src_u32)) 64 /** IPv4 only: get the IP address as an u32_t */ 65 #define ip4_addr_get_u32(src_ipaddr) ((src_ipaddr)->addr) 66 67 #define IP4ADDR_STRLEN_MAX 16 68 #endif /* NETIF_IPV4 */ 69 70 /* These macros should be calculated by the preprocessor and are used 71 with compile-time constants only (so that there is no little-endian 72 overhead at runtime). */ 73 #define PP_HTONS(x) ((((x) & 0x00ffUL) << 8) | (((x) & 0xff00UL) >> 8)) 74 #define PP_NTOHS(x) PP_HTONS(x) 75 #define PP_HTONL(x) ((((x) & 0x000000ffUL) << 24) | \ 76 (((x) & 0x0000ff00UL) << 8) | \ 77 (((x) & 0x00ff0000UL) >> 8) | \ 78 (((x) & 0xff000000UL) >> 24)) 79 #define PP_NTOHL(x) PP_HTONL(x) 80 81 #define htons(x) (uint16_t)PP_HTONS(x) 82 #define ntohs(x) (uint16_t)PP_NTOHS(x) 83 #define htonl(x) (uint32_t)PP_HTONL(x) 84 #define ntohl(x) (uint32_t)PP_NTOHL(x) 85 86 /* If your port already typedef's in_addr_t, define IN_ADDR_T_DEFINED 87 to prevent this code from redefining it. */ 88 #if !defined(in_addr_t) && !defined(IN_ADDR_T_DEFINED) 89 typedef uint32_t in_addr_t; 90 #endif 91 92 #if NETDEV_IPV4 93 struct in_addr 94 { 95 in_addr_t s_addr; 96 }; 97 98 typedef struct ip4_addr 99 { 100 uint32_t addr; 101 } ip4_addr_t; 102 103 /** 255.255.255.255 */ 104 #define IPADDR_NONE ((uint32_t)0xffffffffUL) 105 /** 127.0.0.1 */ 106 #define IPADDR_LOOPBACK ((uint32_t)0x7f000001UL) 107 /** 0.0.0.0 */ 108 #define IPADDR_ANY ((uint32_t)0x00000000UL) 109 /** 255.255.255.255 */ 110 #define IPADDR_BROADCAST ((uint32_t)0xffffffffUL) 111 112 /** 255.255.255.255 */ 113 #define INADDR_NONE IPADDR_NONE 114 /** 127.0.0.1 */ 115 #define INADDR_LOOPBACK IPADDR_LOOPBACK 116 /** 0.0.0.0 */ 117 #define INADDR_ANY IPADDR_ANY 118 /** 255.255.255.255 */ 119 #define INADDR_BROADCAST IPADDR_BROADCAST 120 121 #define IPADDR_BROADCAST_STRING "255.255.255.255" 122 123 /** Copy IP address - faster than ip4_addr_set: no NULL check */ 124 #define ip4_addr_copy(dest, src) ((dest).addr = (src).addr) 125 #define ip4_addr_cmp(addr1, addr2) ((addr1)->addr == (addr2)->addr) 126 /** Safely copy one IP address to another (src may be NULL) */ 127 #define ip4_addr_set(dest, src) ((dest)->addr = ((src) == NULL ? 0 : (src)->addr)) 128 /** Set complete address to zero */ 129 #define ip4_addr_set_zero(ipaddr) ((ipaddr)->addr = 0) 130 /** Set address to IPADDR_ANY (no need for htonl()) */ 131 #define ip4_addr_set_any(ipaddr) ((ipaddr)->addr = IPADDR_ANY) 132 #define ip4_addr_isany_val(ipaddr) ((ipaddr).addr == IPADDR_ANY) 133 #define ip4_addr_isany(ipaddr) ((ipaddr) == NULL || ip4_addr_isany_val(*(ipaddr))) 134 135 in_addr_t netdev_ipaddr_addr(const char *cp); 136 int netdev_ip4addr_aton(const char *cp, ip4_addr_t *addr); 137 char *netdev_ip4addr_ntoa(const ip4_addr_t *addr); 138 char *netdev_ip4addr_ntoa_r(const ip4_addr_t *addr, char *buf, int buflen); 139 #endif /* NETIF_IPV4 */ 140 141 #if NETDEV_IPV6 142 struct in6_addr 143 { 144 union 145 { 146 uint32_t u32_addr[4]; 147 uint8_t u8_addr[16]; 148 } un; 149 #define s6_addr un.u8_addr 150 }; 151 152 typedef struct ip6_addr 153 { 154 uint32_t addr[4]; 155 #ifdef NETDEV_IPV6_SCOPES 156 uint8_t zone; 157 #endif /* NETDEV_IPV6_SCOPES */ 158 } ip6_addr_t; 159 160 /** This macro can be used to initialize a variable of type struct in6_addr 161 to the IPv6 wildcard address. */ 162 #define IN6ADDR_ANY_INIT {{{0,0,0,0}}} 163 /** This macro can be used to initialize a variable of type struct in6_addr 164 to the IPv6 loopback address. */ 165 #define IN6ADDR_LOOPBACK_INIT {{{0,0,0,PP_HTONL(1)}}} 166 167 /** This variable is initialized by the system to contain the wildcard IPv6 address. 168 */ 169 extern const struct in6_addr in6addr_any; 170 171 #define ip6_addr_cmp(addr1, addr2) (((addr1)->addr[0] == (addr2)->addr[0]) && \ 172 ((addr1)->addr[1] == (addr2)->addr[1]) && \ 173 ((addr1)->addr[2] == (addr2)->addr[2]) && \ 174 ((addr1)->addr[3] == (addr2)->addr[3])) 175 /** Copy IPv6 address - faster than ip6_addr_set: no NULL check */ 176 #define ip6_addr_copy(dest, src) do{(dest).addr[0] = (src).addr[0]; \ 177 (dest).addr[1] = (src).addr[1]; \ 178 (dest).addr[2] = (src).addr[2]; \ 179 (dest).addr[3] = (src).addr[3];}while(0) 180 /** Safely copy one IPv6 address to another (src may be NULL) */ 181 #define ip6_addr_set(dest, src) do{(dest)->addr[0] = (src) == NULL ? 0 : (src)->addr[0]; \ 182 (dest)->addr[1] = (src) == NULL ? 0 : (src)->addr[1]; \ 183 (dest)->addr[2] = (src) == NULL ? 0 : (src)->addr[2]; \ 184 (dest)->addr[3] = (src) == NULL ? 0 : (src)->addr[3];}while(0) 185 /** Set complete address to zero */ 186 #define ip6_addr_set_zero(ip6addr) do{(ip6addr)->addr[0] = 0; \ 187 (ip6addr)->addr[1] = 0; \ 188 (ip6addr)->addr[2] = 0; \ 189 (ip6addr)->addr[3] = 0;}while(0) 190 /** Set address to ipv6 'any' (no need for lwip_htonl()) */ 191 #define ip6_addr_set_any(ip6addr) ip6_addr_set_zero(ip6addr) 192 #define ip6_addr_isany_val(ip6addr) (((ip6addr).addr[0] == 0) && \ 193 ((ip6addr).addr[1] == 0) && \ 194 ((ip6addr).addr[2] == 0) && \ 195 ((ip6addr).addr[3] == 0)) 196 #define ip6_addr_isany(ip6addr) (((ip6addr) == NULL) || ip6_addr_isany_val(*(ip6addr))) 197 198 int netdev_ip6addr_aton(const char *cp, ip6_addr_t *addr); 199 char *netdev_ip6addr_ntoa(const ip6_addr_t *addr); 200 char *netdev_ip6addr_ntoa_r(const ip6_addr_t *addr, char *buf, int buflen); 201 #endif /* NETIF_IPV6 */ 202 203 #if NETDEV_IPV4 && NETDEV_IPV6 204 /* A union struct for both IP version's addresses */ 205 typedef struct _ip_addr 206 { 207 union 208 { 209 ip6_addr_t ip6; 210 ip4_addr_t ip4; 211 } u_addr; 212 /** @ref netdev_ip_addr_type */ 213 uint8_t type; 214 } ip_addr_t; 215 216 #define IP_SET_TYPE_VAL(ipaddr, iptype) do { (ipaddr).type = (iptype); }while(0) 217 #define IP_SET_TYPE(ipaddr, iptype) do { if((ipaddr) != NULL) { IP_SET_TYPE_VAL(*(ipaddr), iptype); }}while(0) 218 #define IP_GET_TYPE(ipaddr) ((ipaddr)->type) 219 220 #define IP_IS_V4_VAL(ipaddr) (IP_GET_TYPE(&ipaddr) == IPADDR_TYPE_V4) 221 #define IP_IS_V6_VAL(ipaddr) (IP_GET_TYPE(&ipaddr) == IPADDR_TYPE_V6) 222 #define IP_IS_V4(ipaddr) (((ipaddr) == NULL) || IP_IS_V4_VAL(*(ipaddr))) 223 #define IP_IS_V6(ipaddr) (((ipaddr) != NULL) && IP_IS_V6_VAL(*(ipaddr))) 224 225 /** Convert generic ip address to specific protocol version */ 226 #define ip_2_ip6(ipaddr) (&((ipaddr)->u_addr.ip6)) 227 /** Convert generic ip address to specific protocol version */ 228 #define ip_2_ip4(ipaddr) (&((ipaddr)->u_addr.ip4)) 229 230 #define ip_addr_copy(dest, src) do{ IP_SET_TYPE_VAL(dest, IP_GET_TYPE(&src)); if(IP_IS_V6_VAL(src)){ \ 231 ip6_addr_copy(*ip_2_ip6(&(dest)), *ip_2_ip6(&(src))); }else{ \ 232 ip4_addr_copy(*ip_2_ip4(&(dest)), *ip_2_ip4(&(src))); }}while(0) 233 #define ip_addr_cmp(addr1, addr2) ((IP_GET_TYPE(addr1) != IP_GET_TYPE(addr2)) ? 0 : (IP_IS_V6_VAL(*(addr1)) ? \ 234 ip6_addr_cmp(ip_2_ip6(addr1), ip_2_ip6(addr2)) : \ 235 ip4_addr_cmp(ip_2_ip4(addr1), ip_2_ip4(addr2)))) 236 #define ip_addr_set(dest, src) do{ IP_SET_TYPE(dest, IP_GET_TYPE(src)); if(IP_IS_V6(src)){ \ 237 ip6_addr_set(ip_2_ip6(dest), ip_2_ip6(src)); }else{ \ 238 ip4_addr_set(ip_2_ip4(dest), ip_2_ip4(src)); }}while(0) 239 #define ip_addr_set_zero(ipaddr) do{ ip6_addr_set_zero(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, 0); }while(0) 240 #define ip_addr_set_any(is_ipv6, ipaddr) do{ if(is_ipv6){ \ 241 ip6_addr_set_any(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V6); }else{ \ 242 ip4_addr_set_any(ip_2_ip4(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V4); }}while(0) 243 244 #define ip_addr_isany_val(ipaddr) ((IP_IS_V6_VAL(ipaddr)) ? \ 245 ip6_addr_isany_val(*ip_2_ip6(&(ipaddr))) : \ 246 ip4_addr_isany_val(*ip_2_ip4(&(ipaddr)))) 247 #define ip_addr_isany(ipaddr) ((IP_IS_V6(ipaddr)) ? \ 248 ip6_addr_isany(ip_2_ip6(ipaddr)) : \ 249 ip4_addr_isany(ip_2_ip4(ipaddr))) 250 251 /* directly map this to the lwip internal functions */ 252 #define inet_addr(cp) netdev_ipaddr_addr(cp) 253 #define inet_aton(cp, addr) ((IP_IS_V6_VAL(*addr)) ? \ 254 netdev_ip6addr_aton(cp, ip_2_ip6(addr)) : \ 255 netdev_ip4addr_aton(cp, ip_2_ip4(addr))) 256 #define inet_ntoa(addr) ((IP_IS_V6_VAL(addr)) ? \ 257 netdev_ip6addr_ntoa(ip_2_ip6(&addr)) : \ 258 netdev_ip4addr_ntoa(ip_2_ip4(&addr))) 259 #define inet_ntoa_r(addr, buf, buflen) ((IP_IS_V6_VAL(addr)) ? \ 260 netdev_ip6addr_ntoa_r(ip_2_ip6(&addr), buf, buflen) : \ 261 netdev_ip4addr_ntoa_r(ip_2_ip4(&addr), buf, buflen)) 262 #elif NETDEV_IPV4 /* NETDEV_IPV4 */ 263 264 typedef ip4_addr_t ip_addr_t; 265 266 #define IP_SET_TYPE_VAL(ipaddr, iptype) 267 #define IP_SET_TYPE(ipaddr, iptype) 268 #define IP_GET_TYPE(ipaddr) IPADDR_TYPE_V4 269 270 #define ip_addr_copy(dest, src) ip4_addr_copy(dest, src) 271 #define ip_addr_cmp(addr1, addr2) ip4_addr_cmp(addr1, addr2) 272 #define ip_addr_set(dest, src) ip4_addr_set(dest, src) 273 #define ip_addr_set_zero(ipaddr) ip4_addr_set_zero(ipaddr) 274 #define ip_addr_set_any(is_ipv6, ipaddr) ip4_addr_set_any(ipaddr) 275 #define ip_addr_isany_val(ipaddr) ip4_addr_isany_val(ipaddr) 276 #define ip_addr_isany(ipaddr) ip4_addr_isany(ipaddr) 277 278 /* directly map this to the lwip internal functions */ 279 #define inet_addr(cp) netdev_ipaddr_addr(cp) 280 #define inet_aton(cp, addr) netdev_ip4addr_aton(cp,(ip4_addr_t*)addr) 281 #define inet_ntoa(addr) netdev_ip4addr_ntoa((const ip4_addr_t*)&(addr)) 282 #define inet_ntoa_r(addr, buf, buflen) netdev_ip4addr_ntoa_r((const ip4_addr_t*)&(addr), buf, buflen) 283 #else /* NETDEV_IPV6 */ 284 285 typedef ip6_addr_t ip_addr_t; 286 287 #define IP_SET_TYPE_VAL(ipaddr, iptype) 288 #define IP_SET_TYPE(ipaddr, iptype) 289 #define IP_GET_TYPE(ipaddr) IPADDR_TYPE_V6 290 291 #define ip_addr_copy(dest, src) ip6_addr_copy(dest, src) 292 #define ip_addr_cmp(addr1, addr2) ip6_addr_cmp(addr1, addr2) 293 #define ip_addr_set(dest, src) ip6_addr_set(dest, src) 294 #define ip_addr_set_zero(ipaddr) ip6_addr_set_zero(ipaddr) 295 #define ip_addr_set_any(is_ipv6, ipaddr) ip6_addr_set_any(ipaddr) 296 #define ip_addr_isany_val(ipaddr) ip6_addr_isany_val(ipaddr) 297 #define ip_addr_isany(ipaddr) ip6_addr_isany(ipaddr) 298 299 /* directly map this to the lwip internal functions */ 300 #define inet_aton(cp, addr) netdev_ip6addr_aton(cp, (ip6_addr_t*)addr) 301 #define inet_ntoa(addr) netdev_ip6addr_ntoa((const ip6_addr_t*)&(addr)) 302 #define inet_ntoa_r(addr, buf, buflen) netdev_ip6addr_ntoa_r((const ip6_addr_t*)&(addr), buf, buflen) 303 #endif /* NTDEV_IPV4 && NTDEV_IPV6 */ 304 305 306 const char *netdev_inet_ntop(int af, const void *src, char *dst, int32_t size); 307 int netdev_inet_pton(int af, const char *src, void *dst); 308 309 #define inet_ntop(af, src, dst, size) netdev_inet_ntop(af, src, dst, size) 310 #define inet_pton(af, src, dst) netdev_inet_pton(af, src, dst) 311 312 #ifdef __cplusplus 313 } 314 #endif 315 316 #endif /* __NETDEV_IPADDR_H__ */ 317