Line data Source code
1 : #ifndef HEADER_fd_src_util_net_fd_ip6_h 2 : #define HEADER_fd_src_util_net_fd_ip6_h 3 : 4 : #include "../bits/fd_bits.h" 5 : 6 : /* IPv6 address with an optional scope. */ 7 : 8 : struct fd_ip6_addr { 9 : uchar addr[ 16 ]; 10 : uint scope_id; /* 0 implies global */ 11 : }; 12 : 13 : typedef struct fd_ip6_addr fd_ip6_addr_t; 14 : 15 : FD_PROTOTYPES_BEGIN 16 : 17 : static inline void 18 : fd_ip6_addr_ip4_mapped( uchar ip6_addr[16], 19 45 : uint const ip4_addr ) { 20 45 : memset( ip6_addr, 0, 10 ); 21 45 : ip6_addr[ 10 ] = (uchar)0xff; 22 45 : ip6_addr[ 11 ] = (uchar)0xff; 23 45 : memcpy( ip6_addr+12, &ip4_addr, 4 ); 24 45 : } 25 : 26 : static inline int 27 339 : fd_ip6_addr_is_ip4_mapped( uchar const ip6_addr[16] ) { 28 339 : return ( 29 339 : (ip6_addr[ 0 ]==0x00) & (ip6_addr[ 1 ]==0x00) & 30 339 : (ip6_addr[ 2 ]==0x00) & (ip6_addr[ 3 ]==0x00) & 31 339 : (ip6_addr[ 4 ]==0x00) & (ip6_addr[ 5 ]==0x00) & 32 339 : (ip6_addr[ 6 ]==0x00) & (ip6_addr[ 7 ]==0x00) & 33 339 : (ip6_addr[ 8 ]==0x00) & (ip6_addr[ 9 ]==0x00) & 34 339 : (ip6_addr[ 10 ]==0xff) & (ip6_addr[ 11 ]==0xff) 35 339 : ); 36 339 : } 37 : 38 : static inline uint 39 42 : fd_ip6_addr_to_ip4( uchar const ip6_addr[16] ) { 40 42 : uint ip4_addr; 41 42 : memcpy( &ip4_addr, ip6_addr+12, 4 ); 42 42 : return ip4_addr; 43 42 : } 44 : 45 : /* fd_ip6_addr_is_unspecified returns 1 if the given address is the 46 : wildcard address (::), otherwise 0. Binding a socket to the wildcard 47 : address listens on all addresses of all interfaces (both IPv6 and, 48 : unless IPV6_V6ONLY is set, IPv4). */ 49 : 50 : static inline int 51 57 : fd_ip6_addr_is_unspecified( uchar const ip6_addr[16] ) { 52 57 : ulong hi, lo; 53 57 : memcpy( &hi, ip6_addr, 8 ); 54 57 : memcpy( &lo, ip6_addr+8, 8 ); 55 57 : return !(hi|lo); 56 57 : } 57 : 58 : /* fd_ip6_addr_is_scoped returns 1 if the given address has a scope 59 : narrower than global, i.e. a zone ID is required to identify which 60 : interface the address belongs to. These are the link-local unicast 61 : addresses (fe80::/10) and the multicast addresses with a scope field 62 : below 'global' (ff00::/8 with the low nibble of byte 1 <0xe). */ 63 : 64 : static inline int 65 57 : fd_ip6_addr_is_scoped( uchar const ip6_addr[16] ) { 66 57 : int link_local = (ip6_addr[0]==0xfe) & ((ip6_addr[1]&0xc0)==0x80); 67 57 : int multicast = (ip6_addr[0]==0xff) & ((ip6_addr[1]&0x0f)< 0x0e); 68 57 : return link_local | multicast; 69 57 : } 70 : 71 : /* fd_cstr_to_ip6_addr parses an IPv6 address literal (RFC 4291), with 72 : an optional zone ID suffix (RFC 4007) naming the interface that the 73 : address belongs to. The zone ID is either an interface name or a 74 : numeric interface index, e.g. "fe80::1%eth0" or "fe80::1%2". 75 : 76 : On success, stores the address to out and returns 1. On failure, 77 : returns 0 and leaves out untouched. Fails if a zone ID is given for 78 : an address that is not scoped, or names an interface that does not 79 : exist. 80 : 81 : Calls libc if_nametoindex (requires ioctl/Netlink access). */ 82 : 83 : int 84 : fd_cstr_to_ip6_addr( char const * s, 85 : fd_ip6_addr_t * out ); 86 : 87 : /* fd_cstr_to_ip46_addr is like fd_cstr_to_ip6_addr, but additionally 88 : accepts an IPv4 address literal, which is stored as an IPv4-mapped 89 : IPv6 address (::ffff:a.b.c.d). Note that the IPv4 wildcard address 90 : (0.0.0.0) maps to ::ffff:0.0.0.0. 91 : 92 : Calls libc if_nametoindex (requires ioctl/Netlink access). */ 93 : 94 : int 95 : fd_cstr_to_ip46_addr( char const * s, 96 : fd_ip6_addr_t * out ); 97 : 98 : /* FD_IP6_ADDR_CSTR_MAX is the buffer size required by 99 : fd_ip6_addr_cstr. */ 100 : 101 : #define FD_IP6_ADDR_CSTR_MAX (80UL) 102 : 103 : /* fd_ip6_addr_cstr pretty prints an address for use as the host part of 104 : an URL, in the canonical text representation (RFC 5952). IPv4-mapped 105 : addresses without a zone ID print as an IPv4 dotted quad (1.2.3.4), 106 : all others print bracketed, with a numeric zone ID suffix if the 107 : address is scoped (e.g. [fe80::1%2]). Returns buf. */ 108 : 109 : char * 110 : fd_ip6_addr_cstr( char buf[ static FD_IP6_ADDR_CSTR_MAX ], 111 : fd_ip6_addr_t const * addr ); 112 : 113 : #define FD_IP6_ADDR_CSTR( name, addr ) \ 114 0 : char name[ FD_IP6_ADDR_CSTR_MAX ]; fd_ip6_addr_cstr( name, (addr) ) 115 : 116 : FD_PROTOTYPES_END 117 : 118 : #endif /* HEADER_fd_src_util_net_fd_ip6_h */